feat(core): add nx console messaging to TUI (#31148)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> There is no communication between Nx CLI and Nx Console ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> This enables a connection between the Nx TUI app and Nx Console so that we can send messages to console. This is used to update MCP tools on Nx Console to assist with LLMs ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
47b9b51dd3
commit
81ecb22abe
3
.gitignore
vendored
3
.gitignore
vendored
@ -72,3 +72,6 @@ storybook-static
|
|||||||
# Ignore Gradle project-specific cache directory
|
# Ignore Gradle project-specific cache directory
|
||||||
.gradle
|
.gradle
|
||||||
.kotlin
|
.kotlin
|
||||||
|
|
||||||
|
.cursor/rules/nx-rules.mdc
|
||||||
|
.github/instructions/nx.instructions.md
|
||||||
546
Cargo.lock
generated
546
Cargo.lock
generated
@ -188,6 +188,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3"
|
checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-waker"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -377,6 +383,12 @@ dependencies = [
|
|||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cesu8"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cexpr"
|
name = "cexpr"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -469,6 +481,16 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "combine"
|
||||||
|
version = "4.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "command-group"
|
name = "command-group"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
@ -525,6 +547,16 @@ dependencies = [
|
|||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
@ -720,6 +752,12 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "doctest-file"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "document-features"
|
name = "document-features"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@ -850,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d"
|
checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -860,7 +898,7 @@ version = "0.8.3"
|
|||||||
source = "git+https://github.com/cammisuli/wezterm?rev=b538ee29e1e89eeb4832fb35ae095564dce34c29#b538ee29e1e89eeb4832fb35ae095564dce34c29"
|
source = "git+https://github.com/cammisuli/wezterm?rev=b538ee29e1e89eeb4832fb35ae095564dce34c29#b538ee29e1e89eeb4832fb35ae095564dce34c29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1020,6 +1058,12 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@ -1096,8 +1140,8 @@ dependencies = [
|
|||||||
"btoi",
|
"btoi",
|
||||||
"gix-date",
|
"gix-date",
|
||||||
"itoa",
|
"itoa",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"winnow",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1116,9 +1160,9 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"unicode-bom",
|
"unicode-bom",
|
||||||
"winnow",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1131,7 +1175,7 @@ dependencies = [
|
|||||||
"bstr",
|
"bstr",
|
||||||
"gix-path",
|
"gix-path",
|
||||||
"libc",
|
"libc",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1142,7 +1186,7 @@ checksum = "180b130a4a41870edfbd36ce4169c7090bca70e195da783dea088dd973daa59c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"itoa",
|
"itoa",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"time",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1188,7 +1232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0"
|
checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"faster-hex",
|
"faster-hex",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1199,7 +1243,7 @@ checksum = "7e5c65e6a29830a435664891ced3f3c1af010f14900226019590ee0971a22f37"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"gix-tempfile",
|
"gix-tempfile",
|
||||||
"gix-utils",
|
"gix-utils",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1217,8 +1261,8 @@ dependencies = [
|
|||||||
"gix-validate",
|
"gix-validate",
|
||||||
"itoa",
|
"itoa",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"winnow",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1231,7 +1275,7 @@ dependencies = [
|
|||||||
"gix-trace",
|
"gix-trace",
|
||||||
"home",
|
"home",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1251,8 +1295,8 @@ dependencies = [
|
|||||||
"gix-tempfile",
|
"gix-tempfile",
|
||||||
"gix-validate",
|
"gix-validate",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"winnow",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1303,7 +1347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545"
|
checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1336,6 +1380,25 @@ dependencies = [
|
|||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.4.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-waker",
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"http",
|
||||||
|
"indexmap",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -1383,12 +1446,6 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.9"
|
version = "0.5.9"
|
||||||
@ -1447,6 +1504,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
@ -1467,6 +1525,7 @@ dependencies = [
|
|||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
|
"log",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -1564,7 +1623,7 @@ dependencies = [
|
|||||||
"miette",
|
"miette",
|
||||||
"project-origins",
|
"project-origins",
|
||||||
"radix_trie",
|
"radix_trie",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -1583,7 +1642,7 @@ dependencies = [
|
|||||||
"normalize-path",
|
"normalize-path",
|
||||||
"project-origins",
|
"project-origins",
|
||||||
"radix_trie",
|
"radix_trie",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -1607,6 +1666,16 @@ version = "0.3.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.15.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indoc"
|
name = "indoc"
|
||||||
version = "2.0.6"
|
version = "2.0.6"
|
||||||
@ -1635,14 +1704,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "insta"
|
name = "insta"
|
||||||
version = "1.42.2"
|
version = "1.43.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50259abbaa67d11d2bcafc7ba1d094ed7a0c70e3ce893f0d0997f73558cb3084"
|
checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console",
|
"console",
|
||||||
"linked-hash-map",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pin-project",
|
|
||||||
"similar",
|
"similar",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1659,6 +1726,21 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interprocess"
|
||||||
|
version = "2.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d"
|
||||||
|
dependencies = [
|
||||||
|
"doctest-file",
|
||||||
|
"futures-core",
|
||||||
|
"libc",
|
||||||
|
"recvmsg",
|
||||||
|
"tokio",
|
||||||
|
"widestring",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ioctl-rs"
|
name = "ioctl-rs"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -1710,6 +1792,28 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
|
||||||
|
dependencies = [
|
||||||
|
"cesu8",
|
||||||
|
"cfg-if",
|
||||||
|
"combine",
|
||||||
|
"jni-sys",
|
||||||
|
"log",
|
||||||
|
"thiserror 1.0.58",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jni-sys"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -1726,6 +1830,92 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16"
|
||||||
|
dependencies = [
|
||||||
|
"jsonrpsee-core",
|
||||||
|
"jsonrpsee-http-client",
|
||||||
|
"jsonrpsee-proc-macros",
|
||||||
|
"jsonrpsee-types",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-core"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"futures-timer",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"jsonrpsee-types",
|
||||||
|
"pin-project",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tower",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-http-client"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6962d2bd295f75e97dd328891e58fce166894b974c1f7ce2e7597f02eeceb791"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"http-body",
|
||||||
|
"hyper",
|
||||||
|
"hyper-rustls",
|
||||||
|
"hyper-util",
|
||||||
|
"jsonrpsee-core",
|
||||||
|
"jsonrpsee-types",
|
||||||
|
"rustls",
|
||||||
|
"rustls-platform-verifier",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tower",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-proc-macros"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fa4f5daed39f982a1bb9d15449a28347490ad42b212f8eaa2a2a344a0dce9e9"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-types"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kqueue"
|
name = "kqueue"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
@ -1785,12 +1975,6 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked-hash-map"
|
|
||||||
version = "0.5.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@ -1887,7 +2071,7 @@ checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"miette-derive",
|
"miette-derive",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"unicode-width 0.1.11",
|
"unicode-width 0.1.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2159,16 +2343,6 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_threads"
|
name = "num_threads"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -2201,7 +2375,9 @@ dependencies = [
|
|||||||
"ignore",
|
"ignore",
|
||||||
"ignore-files 2.1.0",
|
"ignore-files 2.1.0",
|
||||||
"insta",
|
"insta",
|
||||||
|
"interprocess",
|
||||||
"itertools 0.10.5",
|
"itertools 0.10.5",
|
||||||
|
"jsonrpsee",
|
||||||
"machine-uid",
|
"machine-uid",
|
||||||
"mio 1.0.3",
|
"mio 1.0.3",
|
||||||
"napi",
|
"napi",
|
||||||
@ -2219,6 +2395,8 @@ dependencies = [
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"rkyv",
|
"rkyv",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
"swc_ecma_ast",
|
"swc_ecma_ast",
|
||||||
"swc_ecma_dep_graph",
|
"swc_ecma_dep_graph",
|
||||||
@ -2228,7 +2406,7 @@ dependencies = [
|
|||||||
"tar",
|
"tar",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"terminal-colorsaurus",
|
"terminal-colorsaurus",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -2236,6 +2414,7 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tui-logger",
|
"tui-logger",
|
||||||
"tui-term 0.2.0 (git+https://github.com/JamesHenry/tui-term?rev=88e3b61425c97220c528ef76c188df10032a75dd)",
|
"tui-term 0.2.0 (git+https://github.com/JamesHenry/tui-term?rev=88e3b61425c97220c528ef76c188df10032a75dd)",
|
||||||
|
"uuid",
|
||||||
"vt100-ctt",
|
"vt100-ctt",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"watchexec",
|
"watchexec",
|
||||||
@ -2332,6 +2511,12 @@ version = "1.21.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -2524,6 +2709,15 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
|
||||||
|
dependencies = [
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.94"
|
version = "1.0.94"
|
||||||
@ -2592,7 +2786,7 @@ dependencies = [
|
|||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -2609,7 +2803,7 @@ dependencies = [
|
|||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
"rustls",
|
"rustls",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -2754,6 +2948,12 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "recvmsg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -2962,10 +3162,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.25"
|
version = "0.23.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c"
|
checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ring",
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@ -2974,6 +3175,18 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-native-certs"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
|
||||||
|
dependencies = [
|
||||||
|
"openssl-probe",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls-pemfile"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@ -2990,10 +3203,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-platform-verifier"
|
||||||
version = "0.103.1"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
|
checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"jni",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"rustls",
|
||||||
|
"rustls-native-certs",
|
||||||
|
"rustls-platform-verifier-android",
|
||||||
|
"rustls-webpki",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"webpki-root-certs 0.26.11",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-platform-verifier-android"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.103.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@ -3021,6 +3261,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -3039,6 +3288,29 @@ version = "4.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "3.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.0",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.22"
|
version = "1.0.22"
|
||||||
@ -3047,18 +3319,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.197"
|
version = "1.0.219"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.197"
|
version = "1.0.219"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3624,7 +3896,16 @@ version = "1.0.58"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
|
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl 1.0.58",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 2.0.12",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3638,6 +3919,17 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.100",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
@ -3709,27 +4001,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.38.0"
|
version = "1.44.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio 0.8.11",
|
"mio 1.0.3",
|
||||||
"num_cpus",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.3.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3770,6 +4061,23 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow 0.7.10",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@ -3816,7 +4124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
|
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"time",
|
"time",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
@ -4029,6 +4337,9 @@ name = "uuid"
|
|||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.2.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
@ -4205,7 +4516,7 @@ dependencies = [
|
|||||||
"notify",
|
"notify",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"project-origins",
|
"project-origins",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"watchexec-events",
|
"watchexec-events",
|
||||||
@ -4248,7 +4559,7 @@ checksum = "af0a778522cf0fc2fa8a8f1380e32893208cb2e7fd33e64de8bd81a00a2a7838"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"miette",
|
"miette",
|
||||||
"nix 0.27.1",
|
"nix 0.27.1",
|
||||||
"thiserror",
|
"thiserror 1.0.58",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4276,6 +4587,24 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-root-certs"
|
||||||
|
version = "0.26.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e"
|
||||||
|
dependencies = [
|
||||||
|
"webpki-root-certs 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-root-certs"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01a83f7e1a9f8712695c03eabe9ed3fbca0feff0152f33f12593e5a6303cb1a4"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.26.8"
|
version = "0.26.8"
|
||||||
@ -4303,6 +4632,12 @@ dependencies = [
|
|||||||
"rustix 0.38.38",
|
"rustix 0.38.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -4422,6 +4757,15 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.45.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
@ -4449,6 +4793,21 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.42.2",
|
||||||
|
"windows_aarch64_msvc 0.42.2",
|
||||||
|
"windows_i686_gnu 0.42.2",
|
||||||
|
"windows_i686_msvc 0.42.2",
|
||||||
|
"windows_x86_64_gnu 0.42.2",
|
||||||
|
"windows_x86_64_gnullvm 0.42.2",
|
||||||
|
"windows_x86_64_msvc 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4496,6 +4855,12 @@ dependencies = [
|
|||||||
"windows_x86_64_msvc 0.53.0",
|
"windows_x86_64_msvc 0.53.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4514,6 +4879,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4532,6 +4903,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4562,6 +4939,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4580,6 +4963,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4598,6 +4987,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4616,6 +5011,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4643,6 +5044,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
|||||||
@ -12,6 +12,13 @@ opt-level = "z"
|
|||||||
strip = "none"
|
strip = "none"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tokio = { version = "1.44.0", features = [
|
||||||
|
"sync",
|
||||||
|
"macros",
|
||||||
|
"io-util",
|
||||||
|
"rt",
|
||||||
|
"time",
|
||||||
|
] }
|
||||||
anyhow = "1.0.71"
|
anyhow = "1.0.71"
|
||||||
better-panic = "0.3.0"
|
better-panic = "0.3.0"
|
||||||
colored = "2"
|
colored = "2"
|
||||||
@ -51,7 +58,6 @@ terminal-colorsaurus = "0.4.0"
|
|||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||||
tokio = { version = "1.32.0", features = ['sync','macros','io-util','rt','time'] }
|
|
||||||
tokio-util = "0.7.9"
|
tokio-util = "0.7.9"
|
||||||
tracing-appender = "0.2"
|
tracing-appender = "0.2"
|
||||||
tui-logger = { version = "0.17.2", features = ["tracing-support"] }
|
tui-logger = { version = "0.17.2", features = ["tracing-support"] }
|
||||||
@ -59,6 +65,8 @@ tui-term = { git = "https://github.com/JamesHenry/tui-term", rev = "88e3b61425c9
|
|||||||
walkdir = '2.3.3'
|
walkdir = '2.3.3'
|
||||||
xxhash-rust = { version = '0.8.5', features = ['xxh3', 'xxh64'] }
|
xxhash-rust = { version = '0.8.5', features = ['xxh3', 'xxh64'] }
|
||||||
vt100-ctt = { git = "https://github.com/JamesHenry/vt100-rust", rev = "b15dc3b0f7db94167a9c584f1d403899c0cc871d" }
|
vt100-ctt = { git = "https://github.com/JamesHenry/vt100-rust", rev = "b15dc3b0f7db94167a9c584f1d403899c0cc871d" }
|
||||||
|
serde = "1.0.219"
|
||||||
|
serde_json = "1.0.140"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["fileapi", "psapi", "shellapi"] }
|
winapi = { version = "0.3", features = ["fileapi", "psapi", "shellapi"] }
|
||||||
@ -74,13 +82,22 @@ portable-pty = { git = "https://github.com/cammisuli/wezterm", rev = "b538ee29e1
|
|||||||
ignore-files = "2.1.0"
|
ignore-files = "2.1.0"
|
||||||
fs4 = "0.12.0"
|
fs4 = "0.12.0"
|
||||||
ratatui = { version = "0.29", features = ["scrolling-regions"] }
|
ratatui = { version = "0.29", features = ["scrolling-regions"] }
|
||||||
reqwest = { version = "0.12.15", default-features = false, features = ["rustls-tls"] }
|
reqwest = { version = "0.12.15", default-features = false, features = [
|
||||||
|
"rustls-tls",
|
||||||
|
] }
|
||||||
rusqlite = { version = "0.32.1", features = ["bundled", "array", "vtab"] }
|
rusqlite = { version = "0.32.1", features = ["bundled", "array", "vtab"] }
|
||||||
watchexec = "3.0.1"
|
watchexec = "3.0.1"
|
||||||
watchexec-events = "2.0.1"
|
watchexec-events = "2.0.1"
|
||||||
watchexec-filterer-ignore = "3.0.0"
|
watchexec-filterer-ignore = "3.0.0"
|
||||||
watchexec-signals = "2.1.0"
|
watchexec-signals = "2.1.0"
|
||||||
machine-uid = "0.5.2"
|
machine-uid = "0.5.2"
|
||||||
|
interprocess = { version = "2.2.3", features = ["tokio"] }
|
||||||
|
jsonrpsee = { version = "0.25.1", features = [
|
||||||
|
"client-core",
|
||||||
|
"async-client",
|
||||||
|
"macros",
|
||||||
|
"http-client",
|
||||||
|
] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ['cdylib']
|
crate-type = ['cdylib']
|
||||||
@ -94,3 +111,4 @@ insta = "1.42.2"
|
|||||||
# This is only used for unit tests
|
# This is only used for unit tests
|
||||||
swc_ecma_dep_graph = "0.109.1"
|
swc_ecma_dep_graph = "0.109.1"
|
||||||
tempfile = "3.13.0"
|
tempfile = "3.13.0"
|
||||||
|
uuid = { version = "1.0", features = ["v4"] }
|
||||||
|
|||||||
2
packages/nx/src/native/index.d.ts
vendored
2
packages/nx/src/native/index.d.ts
vendored
@ -8,7 +8,7 @@ export declare class ExternalObject<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export declare class AppLifeCycle {
|
export declare class AppLifeCycle {
|
||||||
constructor(tasks: Array<Task>, initiatingTasks: Array<string>, runMode: RunMode, pinnedTasks: Array<string>, tuiCliArgs: TuiCliArgs, tuiConfig: TuiConfig, titleText: string)
|
constructor(tasks: Array<Task>, initiatingTasks: Array<string>, runMode: RunMode, pinnedTasks: Array<string>, tuiCliArgs: TuiCliArgs, tuiConfig: TuiConfig, titleText: string, workspaceRoot: string)
|
||||||
startCommand(threadCount?: number | undefined | null): void
|
startCommand(threadCount?: number | undefined | null): void
|
||||||
scheduleTask(task: Task): void
|
scheduleTask(task: Task): void
|
||||||
startTasks(tasks: Array<Task>, metadata: object): void
|
startTasks(tasks: Array<Task>, metadata: object): void
|
||||||
|
|||||||
@ -62,10 +62,15 @@ const originalLoad = Module._load;
|
|||||||
// Will only be called once because the require cache takes over afterwards.
|
// Will only be called once because the require cache takes over afterwards.
|
||||||
Module._load = function (request, parent, isMain) {
|
Module._load = function (request, parent, isMain) {
|
||||||
const modulePath = request;
|
const modulePath = request;
|
||||||
if (
|
// Check if we should use the native file cache (enabled by default)
|
||||||
|
const useNativeFileCache = process.env.NX_SKIP_NATIVE_FILE_CACHE !== 'true';
|
||||||
|
// Check if this is an Nx native module (either from npm or local file)
|
||||||
|
const isNxNativeModule =
|
||||||
nxPackages.has(modulePath) ||
|
nxPackages.has(modulePath) ||
|
||||||
localNodeFiles.some((f) => modulePath.endsWith(f))
|
localNodeFiles.some((file) => modulePath.endsWith(file));
|
||||||
) {
|
|
||||||
|
// Only use the file cache for Nx native modules when caching is enabled
|
||||||
|
if (useNativeFileCache && isNxNativeModule) {
|
||||||
const nativeLocation = require.resolve(modulePath);
|
const nativeLocation = require.resolve(modulePath);
|
||||||
const fileName = basename(nativeLocation);
|
const fileName = basename(nativeLocation);
|
||||||
|
|
||||||
|
|||||||
@ -35,4 +35,6 @@ pub enum Action {
|
|||||||
StartTasks(Vec<Task>),
|
StartTasks(Vec<Task>),
|
||||||
EndTasks(Vec<TaskResult>),
|
EndTasks(Vec<TaskResult>),
|
||||||
ToggleDebugMode,
|
ToggleDebugMode,
|
||||||
|
SendConsoleMessage(String),
|
||||||
|
ConsoleMessengerAvailable(bool),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,6 @@ use crate::native::{
|
|||||||
tasks::types::{Task, TaskResult},
|
tasks::types::{Task, TaskResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::action::Action;
|
|
||||||
use super::components::Component;
|
use super::components::Component;
|
||||||
use super::components::countdown_popup::CountdownPopup;
|
use super::components::countdown_popup::CountdownPopup;
|
||||||
use super::components::help_popup::HelpPopup;
|
use super::components::help_popup::HelpPopup;
|
||||||
@ -39,6 +38,7 @@ use super::pty::PtyInstance;
|
|||||||
use super::theme::THEME;
|
use super::theme::THEME;
|
||||||
use super::tui;
|
use super::tui;
|
||||||
use super::utils::normalize_newlines;
|
use super::utils::normalize_newlines;
|
||||||
|
use super::{action::Action, nx_console::messaging::NxConsoleMessageConnection};
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub components: Vec<Box<dyn Component>>,
|
pub components: Vec<Box<dyn Component>>,
|
||||||
@ -68,6 +68,7 @@ pub struct App {
|
|||||||
tasks: Vec<Task>,
|
tasks: Vec<Task>,
|
||||||
debug_mode: bool,
|
debug_mode: bool,
|
||||||
debug_state: TuiWidgetState,
|
debug_state: TuiWidgetState,
|
||||||
|
console_messenger: Option<NxConsoleMessageConnection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -134,6 +135,7 @@ impl App {
|
|||||||
tasks,
|
tasks,
|
||||||
debug_mode: false,
|
debug_mode: false,
|
||||||
debug_state: TuiWidgetState::default().set_default_display_level(LevelFilter::Debug),
|
debug_state: TuiWidgetState::default().set_default_display_level(LevelFilter::Debug),
|
||||||
|
console_messenger: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +211,10 @@ impl App {
|
|||||||
|
|
||||||
// Show countdown popup for the configured duration (making sure the help popup is not open first)
|
// Show countdown popup for the configured duration (making sure the help popup is not open first)
|
||||||
pub fn end_command(&mut self) {
|
pub fn end_command(&mut self) {
|
||||||
|
self.console_messenger
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.end_running_tasks());
|
||||||
|
|
||||||
// If the user has interacted with the app, or auto-exit is disabled, do nothing
|
// If the user has interacted with the app, or auto-exit is disabled, do nothing
|
||||||
if self.user_has_interacted || !self.tui_config.auto_exit.should_exit_automatically() {
|
if self.user_has_interacted || !self.tui_config.auto_exit.should_exit_automatically() {
|
||||||
return;
|
return;
|
||||||
@ -321,6 +327,10 @@ impl App {
|
|||||||
&& !(matches!(self.focus, Focus::MultipleOutput(_))
|
&& !(matches!(self.focus, Focus::MultipleOutput(_))
|
||||||
&& self.is_interactive_mode())
|
&& self.is_interactive_mode())
|
||||||
{
|
{
|
||||||
|
self.console_messenger
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.end_running_tasks());
|
||||||
|
|
||||||
self.is_forced_shutdown = true;
|
self.is_forced_shutdown = true;
|
||||||
// Quit immediately
|
// Quit immediately
|
||||||
self.quit_at = Some(std::time::Instant::now());
|
self.quit_at = Some(std::time::Instant::now());
|
||||||
@ -769,8 +779,25 @@ impl App {
|
|||||||
trace!("{action:?}");
|
trace!("{action:?}");
|
||||||
}
|
}
|
||||||
match &action {
|
match &action {
|
||||||
|
Action::StartCommand(_) => {
|
||||||
|
self.console_messenger
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|c| c.start_running_tasks());
|
||||||
|
}
|
||||||
|
Action::Tick => {
|
||||||
|
self.console_messenger.as_ref().and_then(|messenger| {
|
||||||
|
self.components
|
||||||
|
.iter()
|
||||||
|
.find_map(|c| c.as_any().downcast_ref::<TasksList>())
|
||||||
|
.and_then(|tasks_list| {
|
||||||
|
messenger.update_running_tasks(&tasks_list.tasks, &self.pty_instances)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
// Quit immediately
|
// Quit immediately
|
||||||
Action::Quit => self.quit_at = Some(std::time::Instant::now()),
|
Action::Quit => {
|
||||||
|
self.quit_at = Some(std::time::Instant::now());
|
||||||
|
}
|
||||||
// Cancel quitting
|
// Cancel quitting
|
||||||
Action::CancelQuit => {
|
Action::CancelQuit => {
|
||||||
self.quit_at = None;
|
self.quit_at = None;
|
||||||
@ -981,6 +1008,7 @@ impl App {
|
|||||||
is_focused,
|
is_focused,
|
||||||
has_pty,
|
has_pty,
|
||||||
is_next_tab_target,
|
is_next_tab_target,
|
||||||
|
self.console_messenger.is_some(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let terminal_pane = TerminalPane::new()
|
let terminal_pane = TerminalPane::new()
|
||||||
@ -1008,6 +1036,13 @@ impl App {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
Action::SendConsoleMessage(msg) => {
|
||||||
|
if let Some(connection) = &self.console_messenger {
|
||||||
|
connection.send_terminal_string(msg);
|
||||||
|
} else {
|
||||||
|
trace!("No console connection available");
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,7 +1393,10 @@ impl App {
|
|||||||
fn handle_key_event(&mut self, key: KeyEvent) -> io::Result<()> {
|
fn handle_key_event(&mut self, key: KeyEvent) -> io::Result<()> {
|
||||||
if let Focus::MultipleOutput(pane_idx) = self.focus {
|
if let Focus::MultipleOutput(pane_idx) = self.focus {
|
||||||
let terminal_pane_data = &mut self.terminal_pane_data[pane_idx];
|
let terminal_pane_data = &mut self.terminal_pane_data[pane_idx];
|
||||||
terminal_pane_data.handle_key_event(key)
|
if let Some(action) = terminal_pane_data.handle_key_event(key)? {
|
||||||
|
self.dispatch_action(action);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1540,4 +1578,15 @@ impl App {
|
|||||||
self.debug_state.transition(event);
|
self.debug_state.transition(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_console_messenger(&mut self, messenger: NxConsoleMessageConnection) {
|
||||||
|
self.console_messenger = Some(messenger);
|
||||||
|
if self
|
||||||
|
.console_messenger
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|c| c.is_connected())
|
||||||
|
{
|
||||||
|
self.dispatch_action(Action::ConsoleMessengerAvailable(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,9 +12,11 @@ use std::any::Any;
|
|||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use super::{Component, Frame};
|
use super::{Component, Frame};
|
||||||
use crate::native::tui::action::Action;
|
use crate::native::tui::{action::Action, nx_console};
|
||||||
|
|
||||||
use crate::native::tui::theme::THEME;
|
use crate::native::tui::theme::THEME;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct HelpPopup {
|
pub struct HelpPopup {
|
||||||
scroll_offset: usize,
|
scroll_offset: usize,
|
||||||
scrollbar_state: ScrollbarState,
|
scrollbar_state: ScrollbarState,
|
||||||
@ -22,6 +24,7 @@ pub struct HelpPopup {
|
|||||||
viewport_height: usize,
|
viewport_height: usize,
|
||||||
visible: bool,
|
visible: bool,
|
||||||
action_tx: Option<UnboundedSender<Action>>,
|
action_tx: Option<UnboundedSender<Action>>,
|
||||||
|
console_available: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HelpPopup {
|
impl HelpPopup {
|
||||||
@ -33,6 +36,7 @@ impl HelpPopup {
|
|||||||
viewport_height: 0,
|
viewport_height: 0,
|
||||||
visible: false,
|
visible: false,
|
||||||
action_tx: None,
|
action_tx: None,
|
||||||
|
console_available: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +44,10 @@ impl HelpPopup {
|
|||||||
self.visible = visible;
|
self.visible = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_console_available(&mut self, available: bool) {
|
||||||
|
self.console_available = available;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the scroll state is reset to avoid recalc issues
|
// Ensure the scroll state is reset to avoid recalc issues
|
||||||
pub fn handle_resize(&mut self, _width: u16, _height: u16) {
|
pub fn handle_resize(&mut self, _width: u16, _height: u16) {
|
||||||
self.scroll_offset = 0;
|
self.scroll_offset = 0;
|
||||||
@ -110,7 +118,7 @@ impl HelpPopup {
|
|||||||
])
|
])
|
||||||
.split(popup_layout[1])[1];
|
.split(popup_layout[1])[1];
|
||||||
|
|
||||||
let keybindings = vec![
|
let mut keybindings = vec![
|
||||||
// Misc
|
// Misc
|
||||||
("?", "Toggle this popup"),
|
("?", "Toggle this popup"),
|
||||||
("q or <ctrl>+c", "Quit the TUI"),
|
("q or <ctrl>+c", "Quit the TUI"),
|
||||||
@ -149,6 +157,25 @@ impl HelpPopup {
|
|||||||
("<ctrl>+z", "Stop interacting with a continuous task"),
|
("<ctrl>+z", "Stop interacting with a continuous task"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if self.console_available {
|
||||||
|
// add Copilot specific keybindings for AI assistance
|
||||||
|
|
||||||
|
keybindings.extend([
|
||||||
|
("", ""),
|
||||||
|
(
|
||||||
|
"<ctrl>+a",
|
||||||
|
match nx_console::get_current_editor() {
|
||||||
|
nx_console::SupportedEditor::VSCode => {
|
||||||
|
"Send terminal output to Copilot so that it can assist with any issues"
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
"Send terminal output to your AI assistant so that it can assist with any issues"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
let mut content: Vec<Line> = vec![
|
let mut content: Vec<Line> = vec![
|
||||||
// Welcome text
|
// Welcome text
|
||||||
Line::from(vec![
|
Line::from(vec![
|
||||||
@ -357,8 +384,14 @@ impl Component for HelpPopup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||||
if let Action::Resize(w, h) = action {
|
match action {
|
||||||
self.handle_resize(w, h);
|
Action::Resize(w, h) => {
|
||||||
|
self.handle_resize(w, h);
|
||||||
|
}
|
||||||
|
Action::ConsoleMessengerAvailable(available) => {
|
||||||
|
self.set_console_available(available);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use ratatui::{
|
|||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{Block, Cell, Paragraph, Row, Table},
|
widgets::{Block, Cell, Paragraph, Row, Table},
|
||||||
};
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
@ -52,7 +53,7 @@ pub struct TaskItem {
|
|||||||
cache_status: String,
|
cache_status: String,
|
||||||
// Public to aid with sorting utility and testing
|
// Public to aid with sorting utility and testing
|
||||||
pub status: TaskStatus,
|
pub status: TaskStatus,
|
||||||
terminal_output: String,
|
pub terminal_output: String,
|
||||||
pub continuous: bool,
|
pub continuous: bool,
|
||||||
start_time: Option<i64>,
|
start_time: Option<i64>,
|
||||||
// Public to aid with sorting utility and testing
|
// Public to aid with sorting utility and testing
|
||||||
@ -115,7 +116,7 @@ impl TaskItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum TaskStatus {
|
pub enum TaskStatus {
|
||||||
// Explicit statuses that can come from the task runner
|
// Explicit statuses that can come from the task runner
|
||||||
Success,
|
Success,
|
||||||
|
|||||||
@ -13,9 +13,9 @@ use ratatui::{
|
|||||||
use std::{io, sync::Arc};
|
use std::{io, sync::Arc};
|
||||||
use tui_term::widget::PseudoTerminal;
|
use tui_term::widget::PseudoTerminal;
|
||||||
|
|
||||||
use super::tasks_list::TaskStatus;
|
use crate::native::tui::components::tasks_list::TaskStatus;
|
||||||
use crate::native::tui::pty::PtyInstance;
|
|
||||||
use crate::native::tui::theme::THEME;
|
use crate::native::tui::theme::THEME;
|
||||||
|
use crate::native::tui::{action::Action, pty::PtyInstance};
|
||||||
|
|
||||||
pub struct TerminalPaneData {
|
pub struct TerminalPaneData {
|
||||||
pub pty: Option<Arc<PtyInstance>>,
|
pub pty: Option<Arc<PtyInstance>>,
|
||||||
@ -34,7 +34,7 @@ impl TerminalPaneData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_key_event(&mut self, key: KeyEvent) -> io::Result<()> {
|
pub fn handle_key_event(&mut self, key: KeyEvent) -> io::Result<Option<Action>> {
|
||||||
if let Some(pty) = &mut self.pty {
|
if let Some(pty) = &mut self.pty {
|
||||||
let mut pty_mut = pty.as_ref().clone();
|
let mut pty_mut = pty.as_ref().clone();
|
||||||
match key.code {
|
match key.code {
|
||||||
@ -42,11 +42,11 @@ impl TerminalPaneData {
|
|||||||
// If interactive, the event falls through to be forwarded to the PTY so that we can support things like interactive prompts within tasks.
|
// If interactive, the event falls through to be forwarded to the PTY so that we can support things like interactive prompts within tasks.
|
||||||
KeyCode::Up | KeyCode::Char('k') if !self.is_interactive => {
|
KeyCode::Up | KeyCode::Char('k') if !self.is_interactive => {
|
||||||
pty_mut.scroll_up();
|
pty_mut.scroll_up();
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
KeyCode::Down | KeyCode::Char('j') if !self.is_interactive => {
|
KeyCode::Down | KeyCode::Char('j') if !self.is_interactive => {
|
||||||
pty_mut.scroll_down();
|
pty_mut.scroll_down();
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
// Handle ctrl+u and ctrl+d for scrolling when not in interactive mode
|
// Handle ctrl+u and ctrl+d for scrolling when not in interactive mode
|
||||||
KeyCode::Char('u')
|
KeyCode::Char('u')
|
||||||
@ -56,7 +56,7 @@ impl TerminalPaneData {
|
|||||||
for _ in 0..12 {
|
for _ in 0..12 {
|
||||||
pty_mut.scroll_up();
|
pty_mut.scroll_up();
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
KeyCode::Char('d')
|
KeyCode::Char('d')
|
||||||
if key.modifiers.contains(KeyModifiers::CONTROL) && !self.is_interactive =>
|
if key.modifiers.contains(KeyModifiers::CONTROL) && !self.is_interactive =>
|
||||||
@ -65,7 +65,7 @@ impl TerminalPaneData {
|
|||||||
for _ in 0..12 {
|
for _ in 0..12 {
|
||||||
pty_mut.scroll_down();
|
pty_mut.scroll_down();
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
// Handle 'c' for copying when not in interactive mode
|
// Handle 'c' for copying when not in interactive mode
|
||||||
KeyCode::Char('c') if !self.is_interactive => {
|
KeyCode::Char('c') if !self.is_interactive => {
|
||||||
@ -81,12 +81,20 @@ impl TerminalPaneData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
}
|
}
|
||||||
// Handle 'i' to enter interactive mode for in progress tasks
|
// Handle 'i' to enter interactive mode for in progress tasks
|
||||||
KeyCode::Char('i') if self.can_be_interactive && !self.is_interactive => {
|
KeyCode::Char('i') if self.can_be_interactive && !self.is_interactive => {
|
||||||
self.set_interactive(true);
|
self.set_interactive(true);
|
||||||
return Ok(());
|
return Ok(None);
|
||||||
|
}
|
||||||
|
KeyCode::Char('a')
|
||||||
|
if key.modifiers.contains(KeyModifiers::CONTROL) && !self.is_interactive =>
|
||||||
|
{
|
||||||
|
let Some(screen) = pty.get_screen() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
return Ok(Some(Action::SendConsoleMessage(screen.all_contents())));
|
||||||
}
|
}
|
||||||
// Only send input to PTY if we're in interactive mode
|
// Only send input to PTY if we're in interactive mode
|
||||||
_ if self.is_interactive => match key.code {
|
_ if self.is_interactive => match key.code {
|
||||||
@ -114,7 +122,7 @@ impl TerminalPaneData {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_mouse_event(&mut self, event: MouseEvent) -> io::Result<()> {
|
pub fn handle_mouse_event(&mut self, event: MouseEvent) -> io::Result<()> {
|
||||||
@ -161,6 +169,7 @@ pub struct TerminalPaneState {
|
|||||||
pub scrollbar_state: ScrollbarState,
|
pub scrollbar_state: ScrollbarState,
|
||||||
pub has_pty: bool,
|
pub has_pty: bool,
|
||||||
pub is_next_tab_target: bool,
|
pub is_next_tab_target: bool,
|
||||||
|
pub console_available: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalPaneState {
|
impl TerminalPaneState {
|
||||||
@ -171,6 +180,7 @@ impl TerminalPaneState {
|
|||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
has_pty: bool,
|
has_pty: bool,
|
||||||
is_next_tab_target: bool,
|
is_next_tab_target: bool,
|
||||||
|
console_available: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
task_name,
|
task_name,
|
||||||
@ -181,6 +191,7 @@ impl TerminalPaneState {
|
|||||||
scrollbar_state: ScrollbarState::default(),
|
scrollbar_state: ScrollbarState::default(),
|
||||||
has_pty,
|
has_pty,
|
||||||
is_next_tab_target,
|
is_next_tab_target,
|
||||||
|
console_available,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,13 +5,17 @@ use parking_lot::Mutex;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
use crate::native::logger::enable_logger;
|
||||||
|
use crate::native::tasks::types::{Task, TaskResult};
|
||||||
|
use crate::native::{
|
||||||
|
pseudo_terminal::pseudo_terminal::{ParserArc, WriterArc},
|
||||||
|
tui::nx_console::messaging::NxConsoleMessageConnection,
|
||||||
|
};
|
||||||
|
|
||||||
use super::app::App;
|
use super::app::App;
|
||||||
use super::components::tasks_list::TaskStatus;
|
use super::components::tasks_list::TaskStatus;
|
||||||
use super::config::{AutoExit, TuiCliArgs as RustTuiCliArgs, TuiConfig as RustTuiConfig};
|
use super::config::{AutoExit, TuiCliArgs as RustTuiCliArgs, TuiConfig as RustTuiConfig};
|
||||||
use super::tui::Tui;
|
use super::tui::Tui;
|
||||||
use crate::native::logger::enable_logger;
|
|
||||||
use crate::native::pseudo_terminal::pseudo_terminal::{ParserArc, WriterArc};
|
|
||||||
use crate::native::tasks::types::{Task, TaskResult};
|
|
||||||
|
|
||||||
#[napi(object)]
|
#[napi(object)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -63,6 +67,7 @@ pub enum RunMode {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppLifeCycle {
|
pub struct AppLifeCycle {
|
||||||
app: Arc<Mutex<App>>,
|
app: Arc<Mutex<App>>,
|
||||||
|
workspace_root: Arc<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
@ -76,6 +81,7 @@ impl AppLifeCycle {
|
|||||||
tui_cli_args: TuiCliArgs,
|
tui_cli_args: TuiCliArgs,
|
||||||
tui_config: TuiConfig,
|
tui_config: TuiConfig,
|
||||||
title_text: String,
|
title_text: String,
|
||||||
|
workspace_root: String,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Get the target names from nx_args.targets
|
// Get the target names from nx_args.targets
|
||||||
let rust_tui_cli_args = tui_cli_args.into();
|
let rust_tui_cli_args = tui_cli_args.into();
|
||||||
@ -97,6 +103,7 @@ impl AppLifeCycle {
|
|||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)),
|
)),
|
||||||
|
workspace_root: Arc::new(workspace_root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +214,14 @@ impl AppLifeCycle {
|
|||||||
|
|
||||||
debug!("Initialized Components");
|
debug!("Initialized Components");
|
||||||
|
|
||||||
|
let workspace_root = self.workspace_root.clone();
|
||||||
napi::tokio::spawn(async move {
|
napi::tokio::spawn(async move {
|
||||||
|
{
|
||||||
|
// set up Console Messenger in a async context
|
||||||
|
let connection = NxConsoleMessageConnection::new(&workspace_root).await;
|
||||||
|
app_mutex.lock().set_console_messenger(connection);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Handle events using our Tui abstraction
|
// Handle events using our Tui abstraction
|
||||||
if let Some(event) = tui.next().await {
|
if let Some(event) = tui.next().await {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ pub mod app;
|
|||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod lifecycle;
|
pub mod lifecycle;
|
||||||
|
pub mod nx_console;
|
||||||
pub mod pty;
|
pub mod pty;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
|
|||||||
195
packages/nx/src/native/tui/nx_console.rs
Normal file
195
packages/nx/src/native/tui/nx_console.rs
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
mod ipc_transport;
|
||||||
|
pub mod messaging;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum SupportedEditor {
|
||||||
|
VSCode,
|
||||||
|
Cursor,
|
||||||
|
Windsurf,
|
||||||
|
JetBrains,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
static CURRENT_EDITOR: OnceLock<SupportedEditor> = OnceLock::new();
|
||||||
|
|
||||||
|
pub fn get_current_editor() -> &'static SupportedEditor {
|
||||||
|
CURRENT_EDITOR.get_or_init(|| detect_editor(HashMap::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detect_editor(mut env_map: HashMap<String, String>) -> SupportedEditor {
|
||||||
|
let term_editor = if let Some(term) = get_env_var("TERM_PROGRAM", &mut env_map) {
|
||||||
|
let term_lower = term.to_lowercase();
|
||||||
|
match term_lower.as_str() {
|
||||||
|
"vscode" => SupportedEditor::VSCode,
|
||||||
|
"cursor" => SupportedEditor::Cursor,
|
||||||
|
"windsurf" => SupportedEditor::Windsurf,
|
||||||
|
"jetbrains" => SupportedEditor::JetBrains,
|
||||||
|
_ => SupportedEditor::Unknown,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SupportedEditor::Unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
// For JetBrains, we don't need any additional checks
|
||||||
|
if matches!(term_editor, SupportedEditor::JetBrains) {
|
||||||
|
return term_editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(term_editor, SupportedEditor::VSCode) {
|
||||||
|
if let Some(vscode_git_var) = get_env_var("VSCODE_GIT_ASKPASS_NODE", &mut env_map) {
|
||||||
|
let vscode_git_var_lowercase = vscode_git_var.to_lowercase();
|
||||||
|
if vscode_git_var_lowercase.contains("cursor") {
|
||||||
|
return SupportedEditor::Cursor;
|
||||||
|
} else if vscode_git_var_lowercase.contains("windsurf") {
|
||||||
|
return SupportedEditor::Windsurf;
|
||||||
|
} else {
|
||||||
|
return SupportedEditor::VSCode;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return term_editor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SupportedEditor::Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_env_var<'a>(name: &str, env_map: &'a mut HashMap<String, String>) -> Option<&'a str> {
|
||||||
|
if env_map.contains_key(name) {
|
||||||
|
return env_map.get(name).map(|s| s.as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
match std::env::var(name) {
|
||||||
|
Ok(val) => {
|
||||||
|
env_map.insert(name.to_string(), val);
|
||||||
|
env_map.get(name).map(|s| s.as_str())
|
||||||
|
}
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_detect_vscode() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "vscode".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/vscode/in/it".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::VSCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_detect_cursor() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "vscode".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/cursor/in/it".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_detect_windsurf() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "vscode".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/windsurf/in/it".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Windsurf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_detect_jetbrains() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "jetbrains".to_string());
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::JetBrains);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_term_program_unknown() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert(
|
||||||
|
"TERM_PROGRAM".to_string(),
|
||||||
|
"some-unknown-editor".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vscode_without_askpass_confirmation() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "vscode".to_string());
|
||||||
|
// No VSCODE_GIT_ASKPASS_NODE set or doesn't contain "vscode"
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::VSCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vscode_with_wrong_askpass() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "vscode".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/no/matching/editor".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::VSCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_case_insensitivity() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "VSCode".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/VSCODE/in/it".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::VSCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cursor_without_askpass_confirmation() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "cursor".to_string());
|
||||||
|
// No VSCODE_GIT_ASKPASS_NODE set
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cursor_with_wrong_askpass() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "cursor".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/no/matching/editor".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_windsurf_without_askpass_confirmation() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "windsurf".to_string());
|
||||||
|
// No VSCODE_GIT_ASKPASS_NODE set
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_windsurf_with_wrong_askpass() {
|
||||||
|
let mut test_env = HashMap::new();
|
||||||
|
test_env.insert("TERM_PROGRAM".to_string(), "windsurf".to_string());
|
||||||
|
test_env.insert(
|
||||||
|
"VSCODE_GIT_ASKPASS_NODE".to_string(),
|
||||||
|
"some/path/with/no/matching/editor".to_string(),
|
||||||
|
);
|
||||||
|
assert_eq!(detect_editor(test_env), SupportedEditor::Unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
320
packages/nx/src/native/tui/nx_console/ipc_transport.rs
Normal file
320
packages/nx/src/native/tui/nx_console/ipc_transport.rs
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use interprocess::{
|
||||||
|
bound_util::{RefTokioAsyncRead, RefTokioAsyncWrite},
|
||||||
|
local_socket::{
|
||||||
|
GenericFilePath, ToFsName,
|
||||||
|
tokio::{Stream, prelude::*},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use jsonrpsee::core::client::{ReceivedMessage, TransportReceiverT, TransportSenderT};
|
||||||
|
use thiserror::Error;
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
|
pub struct IpcTransport {
|
||||||
|
pub reader: IpcTransportReceiver,
|
||||||
|
pub writer: IpcTransportSender,
|
||||||
|
}
|
||||||
|
impl IpcTransport {
|
||||||
|
pub async fn new(socket_path: &Path) -> Result<Self, anyhow::Error> {
|
||||||
|
let socket_path = socket_path.to_fs_name::<GenericFilePath>()?;
|
||||||
|
let conn = Stream::connect(socket_path).await?;
|
||||||
|
let stream = Arc::new(conn);
|
||||||
|
let writer = IpcTransportSender(Arc::clone(&stream));
|
||||||
|
let reader = IpcTransportReceiver(Arc::clone(&stream));
|
||||||
|
Ok(Self { reader, writer })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IpcTransportSender(Arc<Stream>);
|
||||||
|
pub struct IpcTransportReceiver(Arc<Stream>);
|
||||||
|
|
||||||
|
const NEW_LINE: &str = "\r\n";
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
#[error(transparent)]
|
||||||
|
pub enum IpcError {
|
||||||
|
GenericError(#[from] anyhow::Error),
|
||||||
|
IoError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportSenderT for IpcTransportSender {
|
||||||
|
type Error = IpcError;
|
||||||
|
|
||||||
|
async fn send(&mut self, msg: String) -> Result<(), Self::Error> {
|
||||||
|
let mut stream = self.0.as_tokio_async_write();
|
||||||
|
let headers = format!("content-length: {}{}{}", msg.len(), NEW_LINE, NEW_LINE);
|
||||||
|
stream.write_all(headers.as_bytes()).await?;
|
||||||
|
stream.flush().await?;
|
||||||
|
let mut msg = msg;
|
||||||
|
msg.push_str(NEW_LINE);
|
||||||
|
msg.push_str(NEW_LINE);
|
||||||
|
stream.write_all(msg.as_bytes()).await?;
|
||||||
|
stream.flush().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportReceiverT for IpcTransportReceiver {
|
||||||
|
type Error = IpcError;
|
||||||
|
|
||||||
|
async fn receive(&mut self) -> Result<ReceivedMessage, Self::Error> {
|
||||||
|
let mut stream = self.0.as_tokio_async_read();
|
||||||
|
let mut response_data = Vec::new();
|
||||||
|
let mut buffer = [0u8; 1024];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let bytes_read = stream.read(buffer.as_mut()).await?;
|
||||||
|
if bytes_read == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
response_data.extend_from_slice(&buffer[..bytes_read]);
|
||||||
|
|
||||||
|
if let Ok(response_str) = String::from_utf8(response_data.clone()) {
|
||||||
|
if response_str.contains('\n') {
|
||||||
|
let parts: Vec<&str> = response_str.split('\n').collect();
|
||||||
|
if let Some(response_part) = parts.first() {
|
||||||
|
return Ok(ReceivedMessage::Text(response_part.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(anyhow!("Failed to read from IPC stream").into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_utils {
|
||||||
|
use super::*;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::{future::Future, path::PathBuf};
|
||||||
|
use tokio::task;
|
||||||
|
|
||||||
|
// Define trait for platform-specific test setup
|
||||||
|
pub trait IpcTestSetup {
|
||||||
|
type ServerHandle: Sized;
|
||||||
|
type ServerSocket: AsyncReadExt + AsyncWriteExt + Unpin;
|
||||||
|
type AcceptFuture: Future<Output = Self::ServerSocket> + Send;
|
||||||
|
type ConnectFuture: Future<Output = Result<IpcTransport, anyhow::Error>> + Send;
|
||||||
|
|
||||||
|
// Setup connection paths
|
||||||
|
fn create_connection_path() -> (PathBuf, PathBuf);
|
||||||
|
|
||||||
|
// Create server
|
||||||
|
fn create_server(path: PathBuf) -> Self::ServerHandle;
|
||||||
|
|
||||||
|
// Accept client connection
|
||||||
|
fn accept_connection(handle: &mut Self::ServerHandle) -> Self::AcceptFuture;
|
||||||
|
|
||||||
|
// Connect client
|
||||||
|
fn connect_client(path: PathBuf) -> Self::ConnectFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common test implementations
|
||||||
|
pub async fn test_ipc_transport_connection<T: IpcTestSetup>() {
|
||||||
|
let (server_path, client_path) = T::create_connection_path();
|
||||||
|
|
||||||
|
// Create a mock server
|
||||||
|
let mut server = T::create_server(server_path);
|
||||||
|
|
||||||
|
// Connect in a separate task
|
||||||
|
let client_task = task::spawn(async move {
|
||||||
|
// Small delay to ensure server is ready
|
||||||
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
T::connect_client(client_path).await
|
||||||
|
});
|
||||||
|
|
||||||
|
// Accept the connection
|
||||||
|
T::accept_connection(&mut server).await;
|
||||||
|
|
||||||
|
let result = client_task.await.unwrap();
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_transport_sender_send<T: IpcTestSetup>() {
|
||||||
|
let (server_path, client_path) = T::create_connection_path();
|
||||||
|
|
||||||
|
// Create a mock server
|
||||||
|
let mut server = T::create_server(server_path);
|
||||||
|
|
||||||
|
// Start client in background
|
||||||
|
let client_task = task::spawn(async move {
|
||||||
|
let mut transport = T::connect_client(client_path).await.unwrap();
|
||||||
|
transport.writer.send("test message".to_string()).await
|
||||||
|
});
|
||||||
|
|
||||||
|
// Accept the connection and read the message
|
||||||
|
let mut socket = T::accept_connection(&mut server).await;
|
||||||
|
let mut buf = [0u8; 1024];
|
||||||
|
let n = socket.read(&mut buf).await.unwrap();
|
||||||
|
let received = String::from_utf8_lossy(&buf[0..n]);
|
||||||
|
|
||||||
|
assert!(received.contains("content-length: 12"));
|
||||||
|
|
||||||
|
let result = client_task.await.unwrap();
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn test_transport_receiver_receive<T: IpcTestSetup>() {
|
||||||
|
let (server_path, client_path) = T::create_connection_path();
|
||||||
|
|
||||||
|
// Create a mock server
|
||||||
|
let mut server = T::create_server(server_path);
|
||||||
|
|
||||||
|
// Start client in background
|
||||||
|
let client_task = task::spawn(async move {
|
||||||
|
let mut transport = T::connect_client(client_path).await.unwrap();
|
||||||
|
transport.reader.receive().await
|
||||||
|
});
|
||||||
|
|
||||||
|
// Accept connection and send a message
|
||||||
|
let mut socket = T::accept_connection(&mut server).await;
|
||||||
|
let message = "test\nresponse";
|
||||||
|
socket.write_all(message.as_bytes()).await.unwrap();
|
||||||
|
socket.flush().await.unwrap();
|
||||||
|
|
||||||
|
let result = client_task.await.unwrap();
|
||||||
|
assert!(result.is_ok());
|
||||||
|
if let Ok(ReceivedMessage::Text(text)) = result {
|
||||||
|
assert_eq!(text, "test");
|
||||||
|
} else {
|
||||||
|
panic!("Expected Text message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, unix))]
|
||||||
|
mod tests {
|
||||||
|
use super::test_utils::*;
|
||||||
|
use super::*;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::{future::Future, path::PathBuf};
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
use tokio::net::UnixListener;
|
||||||
|
|
||||||
|
struct UnixIpcTestSetup;
|
||||||
|
|
||||||
|
// Define concrete future types
|
||||||
|
type AcceptConnectionFuture = Pin<Box<dyn Future<Output = tokio::net::UnixStream> + Send>>;
|
||||||
|
type ConnectClientFuture =
|
||||||
|
Pin<Box<dyn Future<Output = Result<IpcTransport, anyhow::Error>> + Send>>;
|
||||||
|
|
||||||
|
impl IpcTestSetup for UnixIpcTestSetup {
|
||||||
|
type ServerHandle = UnixListener;
|
||||||
|
type ServerSocket = tokio::net::UnixStream;
|
||||||
|
type AcceptFuture = AcceptConnectionFuture;
|
||||||
|
type ConnectFuture = ConnectClientFuture;
|
||||||
|
|
||||||
|
fn create_connection_path() -> (PathBuf, PathBuf) {
|
||||||
|
let temp_file = NamedTempFile::new().unwrap();
|
||||||
|
let socket_path = temp_file.path().to_path_buf();
|
||||||
|
std::fs::remove_file(&socket_path).unwrap_or(());
|
||||||
|
(socket_path.clone(), socket_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_server(path: PathBuf) -> Self::ServerHandle {
|
||||||
|
UnixListener::bind(&path).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_connection(handle: &mut Self::ServerHandle) -> Self::AcceptFuture {
|
||||||
|
// Take ownership of the listener and create a new one for subsequent calls
|
||||||
|
let path = std::env::temp_dir().join(format!("socket-{}", uuid::Uuid::new_v4()));
|
||||||
|
std::fs::remove_file(&path).unwrap_or(());
|
||||||
|
let old_listener = std::mem::replace(handle, UnixListener::bind(&path).unwrap());
|
||||||
|
|
||||||
|
Box::pin(async move {
|
||||||
|
let (socket, _) = old_listener.accept().await.unwrap();
|
||||||
|
socket
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_client(path: PathBuf) -> Self::ConnectFuture {
|
||||||
|
Box::pin(async move { IpcTransport::new(&path).await })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_ipc_transport_connection() {
|
||||||
|
test_utils::test_ipc_transport_connection::<UnixIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_transport_sender_send() {
|
||||||
|
test_utils::test_transport_sender_send::<UnixIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_transport_receiver_receive() {
|
||||||
|
test_utils::test_transport_receiver_receive::<UnixIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, windows))]
|
||||||
|
mod tests_windows {
|
||||||
|
use super::test_utils::*;
|
||||||
|
use super::*;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::{future::Future, path::PathBuf};
|
||||||
|
use tokio::net::windows::named_pipe::ServerOptions;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
struct WindowsIpcTestSetup;
|
||||||
|
|
||||||
|
// Define concrete future types
|
||||||
|
type AcceptConnectionFuture =
|
||||||
|
Pin<Box<dyn Future<Output = tokio::net::windows::named_pipe::NamedPipeServer> + Send>>;
|
||||||
|
type ConnectClientFuture =
|
||||||
|
Pin<Box<dyn Future<Output = Result<IpcTransport, anyhow::Error>> + Send>>;
|
||||||
|
|
||||||
|
impl IpcTestSetup for WindowsIpcTestSetup {
|
||||||
|
type ServerHandle = (ServerOptions, PathBuf);
|
||||||
|
type ServerSocket = tokio::net::windows::named_pipe::NamedPipeServer;
|
||||||
|
type AcceptFuture = AcceptConnectionFuture;
|
||||||
|
type ConnectFuture = ConnectClientFuture;
|
||||||
|
|
||||||
|
fn create_connection_path() -> (PathBuf, PathBuf) {
|
||||||
|
let pipe_name = format!(r"\\.\pipe\test-{}", Uuid::new_v4());
|
||||||
|
(pipe_name.clone().into(), pipe_name.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_server(path: PathBuf) -> Self::ServerHandle {
|
||||||
|
let mut options = ServerOptions::new();
|
||||||
|
options.first_pipe_instance(true);
|
||||||
|
(options, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_connection(handle: &mut Self::ServerHandle) -> Self::AcceptFuture {
|
||||||
|
let (options, path) = handle;
|
||||||
|
let options = options.clone();
|
||||||
|
let path = path.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
let path_str = path.to_str().unwrap();
|
||||||
|
let server = options.create(path_str).unwrap();
|
||||||
|
server.connect().await.unwrap();
|
||||||
|
server
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect_client(path: PathBuf) -> Self::ConnectFuture {
|
||||||
|
Box::pin(async move { IpcTransport::new(&path).await })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_ipc_transport_connection() {
|
||||||
|
test_utils::test_ipc_transport_connection::<WindowsIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_transport_sender_send() {
|
||||||
|
test_utils::test_transport_sender_send::<WindowsIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_transport_receiver_receive() {
|
||||||
|
test_utils::test_transport_receiver_receive::<WindowsIpcTestSetup>().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
164
packages/nx/src/native/tui/nx_console/messaging.rs
Normal file
164
packages/nx/src/native/tui/nx_console/messaging.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
use std::{collections::HashMap, sync::Arc, time::Duration};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::time::Instant;
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
|
use jsonrpsee::{
|
||||||
|
async_client::{Client, ClientBuilder},
|
||||||
|
proc_macros::rpc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::native::{
|
||||||
|
tui::{
|
||||||
|
components::tasks_list::{TaskItem, TaskStatus},
|
||||||
|
nx_console::ipc_transport::IpcTransport,
|
||||||
|
pty::PtyInstance,
|
||||||
|
},
|
||||||
|
utils::socket_path::get_full_nx_console_socket_path,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct UpdatedRunningTask {
|
||||||
|
pub name: String,
|
||||||
|
pub status: TaskStatus,
|
||||||
|
pub output: String,
|
||||||
|
pub continuous: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rpc(client, namespace = "nx", namespace_separator = "/")]
|
||||||
|
pub trait ConsoleRpc {
|
||||||
|
#[method(name = "terminalMessage")]
|
||||||
|
fn terminal_message(&self, text: String);
|
||||||
|
|
||||||
|
#[method(name = "updateRunningTasks")]
|
||||||
|
fn update_running_tasks(&self, process_id: u32, updates: Vec<UpdatedRunningTask>);
|
||||||
|
#[method(name = "startedRunningTasks")]
|
||||||
|
fn start_running_tasks(&self, process_id: u32);
|
||||||
|
#[method(name = "endedRunningTasks")]
|
||||||
|
fn end_running_tasks(&self, process_id: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NxConsoleMessageConnection {
|
||||||
|
client: Option<Arc<Client>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
static LAST_UPDATES: Lazy<Mutex<HashMap<&'static str, Instant>>> =
|
||||||
|
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||||
|
const THROTTLE_DURATION: Duration = Duration::from_secs(2);
|
||||||
|
|
||||||
|
/// Utility function to check if an operation should be throttled.
|
||||||
|
/// Returns true if the operation should be throttled (skipped), false if it should proceed.
|
||||||
|
fn throttled(operation_key: &'static str, throttle_duration: Duration) -> bool {
|
||||||
|
let mut last_updates = LAST_UPDATES.lock();
|
||||||
|
let now = Instant::now();
|
||||||
|
|
||||||
|
match last_updates.get(operation_key) {
|
||||||
|
Some(last) if now.duration_since(*last) < throttle_duration => true, // Should throttle
|
||||||
|
_ => {
|
||||||
|
// Update the last update time
|
||||||
|
last_updates.insert(operation_key, now);
|
||||||
|
false // Should NOT throttle, operation should proceed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NxConsoleMessageConnection {
|
||||||
|
pub async fn new(workspace_root: &str) -> Self {
|
||||||
|
let socket_path = get_full_nx_console_socket_path(workspace_root);
|
||||||
|
let client = IpcTransport::new(&socket_path)
|
||||||
|
.await
|
||||||
|
.map(|transport| {
|
||||||
|
ClientBuilder::new().build_with_tokio(transport.writer, transport.reader)
|
||||||
|
})
|
||||||
|
.inspect_err(|e| {
|
||||||
|
trace!(?socket_path, "Could not connect to Nx Console: {}", e);
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.map(Arc::new);
|
||||||
|
|
||||||
|
Self { client }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_connected(&self) -> bool {
|
||||||
|
self.client.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_terminal_string(&self, message: impl Into<String>) -> Option<()> {
|
||||||
|
self.client.as_ref().map(|client| {
|
||||||
|
let message = message.into();
|
||||||
|
let client = client.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = client.terminal_message(message).await {
|
||||||
|
trace!("Failed to send terminal message: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_running_tasks(
|
||||||
|
&self,
|
||||||
|
task_statuses: &[TaskItem],
|
||||||
|
ptys: &HashMap<String, Arc<PtyInstance>>,
|
||||||
|
) -> Option<()> {
|
||||||
|
if throttled("update_running_tasks", THROTTLE_DURATION) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client.as_ref().map(|client| {
|
||||||
|
let client = client.clone();
|
||||||
|
|
||||||
|
let task_statuses: Vec<UpdatedRunningTask> = task_statuses
|
||||||
|
.iter()
|
||||||
|
.map(|task| {
|
||||||
|
let output = ptys
|
||||||
|
.get(&task.name)
|
||||||
|
.and_then(|pty| pty.get_screen())
|
||||||
|
.map(|screen| screen.all_contents())
|
||||||
|
.unwrap_or_default();
|
||||||
|
UpdatedRunningTask {
|
||||||
|
name: task.name.clone(),
|
||||||
|
status: task.status,
|
||||||
|
output,
|
||||||
|
continuous: task.continuous,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = client
|
||||||
|
.update_running_tasks(std::process::id(), task_statuses)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
trace!("Failed to send task statuses: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_running_tasks(&self) -> Option<()> {
|
||||||
|
self.client.as_ref().map(|client| {
|
||||||
|
let client = client.clone();
|
||||||
|
let process_id = std::process::id();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = client.start_running_tasks(process_id).await {
|
||||||
|
trace!("Failed to send start running tasks: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end_running_tasks(&self) -> Option<()> {
|
||||||
|
self.client.as_ref().map(|client| {
|
||||||
|
let client = client.clone();
|
||||||
|
let process_id = std::process::id();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = client.end_running_tasks(process_id).await {
|
||||||
|
trace!("Failed to send end running tasks: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ mod find_matching_projects;
|
|||||||
mod get_mod_time;
|
mod get_mod_time;
|
||||||
mod normalize_trait;
|
mod normalize_trait;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
pub mod socket_path;
|
||||||
|
|
||||||
pub use find_matching_projects::*;
|
pub use find_matching_projects::*;
|
||||||
pub use get_mod_time::*;
|
pub use get_mod_time::*;
|
||||||
|
|||||||
95
packages/nx/src/native/utils/socket_path.rs
Normal file
95
packages/nx/src/native/utils/socket_path.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::native::hasher::hash;
|
||||||
|
|
||||||
|
const DAEMON_DIR_FOR_CURRENT_WORKSPACE: &str = "./nx/workspace-data/d";
|
||||||
|
|
||||||
|
fn socket_dir_name(workspace_root: &str, unique_name: Option<&'static str>) -> PathBuf {
|
||||||
|
let mut hashing_string = workspace_root.to_lowercase();
|
||||||
|
if let Some(name) = unique_name {
|
||||||
|
hashing_string.push(',');
|
||||||
|
hashing_string.push_str(name);
|
||||||
|
}
|
||||||
|
let result = hash(hashing_string.as_bytes());
|
||||||
|
let temp_dir = std::env::temp_dir();
|
||||||
|
temp_dir.join(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_socket_dir(workspace_root: &str, unique_name: Option<&'static str>) -> PathBuf {
|
||||||
|
let dir_path = env::var("NX_SOCKET_DIR")
|
||||||
|
.or_else(|_| env::var("NX_DAEMON_SOCKET_DIR"))
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.unwrap_or_else(|_| socket_dir_name(workspace_root, unique_name));
|
||||||
|
|
||||||
|
let path = if cfg!(target_os = "windows") {
|
||||||
|
dir_path
|
||||||
|
} else {
|
||||||
|
match fs::create_dir_all(&dir_path) {
|
||||||
|
Ok(_) => dir_path,
|
||||||
|
Err(_) => PathBuf::from(workspace_root).join(DAEMON_DIR_FOR_CURRENT_WORKSPACE),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if cfg!(target_os = "windows") {
|
||||||
|
let path_str = path.to_string_lossy();
|
||||||
|
PathBuf::from(format!(r"\\.\pipe\nx\{}", path_str))
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_full_os_socket_path(workspace_root: &str) -> PathBuf {
|
||||||
|
get_socket_dir(workspace_root, None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_full_nx_console_socket_path(workspace_root: &str) -> PathBuf {
|
||||||
|
get_socket_dir(workspace_root, Some("nx-console")).join("nx-console.sock")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_socket_dir_name_basic() {
|
||||||
|
let root = "/tmp/test_workspace";
|
||||||
|
let dir = socket_dir_name(root, None);
|
||||||
|
assert_eq!(dir.to_string_lossy(), "/tmp/17684150229889955837");
|
||||||
|
assert!(dir.is_absolute());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_socket_dir_name_with_unique_name() {
|
||||||
|
let root = "/tmp/test_workspace";
|
||||||
|
let dir = socket_dir_name(root, Some("unique"));
|
||||||
|
assert_eq!(dir.to_string_lossy(), "/tmp/10757852796479033769");
|
||||||
|
assert!(dir.is_absolute());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_socket_dir_env_var() {
|
||||||
|
let root = "/tmp/test_workspace";
|
||||||
|
let temp_dir = std::env::temp_dir().join("nx_test_socket_dir");
|
||||||
|
unsafe { env::set_var("NX_SOCKET_DIR", &temp_dir) };
|
||||||
|
let dir = get_socket_dir(root, None);
|
||||||
|
assert_eq!(dir.to_string_lossy(), "/tmp/nx_test_socket_dir");
|
||||||
|
unsafe { env::remove_var("NX_SOCKET_DIR") };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_full_os_socket_path() {
|
||||||
|
let root = "/tmp/test_workspace";
|
||||||
|
let path = get_full_os_socket_path(root);
|
||||||
|
assert!(path.is_absolute() || path.starts_with("./nx/workspace-data/d"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_full_nx_console_socket_path() {
|
||||||
|
let root = "/tmp/test_workspace";
|
||||||
|
let path = get_full_nx_console_socket_path(root);
|
||||||
|
assert!(path.to_string_lossy().contains("nx-console.sock"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -199,7 +199,8 @@ async function getTerminalOutputLifeCycle(
|
|||||||
pinnedTasks,
|
pinnedTasks,
|
||||||
nxArgs ?? {},
|
nxArgs ?? {},
|
||||||
nxJson.tui ?? {},
|
nxJson.tui ?? {},
|
||||||
titleText
|
titleText,
|
||||||
|
workspaceRoot
|
||||||
);
|
);
|
||||||
lifeCycles.unshift(appLifeCycle);
|
lifeCycles.unshift(appLifeCycle);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user