From 313f0b1ac7eae1a95d41c8b35a92e1f6ad09ca35 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Sun, 17 Nov 2024 16:44:01 +0300 Subject: [PATCH 01/15] wip: wip --- .cargo/config.toml | 3 + .ghjk/lock.json | 283 +- .gitignore | 4 + Cargo.lock | 8455 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 19 + ghjk.ts | 31 +- src/denort/Cargo.toml | 20 + src/denort/lib.rs | 411 ++ src/ghjk/Cargo.toml | 53 + src/ghjk/main.rs | 153 + src/ghjk/utils.rs | 155 + src/xtask/Cargo.toml | 19 + src/xtask/main.rs | 60 + 13 files changed, 9621 insertions(+), 45 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/denort/Cargo.toml create mode 100644 src/denort/lib.rs create mode 100644 src/ghjk/Cargo.toml create mode 100644 src/ghjk/main.rs create mode 100644 src/ghjk/utils.rs create mode 100644 src/xtask/Cargo.toml create mode 100644 src/xtask/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..6c8d827 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[alias] +xtask = "run --package xtask --" +x = "run --package xtask --" diff --git a/.ghjk/lock.json b/.ghjk/lock.json index eed5196..cef8ffc 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -101,6 +101,89 @@ "buildDepConfigs": {}, "portRef": "deno_ghrel@0.1.0", "specifiedVersion": true + }, + "bciqg5gzspxjw7zvrubuyyqskh2244x6mkoxfwugnrx3clyadlegvidi": { + "version": "v2.0.6", + "buildDepConfigs": {}, + "portRef": "deno_ghrel@0.1.0", + "specifiedVersion": true + }, + "bciqkpfuyqchouu5o3whigod3f5coscq2jdlwde6fztypy3x6fg6xb5q": { + "version": "v28.3", + "buildDepConfigs": {}, + "portRef": "protoc_ghrel@0.1.0", + "specifiedVersion": false + }, + "bciqe6tpdv6hffdbc7hql52w3ivpdls47lgpuhsa3hzsryrwx7ty5dgy": { + "version": "3.31.0.1", + "buildDepConfigs": { + "cpy_bs_ghrel": { + "version": "3.12.7", + "buildDepConfigs": { + "tar_aa": { + "version": "1.35", + "buildDepConfigs": {}, + "portRef": "tar_aa@0.1.0", + "specifiedVersion": false + }, + "zstd_aa": { + "version": "v1.5.6", + "buildDepConfigs": {}, + "portRef": "zstd_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "cpy_bs_ghrel@0.1.0", + "specifiedVersion": true + } + }, + "portRef": "pipi_pypi@0.1.0", + "packageName": "cmake", + "specifiedVersion": false + }, + "bciqado5fpguhzyhrxmxqdgutm4i5zgpjhezjoqs5tqrlqqdj5453vhi": { + "version": "1.82.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "default", + "components": [ + "rustfmt", + "clippy" + ], + "specifiedVersion": true + }, + "bciqay4m4kmzfduj5t2clgejxgpe5zwper6lyyaxt7rhbjalaqd32nhq": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + }, + "bciqewpyjyfnnk4rbd6bbu5who2w6ve7dyt3inal72zg23cs4qnln32q": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false } } }, @@ -122,12 +205,20 @@ "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", - "bciqmgggy7hd5as3zz7pzbx54va7lq657bdxvthntxphhlbsl2434dgq" + "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq" ], "allowedBuildDeps": "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq" }, - "ghjkEnvProvInstSet___test": { - "installs": [], + "ghjkEnvProvInstSet____rust": { + "installs": [ + "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", + "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", + "bciqp4n2ahd6nxzsytkoip53ruob4xohbjnmejx4cyux7nvp3usd56bq", + "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", + "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", + "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", + "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq" + ], "allowedBuildDeps": "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq" } } @@ -140,7 +231,7 @@ "lock-sed": { "ty": "denoFile@v1", "key": "lock-sed", - "envKey": "bciqekhy7ndyc6hmkzspdsguxjgvyz5yedr5weigsqsa72kyloity4jy" + "envKey": "bciqa3gn6bjbmgjf7mvk7cv6wfjo23wj3vyppgtpqt4ovvxkpzjrcvua" } }, "tasksNamed": [ @@ -152,27 +243,50 @@ "id": "envs", "config": { "envs": { - "bciqekhy7ndyc6hmkzspdsguxjgvyz5yedr5weigsqsa72kyloity4jy": { + "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya": { + "desc": "the default default environment.", "provides": [ { "ty": "ghjk.ports.InstallSetRef", - "setId": "ghjkEnvProvInstSet___test" + "setId": "ghjkEnvProvInstSet___main" } ] }, - "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya": { - "desc": "the default default environment.", + "bciqa3gn6bjbmgjf7mvk7cv6wfjo23wj3vyppgtpqt4ovvxkpzjrcvua": { "provides": [ { "ty": "ghjk.ports.InstallSetRef", "setId": "ghjkEnvProvInstSet___main" } ] + }, + "bciqjzvefargmop4vyqujvr7igrjunekxn5dmfqezjd2rgrdji5xpdai": { + "provides": [ + { + "ty": "ghjk.ports.InstallSetRef", + "setId": "ghjkEnvProvInstSet____rust" + } + ] + }, + "bciqjgrh5crhxhhnalukxrijysquvykpejx4ldj7jsu3cdzfdynuo3cq": { + "provides": [ + { + "ty": "posix.envVar", + "key": "RUSTY_V8_MIRROR", + "val": "~/.cache/rusty_v8" + }, + { + "ty": "ghjk.ports.InstallSetRef", + "setId": "ghjkEnvProvInstSet____rust" + } + ] } }, - "defaultEnv": "main", + "defaultEnv": "dev", "envsNamed": { - "main": "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya" + "main": "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya", + "_rust": "bciqjzvefargmop4vyqujvr7igrjunekxn5dmfqezjd2rgrdji5xpdai", + "dev": "bciqjgrh5crhxhhnalukxrijysquvykpejx4ldj7jsu3cdzfdynuo3cq" } } } @@ -262,8 +376,8 @@ }, "packageName": "vale" }, - "bciqmgggy7hd5as3zz7pzbx54va7lq657bdxvthntxphhlbsl2434dgq": { - "version": "1.44.2", + "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq": { + "version": "2.0.6", "port": { "ty": "denoWorker@v1", "name": "deno_ghrel", @@ -279,6 +393,34 @@ "moduleSpecifier": "file:///ports/deno_ghrel.ts" } }, + "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq": { + "manifest": { + "ty": "denoWorker@v1", + "name": "cpy_bs_ghrel", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin", + "x86_64-windows", + "aarch64-windows" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "tar_aa" + }, + { + "name": "zstd_aa" + } + ], + "moduleSpecifier": "file:///ports/cpy_bs.ts" + }, + "defaultInst": { + "version": "3.12.7", + "portRef": "cpy_bs_ghrel@0.1.0" + } + }, "bciqb6ua63xodzwxngnbjq35hfikiwzb3dclbqkc7e6xgjdt5jin4pia": { "manifest": { "ty": "ambientAccess@v1", @@ -457,34 +599,6 @@ "portRef": "cargo_binstall_ghrel@0.1.0" } }, - "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq": { - "manifest": { - "ty": "denoWorker@v1", - "name": "cpy_bs_ghrel", - "platforms": [ - "x86_64-linux", - "aarch64-linux", - "x86_64-darwin", - "aarch64-darwin", - "x86_64-windows", - "aarch64-windows" - ], - "version": "0.1.0", - "buildDeps": [ - { - "name": "tar_aa" - }, - { - "name": "zstd_aa" - } - ], - "moduleSpecifier": "file:///ports/cpy_bs.ts" - }, - "defaultInst": { - "version": "3.12.7", - "portRef": "cpy_bs_ghrel@0.1.0" - } - }, "bciqboouqnp54fnumgxvl7uay2k6ho4vhlbibvgoyyt5yt3rkwqaohzi": { "manifest": { "ty": "denoWorker@v1", @@ -576,6 +690,7 @@ } }, "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq": { + "cpy_bs_ghrel": "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq", "tar_aa": "bciqb6ua63xodzwxngnbjq35hfikiwzb3dclbqkc7e6xgjdt5jin4pia", "git_aa": "bciqfl5s36w335ducrb6f6gwb3vuwup7vzqwwg67pq42xtkngsnxqobi", "curl_aa": "bciqcfe7qyxmokpn6pgtaj35r5qg74jkehuu6cvyrtcsnegvwlm64oqy", @@ -583,10 +698,96 @@ "zstd_aa": "bciqpezvwy56igv7hqdpb3qreewqmyftjyej7zhcyhz6afcgfxgy3rjy", "rustup_rustlang": "bciqk4ivbyqvpxwcaj5reufmveqldiizo6xmqiqq7njtaczgappydoka", "cargo_binstall_ghrel": "bciqpgt5wsiw4y7qzovqbt2yrdgq5mvhhjpcg6cxzt4w4taudyen44ca", - "cpy_bs_ghrel": "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq", "node_org": "bciqboouqnp54fnumgxvl7uay2k6ho4vhlbibvgoyyt5yt3rkwqaohzi", "rust_rustup": "bciqhjmjvlo4aqvwxjkrmoiledobmhkfe7iovqe3wndxiw2aootwn4lq", "asdf_plugin_git": "bciqoxx4uhfhw77sux6kzqhy6bvxhxkk4cqigrxdrmggillzkfjgjnli" + }, + "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa": { + "port": { + "ty": "denoWorker@v1", + "name": "protoc_ghrel", + "platforms": [ + "aarch64-linux", + "x86_64-linux", + "aarch64-darwin", + "x86_64-darwin" + ], + "version": "0.1.0", + "moduleSpecifier": "file:///ports/protoc.ts" + } + }, + "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi": { + "port": { + "ty": "denoWorker@v1", + "name": "pipi_pypi", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin", + "x86_64-windows", + "aarch64-windows", + "x86_64-freebsd", + "aarch64-freebsd", + "x86_64-netbsd", + "aarch64-netbsd", + "x86_64-aix", + "aarch64-aix", + "x86_64-solaris", + "aarch64-solaris", + "x86_64-illumos", + "aarch64-illumos", + "x86_64-android", + "aarch64-android" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "cpy_bs_ghrel" + } + ], + "moduleSpecifier": "file:///ports/pipi.ts" + }, + "packageName": "cmake" + }, + "bciqp4n2ahd6nxzsytkoip53ruob4xohbjnmejx4cyux7nvp3usd56bq": { + "version": "1.82.0", + "port": { + "ty": "denoWorker@v1", + "name": "rust_rustup", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin", + "x86_64-windows", + "aarch64-windows", + "x86_64-freebsd", + "aarch64-freebsd", + "x86_64-netbsd", + "aarch64-netbsd", + "x86_64-aix", + "aarch64-aix", + "x86_64-solaris", + "aarch64-solaris", + "x86_64-illumos", + "aarch64-illumos", + "x86_64-android", + "aarch64-android" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "rustup_rustlang" + } + ], + "moduleSpecifier": "file:///ports/rust.ts" + }, + "profile": "default", + "components": [ + "rustfmt", + "clippy" + ] } } } diff --git a/.gitignore b/.gitignore index 6e7b8fb..ffa470c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ npm deno.land jsr.io esm.sh + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2b8204f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,8455 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aead-gcm-stream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4947a169074c7e038fa43051d1c4e073f4488b0e4b0a30658f1e1a1b06449ce8" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + +[[package]] +name = "aes-kw" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c" +dependencies = [ + "aes", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +dependencies = [ + "serde", +] + +[[package]] +name = "ash" +version = "0.37.3+1.3.251" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" +dependencies = [ + "libloading 0.7.4", +] + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.3", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ast_node" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab31376d309dd3bfc9cfb3c11c93ce0e0741bbe0354b20e7f8c60b044730b79" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "async-compression" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "asynchronous-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base32" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64-simd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5" +dependencies = [ + "simd-abstraction", +] + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref 0.5.1", + "vsimd", +] + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "better_scoped_tls" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de" +dependencies = [ + "scoped-tls", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.10.5", + "lazy_static", + "lazycell", + "log", + "prettyplease 0.2.25", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.87", + "which 4.4.2", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "brotli" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cache_control" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2a5fb3207c12b5d208ebc145f967fea5cac41a021c37417ccc31ba40f39ee" + +[[package]] +name = "caseless" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f" +dependencies = [ + "regex", + "unicode-normalization", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading 0.8.4", +] + +[[package]] +name = "clap" +version = "4.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7db6eca8c205649e8d3ccd05aa5042b1800a784e56bc7c43524fde8abbfa9b" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_complete_fig" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d494102c8ff3951810c72baf96910b980fb065ca5d3101243e6a8dc19747c86b" +dependencies = [ + "clap", + "clap_complete", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "clipboard-win" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" +dependencies = [ + "error-code", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "color-eyre" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-print" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" +dependencies = [ + "color-print-proc-macro", +] + +[[package]] +name = "color-print-proc-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" +dependencies = [ + "nom 7.1.3", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "comrak" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c93ab3577cca16b4a1d80a88c2e0cd8b6e969e51696f0bbb0d1dcb0157109832" +dependencies = [ + "caseless", + "derive_builder", + "entities", + "memchr", + "once_cell", + "regex", + "slug", + "typed-arena", + "unicode_categories", +] + +[[package]] +name = "console_static_text" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4be93df536dfbcbd39ff7c129635da089901116b88bfc29ec1acb9b56f8ff35" +dependencies = [ + "unicode-width", + "vte", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cooked-waker" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "countme" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "css_dataset" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25670139e591f1c2869eb8d0d977028f8d05e859132b4c874ecd02a00d3c9174" + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto 0.2.9", + "rustc_version 0.4.0", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "d3d12" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28bfe653d79bd16c77f659305b195b82bb5ce0c0eb2a4846b82ddbd77586813" +dependencies = [ + "bitflags 2.6.0", + "libloading 0.8.4", + "winapi", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.87", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", + "serde", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "data-url" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b319d1b62ffbd002e057f36bebd1f42b9f97927c9577461d855f3513c4289f" + +[[package]] +name = "debug-ignore" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[package]] +name = "deno" +version = "2.0.6" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "anstream", + "async-trait", + "base64 0.21.7", + "bincode", + "bytes", + "cache_control", + "chrono", + "clap", + "clap_complete", + "clap_complete_fig", + "color-print", + "console_static_text", + "dashmap", + "data-encoding", + "deno_ast", + "deno_cache_dir", + "deno_config", + "deno_core", + "deno_doc", + "deno_graph", + "deno_lint", + "deno_lockfile", + "deno_npm", + "deno_package_json", + "deno_path_util", + "deno_resolver", + "deno_runtime", + "deno_semver", + "deno_task_shell", + "deno_terminal 0.2.0", + "deno_tower_lsp", + "dissimilar", + "dotenvy", + "dprint-plugin-json", + "dprint-plugin-jupyter", + "dprint-plugin-markdown", + "dprint-plugin-typescript", + "env_logger", + "fancy-regex", + "faster-hex", + "flate2", + "fs3", + "glibc_version", + "glob", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper-util", + "import_map", + "indexmap", + "jsonc-parser", + "junction", + "lazy-regex", + "libc", + "libsui", + "libz-sys", + "log", + "lsp-types", + "malva", + "markup_fmt", + "memmem", + "monch", + "nix", + "node_resolver", + "notify", + "once_cell", + "open", + "p256", + "pathdiff", + "percent-encoding", + "phf", + "pretty_yaml", + "quick-junit", + "rand", + "regex", + "ring", + "runtimelib", + "rustyline", + "rustyline-derive", + "serde", + "serde_json", + "serde_repr", + "sha2", + "shell-escape", + "spki", + "strsim", + "tar", + "tempfile", + "text-size", + "text_lines", + "thiserror", + "tokio", + "tokio-util", + "tracing", + "twox-hash", + "typed-arena", + "uuid", + "walkdir", + "which 4.4.2", + "winapi", + "winres", + "zeromq", + "zip", + "zstd", +] + +[[package]] +name = "deno-tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d59a1cfd445fd86f63616127a434aabca000e03d963b01b03ce813520565b9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "deno_ast" +version = "0.43.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d00b724e06d2081a141ec1155756a0b465d413d8e2a7515221f61d482eb2ee" +dependencies = [ + "base64 0.21.7", + "deno_media_type", + "deno_terminal 0.1.1", + "dprint-swc-ext", + "once_cell", + "percent-encoding", + "serde", + "sourcemap 9.1.0", + "swc_atoms", + "swc_bundler", + "swc_common", + "swc_config", + "swc_config_macro", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_codegen_macros", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_transforms_optimization", + "swc_ecma_transforms_proposal", + "swc_ecma_transforms_react", + "swc_ecma_transforms_typescript", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_eq_ignore_macros", + "swc_graph_analyzer", + "swc_macros_common", + "swc_visit", + "swc_visit_macros", + "text_lines", + "thiserror", + "unicode-width", + "url", +] + +[[package]] +name = "deno_broadcast_channel" +version = "0.171.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-trait", + "deno_core", + "thiserror", + "tokio", + "uuid", +] + +[[package]] +name = "deno_cache" +version = "0.109.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-trait", + "deno_core", + "rusqlite", + "serde", + "sha2", + "thiserror", + "tokio", +] + +[[package]] +name = "deno_cache_dir" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c1f52170cd7715f8006da54cde1444863a0d6fbd9c11d037a737db2dec8e22" +dependencies = [ + "base32", + "deno_media_type", + "deno_path_util", + "indexmap", + "log", + "once_cell", + "parking_lot", + "serde", + "serde_json", + "sha2", + "thiserror", + "url", +] + +[[package]] +name = "deno_canvas" +version = "0.46.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_webgpu", + "image", + "serde", + "thiserror", +] + +[[package]] +name = "deno_config" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966825073480a6ac7e01977a3879d13edc8d6ea2d65ea164b37156a5fb206e9a" +dependencies = [ + "anyhow", + "deno_package_json", + "deno_path_util", + "deno_semver", + "glob", + "ignore", + "import_map", + "indexmap", + "jsonc-parser", + "log", + "percent-encoding", + "phf", + "serde", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "deno_console" +version = "0.177.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", +] + +[[package]] +name = "deno_core" +version = "0.318.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cae2393219ff9278123f7b24799cdfab37c7d6561b69ca06ced115cac92111" +dependencies = [ + "anyhow", + "bincode", + "bit-set", + "bit-vec", + "bytes", + "cooked-waker", + "deno_core_icudata", + "deno_ops", + "deno_unsync", + "futures", + "libc", + "memoffset", + "parking_lot", + "percent-encoding", + "pin-project", + "serde", + "serde_json", + "serde_v8", + "smallvec", + "sourcemap 8.0.1", + "static_assertions", + "tokio", + "url", + "v8", +] + +[[package]] +name = "deno_core_icudata" +version = "0.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1" + +[[package]] +name = "deno_cron" +version = "0.57.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "deno_core", + "saffron", + "thiserror", + "tokio", +] + +[[package]] +name = "deno_crypto" +version = "0.191.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "aes", + "aes-gcm", + "aes-kw", + "base64 0.21.7", + "cbc", + "const-oid", + "ctr", + "curve25519-dalek", + "deno_core", + "deno_web", + "ed448-goldilocks", + "elliptic-curve", + "num-traits", + "once_cell", + "p256", + "p384", + "p521", + "rand", + "ring", + "rsa", + "sec1", + "serde", + "serde_bytes", + "sha1", + "sha2", + "signature", + "spki", + "thiserror", + "tokio", + "uuid", + "x25519-dalek", +] + +[[package]] +name = "deno_doc" +version = "0.156.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2585b98d6ad76dae30bf2d7b6d71b8363cae041158b8780d14a2f4fe17590a61" +dependencies = [ + "anyhow", + "cfg-if", + "comrak", + "deno_ast", + "deno_graph", + "futures", + "handlebars", + "html-escape", + "import_map", + "indexmap", + "itoa", + "lazy_static", + "regex", + "serde", + "serde_json", + "syntect", + "termcolor", +] + +[[package]] +name = "deno_fetch" +version = "0.201.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "base64 0.21.7", + "bytes", + "data-url", + "deno_core", + "deno_permissions", + "deno_tls", + "dyn-clone", + "error_reporter", + "http 1.1.0", + "http-body-util", + "hyper 1.5.0", + "hyper-rustls", + "hyper-util", + "ipnet", + "percent-encoding", + "rustls-webpki", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-socks", + "tokio-util", + "tower", + "tower-http", + "tower-service", +] + +[[package]] +name = "deno_ffi" +version = "0.164.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_permissions", + "dlopen2 0.6.1", + "dynasmrt", + "libffi", + "libffi-sys", + "log", + "num-bigint", + "serde", + "serde-value", + "serde_json", + "thiserror", + "tokio", + "winapi", +] + +[[package]] +name = "deno_fs" +version = "0.87.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-trait", + "base32", + "deno_core", + "deno_io", + "deno_path_util", + "deno_permissions", + "filetime", + "junction", + "libc", + "nix", + "rand", + "rayon", + "serde", + "thiserror", + "winapi", + "windows-sys 0.52.0", +] + +[[package]] +name = "deno_graph" +version = "0.84.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd4f4a14aa069087be41c2998077b0453f0191747898f96e6343f700abfc2c18" +dependencies = [ + "anyhow", + "async-trait", + "data-url", + "deno_ast", + "deno_semver", + "deno_unsync", + "encoding_rs", + "futures", + "import_map", + "indexmap", + "log", + "monch", + "once_cell", + "parking_lot", + "regex", + "serde", + "serde_json", + "sha2", + "thiserror", + "twox-hash", + "url", +] + +[[package]] +name = "deno_http" +version = "0.175.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-compression", + "async-trait", + "base64 0.21.7", + "brotli", + "bytes", + "cache_control", + "deno_core", + "deno_net", + "deno_websocket", + "flate2", + "http 0.2.12", + "http 1.1.0", + "httparse", + "hyper 0.14.29", + "hyper 1.5.0", + "hyper-util", + "itertools 0.10.5", + "memmem", + "mime", + "once_cell", + "percent-encoding", + "phf", + "pin-project", + "ring", + "scopeguard", + "serde", + "smallvec", + "thiserror", + "tokio", + "tokio-util", +] + +[[package]] +name = "deno_io" +version = "0.87.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-trait", + "deno_core", + "filetime", + "fs3", + "libc", + "log", + "once_cell", + "os_pipe", + "parking_lot", + "pin-project", + "rand", + "tokio", + "uuid", + "winapi", + "windows-sys 0.52.0", +] + +[[package]] +name = "deno_kv" +version = "0.85.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "bytes", + "chrono", + "deno_core", + "deno_fetch", + "deno_path_util", + "deno_permissions", + "deno_tls", + "denokv_proto", + "denokv_remote", + "denokv_sqlite", + "faster-hex", + "http 1.1.0", + "http-body-util", + "log", + "num-bigint", + "prost 0.11.9", + "prost-build", + "rand", + "rusqlite", + "serde", + "thiserror", + "url", +] + +[[package]] +name = "deno_lint" +version = "0.68.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb994e6d1b18223df0a756c7948143b35682941d615edffef60d5b38822f38ac" +dependencies = [ + "anyhow", + "deno_ast", + "derive_more", + "if_chain", + "log", + "once_cell", + "phf", + "regex", + "serde", + "serde_json", +] + +[[package]] +name = "deno_lockfile" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579117d5815aa9bae0212637d6f4d5f45f9649bb2c8988dca434077545535039" +dependencies = [ + "deno_semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "deno_media_type" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf552fbdedbe81c89705349d7d2485c7051382b000dfddbdbf7fc25931cf83" +dependencies = [ + "data-url", + "serde", + "url", +] + +[[package]] +name = "deno_napi" +version = "0.108.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_permissions", + "libc", + "libloading 0.7.4", + "log", + "napi_sym", + "thiserror", + "windows-sys 0.52.0", +] + +[[package]] +name = "deno_native_certs" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bc737e098a45aa5742d51ce694ac7236a1e69fb0d9df8c862e9b4c9583c5f9" +dependencies = [ + "dlopen2 0.7.0", + "dlopen2_derive", + "once_cell", + "rustls-native-certs", + "rustls-pemfile", +] + +[[package]] +name = "deno_net" +version = "0.169.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_permissions", + "deno_tls", + "hickory-proto", + "hickory-resolver", + "pin-project", + "rustls-tokio-stream", + "serde", + "socket2", + "thiserror", + "tokio", +] + +[[package]] +name = "deno_node" +version = "0.114.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "aead-gcm-stream", + "aes", + "async-trait", + "base64 0.21.7", + "blake2", + "brotli", + "bytes", + "cbc", + "const-oid", + "data-encoding", + "deno_core", + "deno_fetch", + "deno_fs", + "deno_io", + "deno_media_type", + "deno_net", + "deno_package_json", + "deno_path_util", + "deno_permissions", + "deno_whoami", + "der", + "digest", + "dsa", + "ecb", + "ecdsa", + "ed25519-dalek", + "elliptic-curve", + "errno 0.2.8", + "faster-hex", + "h2 0.4.5", + "hkdf", + "home", + "http 1.1.0", + "http-body-util", + "hyper 1.5.0", + "hyper-util", + "idna 0.3.0", + "indexmap", + "ipnetwork", + "k256", + "lazy-regex", + "libc", + "libz-sys", + "md-5", + "md4", + "memchr", + "node_resolver", + "num-bigint", + "num-bigint-dig", + "num-integer", + "num-traits", + "once_cell", + "p224", + "p256", + "p384", + "path-clean", + "pbkdf2", + "pin-project-lite", + "pkcs8", + "rand", + "regex", + "ring", + "ripemd", + "rsa", + "scrypt", + "sec1", + "serde", + "sha1", + "sha2", + "sha3", + "signature", + "simd-json", + "sm3", + "spki", + "stable_deref_trait", + "thiserror", + "tokio", + "url", + "webpki-root-certs", + "winapi", + "windows-sys 0.52.0", + "x25519-dalek", + "x509-parser", + "yoke", +] + +[[package]] +name = "deno_npm" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b4dc4a9f1cff63d5638e7d93042f24f46300d1cc77b86f3caaa699a7ddccf7" +dependencies = [ + "anyhow", + "async-trait", + "deno_lockfile", + "deno_semver", + "futures", + "log", + "monch", + "serde", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "deno_ops" +version = "0.194.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f760b492bd638c1dc3e992d11672c259fbe9a233162099a8347591c9e22d0391" +dependencies = [ + "proc-macro-rules", + "proc-macro2", + "quote", + "strum", + "strum_macros", + "syn 2.0.87", + "thiserror", +] + +[[package]] +name = "deno_package_json" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbc4c4d3eb0960b58e8f43f9fc2d3f620fcac9a03cd85203e08db5b04e83c1f" +dependencies = [ + "deno_semver", + "indexmap", + "serde", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "deno_path_util" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff25f6e08e7a0214bbacdd6f7195c7f1ebcd850c87a624e4ff06326b68b42d99" +dependencies = [ + "percent-encoding", + "thiserror", + "url", +] + +[[package]] +name = "deno_permissions" +version = "0.37.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_path_util", + "deno_terminal 0.2.0", + "fqdn", + "libc", + "log", + "once_cell", + "percent-encoding", + "serde", + "thiserror", + "which 4.4.2", + "winapi", +] + +[[package]] +name = "deno_resolver" +version = "0.9.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "anyhow", + "base32", + "deno_media_type", + "deno_package_json", + "deno_path_util", + "deno_semver", + "node_resolver", + "thiserror", + "url", +] + +[[package]] +name = "deno_runtime" +version = "0.186.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "color-print", + "deno_ast", + "deno_broadcast_channel", + "deno_cache", + "deno_canvas", + "deno_console", + "deno_core", + "deno_cron", + "deno_crypto", + "deno_fetch", + "deno_ffi", + "deno_fs", + "deno_http", + "deno_io", + "deno_kv", + "deno_napi", + "deno_net", + "deno_node", + "deno_path_util", + "deno_permissions", + "deno_terminal 0.2.0", + "deno_tls", + "deno_url", + "deno_web", + "deno_webgpu", + "deno_webidl", + "deno_websocket", + "deno_webstorage", + "dlopen2 0.6.1", + "encoding_rs", + "fastwebsockets", + "flate2", + "http 1.1.0", + "http-body-util", + "hyper 0.14.29", + "hyper 1.5.0", + "hyper-util", + "libc", + "log", + "netif", + "nix", + "node_resolver", + "notify", + "ntapi", + "once_cell", + "percent-encoding", + "regex", + "rustyline", + "same-file", + "serde", + "signal-hook", + "signal-hook-registry", + "tempfile", + "thiserror", + "tokio", + "tokio-metrics", + "twox-hash", + "uuid", + "which 4.4.2", + "winapi", + "windows-sys 0.52.0", +] + +[[package]] +name = "deno_semver" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c957c6a57c38b7dde2315df0da0ec228911e56a74f185b108a488d0401841a67" +dependencies = [ + "monch", + "once_cell", + "serde", + "thiserror", + "url", +] + +[[package]] +name = "deno_task_shell" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f444918f7102c1a5a143e9d57809e499fb4d365070519bf2e8bdb16d586af2a" +dependencies = [ + "anyhow", + "futures", + "glob", + "monch", + "os_pipe", + "path-dedot", + "thiserror", + "tokio", + "tokio-util", +] + +[[package]] +name = "deno_terminal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e6337d4e7f375f8b986409a76fbeecfa4bd8a1343e63355729ae4befa058eaf" +dependencies = [ + "once_cell", + "termcolor", +] + +[[package]] +name = "deno_terminal" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daef12499e89ee99e51ad6000a91f600d3937fb028ad4918af76810c5bc9e0d5" +dependencies = [ + "once_cell", + "termcolor", +] + +[[package]] +name = "deno_tls" +version = "0.164.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_native_certs", + "rustls", + "rustls-pemfile", + "rustls-tokio-stream", + "rustls-webpki", + "serde", + "thiserror", + "tokio", + "webpki-roots", +] + +[[package]] +name = "deno_tower_lsp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afb4d257c084fd889e8cf1ba3ad58db0002428c819cc7717815f996f97777a" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap", + "deno-tower-lsp-macros", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "deno_unsync" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f36b4ef61a04ce201b925a5dffa90f88437d37fee4836c758470dd15ba7f05e" +dependencies = [ + "parking_lot", + "tokio", +] + +[[package]] +name = "deno_url" +version = "0.177.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "thiserror", + "urlpattern", +] + +[[package]] +name = "deno_web" +version = "0.208.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "async-trait", + "base64-simd 0.8.0", + "bytes", + "deno_core", + "deno_permissions", + "encoding_rs", + "flate2", + "futures", + "serde", + "thiserror", + "tokio", + "uuid", +] + +[[package]] +name = "deno_webgpu" +version = "0.144.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "raw-window-handle", + "serde", + "thiserror", + "tokio", + "wgpu-core", + "wgpu-types", +] + +[[package]] +name = "deno_webidl" +version = "0.177.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", +] + +[[package]] +name = "deno_websocket" +version = "0.182.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "bytes", + "deno_core", + "deno_net", + "deno_permissions", + "deno_tls", + "fastwebsockets", + "h2 0.4.5", + "http 1.1.0", + "http-body-util", + "hyper 1.5.0", + "hyper-util", + "once_cell", + "rustls-tokio-stream", + "serde", + "thiserror", + "tokio", +] + +[[package]] +name = "deno_webstorage" +version = "0.172.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "deno_core", + "deno_web", + "rusqlite", + "thiserror", +] + +[[package]] +name = "deno_whoami" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75e4caa92b98a27f09c671d1399aee0f5970aa491b9a598523aac000a2192e3" +dependencies = [ + "libc", + "whoami", +] + +[[package]] +name = "denokv_proto" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7ba1f99ed11a9c11e868a8521b1f71a7e1aba785d7f42ea9ecbdc01146c89ec" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "futures", + "num-bigint", + "prost 0.13.3", + "serde", + "uuid", +] + +[[package]] +name = "denokv_remote" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ed833073189e8f6d03155fe3b05a024e75e29d8a28a4c2e9ec3b5c925e727b" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "bytes", + "chrono", + "denokv_proto", + "futures", + "http 1.1.0", + "log", + "prost 0.13.3", + "rand", + "serde", + "serde_json", + "tokio", + "tokio-util", + "url", + "uuid", +] + +[[package]] +name = "denokv_sqlite" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b790f01d1302d53a0c3cbd27de88a06b3abd64ec8ab8673924e490541c7c713" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "chrono", + "denokv_proto", + "futures", + "hex", + "log", + "num-bigint", + "rand", + "rusqlite", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", + "uuid", + "v8_valueserializer", +] + +[[package]] +name = "denort" +version = "0.3.0" +dependencies = [ + "color-eyre", + "deno", + "derive_more", + "tracing", + "tracing-subscriber", + "tracing-unwrap", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "der_derive", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.3", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.87", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "deunicode" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "dissimilar" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5" + +[[package]] +name = "dlopen2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bc2c7ed06fd72a8513ded8d0d2f6fd2655a85d6885c48cae8625d80faf28c03" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dprint-core" +version = "0.66.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab0dd2bedc109d25f0d21afb09b7d329f6c6fa83b095daf31d2d967e091548" +dependencies = [ + "anyhow", + "bumpalo", + "hashbrown 0.14.5", + "indexmap", + "rustc-hash", + "serde", + "unicode-width", +] + +[[package]] +name = "dprint-core-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1675ad2b358481f3cc46202040d64ac7a36c4ade414a696df32e0e45421a6e9f" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dprint-plugin-json" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57f91e594559b450b7c5d6a0ba9f3f9fe951c1ea371168f7c95973da3fdbd85a" +dependencies = [ + "anyhow", + "dprint-core", + "dprint-core-macros", + "jsonc-parser", + "serde", + "text_lines", +] + +[[package]] +name = "dprint-plugin-jupyter" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d20684e37b3824e2bc917cfcb14e2cdf88398eef507335d839cbd78172bfee" +dependencies = [ + "anyhow", + "dprint-core", + "jsonc-parser", + "serde", + "serde_json", +] + +[[package]] +name = "dprint-plugin-markdown" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934a8e33f6f373b2fb66c288a468e3dae9a56a6c66bfecd5504fe566131afd3f" +dependencies = [ + "anyhow", + "dprint-core", + "dprint-core-macros", + "pulldown-cmark", + "regex", + "serde", + "unicode-width", +] + +[[package]] +name = "dprint-plugin-typescript" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff29fd136541e59d51946f0d2d353fefc886776f61a799ebfb5838b06cef13b" +dependencies = [ + "anyhow", + "deno_ast", + "dprint-core", + "dprint-core-macros", + "percent-encoding", + "rustc-hash", + "serde", +] + +[[package]] +name = "dprint-swc-ext" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ba28c12892aadb751c2ba7001d8460faee4748a04b4edc51c7121cc67ee03db" +dependencies = [ + "allocator-api2", + "bumpalo", + "num-bigint", + "rustc-hash", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "text_lines", +] + +[[package]] +name = "dsa" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" +dependencies = [ + "digest", + "num-bigint-dig", + "num-traits", + "pkcs8", + "rfc6979", + "sha2", + "signature", + "zeroize", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "dynasm" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" +dependencies = [ + "bitflags 1.3.2", + "byteorder", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dynasmrt" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" +dependencies = [ + "byteorder", + "dynasm", + "memmap2", +] + +[[package]] +name = "ecb" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" +dependencies = [ + "cipher", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "signature", + "subtle", + "zeroize", +] + +[[package]] +name = "ed448-goldilocks" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06924531e9e90130842b012e447f85bdaf9161bc8a0f8092be8cb70b01ebe092" +dependencies = [ + "fiat-crypto 0.1.20", + "hex", + "subtle", + "zeroize", +] + +[[package]] +name = "editpe" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48cede2bb1b07dd598d269f973792c43e0cd92686d3b452bd6e01d7a8eb01211" +dependencies = [ + "debug-ignore", + "indexmap", + "log", + "thiserror", + "zerocopy", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "base64ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "serde_json", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "entities" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "error-code" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" + +[[package]] +name = "error_reporter" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ae425815400e5ed474178a7a22e275a9687086a12ca63ec793ff292d8fdae8" + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "fancy-regex" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0678ab2d46fa5195aaf59ad034c083d351377d4af57f3e073c074d0da3e3c766" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" +dependencies = [ + "serde", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fastwebsockets" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26da0c7b5cef45c521a6f9cdfffdfeb6c9f5804fbac332deb5ae254634c7a6be" +dependencies = [ + "base64 0.21.7", + "bytes", + "http-body-util", + "hyper 1.5.0", + "hyper-util", + "pin-project", + "rand", + "sha1", + "simdutf8", + "thiserror", + "tokio", + "utf-8", +] + +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fqdn" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08b1eaa7dfddeab6036292995620bf0435712e619db6d7690605897e76975eb0" + +[[package]] +name = "from_variant" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc9cc75639b041067353b9bce2450d6847e547276c6fbe4487d7407980e07db" +dependencies = [ + "proc-macro2", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "fs3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb17cf6ed704f72485332f6ab65257460c4f9f3083934cf402bf9f5b3b600a90" +dependencies = [ + "libc", + "rustc_version 0.2.3", + "winapi", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "ghjk" +version = "0.3.0" +dependencies = [ + "ahash", + "bitflags 2.6.0", + "color-eyre", + "dashmap", + "denort", + "educe", + "futures-lite", + "itertools 0.13.0", + "once_cell", + "parking_lot", + "rand", + "regex", + "serde", + "serde_json", + "smallvec", + "smartstring", + "thiserror", + "time", + "tokio", + "tokio-stream", + "tracing", + "tracing-appender", + "tracing-error", + "tracing-futures", + "tracing-subscriber", + "tracing-unwrap", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glibc_version" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803ff7635f1ab4e2c064b68a0c60da917d3d18dc8d086130f689d62ce4f1c33e" +dependencies = [ + "regex", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "glow" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.6.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c08c1f623a8d0b722b8b99f821eb0ba672a1618f0d3b16ddbee1cedd2dd8557" +dependencies = [ + "bitflags 2.6.0", + "gpu-descriptor-types", + "hashbrown 0.14.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "gzip-header" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2" +dependencies = [ + "crc32fast", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "handlebars" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315" +dependencies = [ + "heck 0.5.0", + "log", + "num-order", + "pest", + "pest_derive", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "serde", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "serde", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "hstr" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96274be293b8877e61974a607105d09c84caebe9620b47774aa8a6b942042dd4" +dependencies = [ + "hashbrown 0.14.5", + "new_debug_unreachable", + "once_cell", + "phf", + "rustc-hash", + "triomphe", +] + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.5.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + +[[package]] +name = "import_map" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a787decc56f38d65d16d32687265045d6d6a4531b4a0e1b649def3590354e" +dependencies = [ + "indexmap", + "log", + "percent-encoding", + "serde", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.1", + "serde", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + +[[package]] +name = "is-docker" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" +dependencies = [ + "once_cell", +] + +[[package]] +name = "is-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a85abdc13717906baccb5a1e435556ce0df215f242892f721dff62bf25288f" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is-wsl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" +dependencies = [ + "is-docker", + "once_cell", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonc-parser" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b558af6b49fd918e970471374e7a798b2c9bbcda624a210ffa3901ee5614bc8e" +dependencies = [ + "serde_json", +] + +[[package]] +name = "junction" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be39922b087cecaba4e2d5592dedfc8bda5d4a5a1231f143337cca207950b61d" +dependencies = [ + "scopeguard", + "winapi", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.4", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lazy-regex" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.87", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libffi" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" +dependencies = [ + "libc", + "libffi-sys", +] + +[[package]] +name = "libffi-sys" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" +dependencies = [ + "cc", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libsui" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89795977654ad6250d6c0915411b622bac22f9efb4f852af94b2e00964cab832" +dependencies = [ + "editpe", + "libc", + "sha2", + "windows-sys 0.48.0", + "zerocopy", +] + +[[package]] +name = "libz-sys" +version = "1.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +dependencies = [ + "cc", + "cmake", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +dependencies = [ + "serde", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "lsp-types" +version = "0.97.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53353550a17c04ac46c585feb189c2db82154fc84b79c7a66c96c2c644f66071" +dependencies = [ + "bitflags 1.3.2", + "fluent-uri", + "serde", + "serde_json", + "serde_repr", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "malva" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c67b97ed99f56b86fa3c010843441f1fcdb71884bab96b8551bb3d1e7c6d529" +dependencies = [ + "aho-corasick", + "itertools 0.13.0", + "memchr", + "raffia", + "tiny_pretty", +] + +[[package]] +name = "markup_fmt" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebae65c91eab3d42231232bf48107f351e5a8d511454927218c53aeb68bbdb6f" +dependencies = [ + "aho-corasick", + "css_dataset", + "itertools 0.13.0", + "memchr", + "tiny_pretty", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "md4" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da5ac363534dce5fabf69949225e174fbf111a498bf0ff794c8ea1fba9f3dda" +dependencies = [ + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5637e166ea14be6063a3f8ba5ccb9a4159df7d8f6d61c02fc3d480b1f90dcfcb" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "monch" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52c1b33ff98142aecea13138bd399b68aa7ab5d9546c300988c345004001eea" + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "naga" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e536ae46fcab0876853bd4a632ede5df4b1c2527a58f6c5a4150fe86be858231" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.6.0", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "serde", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "napi_sym" +version = "0.107.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "quote", + "serde", + "serde_json", + "syn 2.0.87", +] + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "netif" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29a01b9f018d6b7b277fef6c79fdbd9bf17bb2d1e298238055cafab49baa5ee" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "libc", +] + +[[package]] +name = "node_resolver" +version = "0.16.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +dependencies = [ + "anyhow", + "async-trait", + "deno_media_type", + "deno_package_json", + "deno_path_util", + "futures", + "lazy-regex", + "once_cell", + "path-clean", + "regex", + "serde_json", + "thiserror", + "tokio", + "url", +] + +[[package]] +name = "nom" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "rand", + "serde", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "serde", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[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]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags 1.3.2", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "open" +version = "5.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388" +dependencies = [ + "is-wsl", + "libc", + "pathdiff", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "os_pipe" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "outref" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "p224" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c06436d66652bc2f01ade021592c80a2aad401570a18aa18b82e440d2b9aa1" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core", + "sha2", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.2", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "path-clean" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecba01bf2678719532c5e3059e0b5f0811273d94b397088b82e3bd0a78c78fdd" + +[[package]] +name = "path-dedot" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" +dependencies = [ + "once_cell", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs5" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +dependencies = [ + "aes", + "cbc", + "der", + "pbkdf2", + "scrypt", + "sha2", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "pkcs5", + "rand_core", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "pretty_yaml" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dda9a64ee7296e82d1e0f4389383e6a7d8e6e2487d8391f7d028c131395fd376" +dependencies = [ + "rowan", + "tiny_pretty", + "yaml_parser", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn 2.0.87", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-rules" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07c277e4e643ef00c1233393c673f655e3672cf7eb3ba08a00bdd0ea59139b5f" +dependencies = [ + "proc-macro-rules-macros", + "proc-macro2", + "syn 2.0.87", +] + +[[package]] +name = "proc-macro-rules-macros" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207fffb0fe655d1d47f6af98cc2793405e85929bdbc420d685554ff07be27ac7" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive 0.13.3", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.10.5", + "lazy_static", + "log", + "multimap", + "petgraph", + "prettyplease 0.1.25", + "prost 0.11.9", + "prost-types", + "regex", + "syn 1.0.109", + "tempfile", + "which 4.4.2", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pulldown-cmark" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" +dependencies = [ + "bitflags 2.6.0", + "memchr", + "unicase", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-junit" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1a341ae463320e9f8f34adda49c8a85d81d4e8f34cce4397fb0350481552224" +dependencies = [ + "chrono", + "indexmap", + "quick-xml", + "strip-ansi-escapes", + "thiserror", + "uuid", +] + +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "radix_fmt" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426" + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "raffia" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c36f58fa7ad2f26bca656054c902becddeac5582df2bb31d4b4d2a148c62cfd5" +dependencies = [ + "raffia_macro", + "smallvec", +] + +[[package]] +name = "raffia_macro" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdb50eb5bf734fa5a770680a61876a6ec77b99c1e0e52d1f18ad6ebfa85759f" +dependencies = [ + "heck 0.5.0", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "range-alloc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.6.0", + "serde", + "serde_derive", +] + +[[package]] +name = "rowan" +version = "0.15.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" +dependencies = [ + "countme", + "hashbrown 0.14.5", + "rustc-hash", + "text-size", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "runtimelib" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3d817764e3971867351e6103955b17d808f5330e9ef63aaaaab55bf8c664c1" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bytes", + "chrono", + "data-encoding", + "dirs", + "futures", + "glob", + "rand", + "ring", + "serde", + "serde_json", + "shellexpand", + "tokio", + "uuid", + "zeromq", +] + +[[package]] +name = "rusqlite" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" +dependencies = [ + "bitflags 2.6.0", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.23", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.6.0", + "errno 0.3.9", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-tokio-stream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22557157d7395bc30727745b365d923f1ecc230c4c80b176545f3f4f08c46e33" +dependencies = [ + "futures", + "rustls", + "socket2", + "tokio", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "rustyline" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a2d683a4ac90aeef5b1013933f6d977bd37d51ff3f4dad829d4931a7e6be86" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "clipboard-win", + "fd-lock", + "home", + "libc", + "log", + "memchr", + "nix", + "radix_trie", + "unicode-segmentation", + "unicode-width", + "utf8parse", + "winapi", +] + +[[package]] +name = "rustyline-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "ryu-js" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad97d4ce1560a5e27cec89519dc8300d1aa6035b099821261c651486a19e44d5" + +[[package]] +name = "saffron" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03fb9a628596fc7590eb7edbf7b0613287be78df107f5f97b118aad59fb2eea9" +dependencies = [ + "chrono", + "nom 5.1.3", +] + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.215" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "indexmap", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_v8" +version = "0.227.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a8294c2223c53bed343be8b80564ece4dc0d03b643b06fa86c4ccc0e064eda0" +dependencies = [ + "num-bigint", + "serde", + "smallvec", + "thiserror", + "v8", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shell-escape" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" + +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simd-abstraction" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987" +dependencies = [ + "outref 0.1.0", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd-json" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1df0290e9bfe79ddd5ff8798ca887cd107b75353d2957efe9777296e17f26b5" +dependencies = [ + "getrandom", + "halfbrown", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "slug" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +dependencies = [ + "deunicode", + "wasm-bindgen", +] + +[[package]] +name = "sm3" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb9a3b702d0a7e33bc4d85a14456633d2b165c2ad839c5fd9a8417c1ab15860" +dependencies = [ + "digest", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "serde", + "static_assertions", + "version_check", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "sourcemap" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "208d40b9e8cad9f93613778ea295ed8f3c2b1824217c6cfc7219d3f6f45b96d4" +dependencies = [ + "base64-simd 0.7.0", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + +[[package]] +name = "sourcemap" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d146f02f4bbbabbbe3da0f9cd3ea2ab779defc4ed1f070b5bd83ea48ed78811" +dependencies = [ + "base64-simd 0.7.0", + "bitvec", + "data-encoding", + "debugid", + "if_chain", + "rustc-hash", + "rustc_version 0.2.3", + "serde", + "serde_json", + "unicode-id-start", + "url", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spirv" +version = "0.3.0+sdk-1.3.268.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_enum" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e383308aebc257e7d7920224fa055c632478d92744eca77f99be8fa1545b90" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.87", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "swc_allocator" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76aa0eb65c0f39f9b6d82a7e5192c30f7ac9a78f084a21f270de1d8c600ca388" +dependencies = [ + "bumpalo", + "hashbrown 0.14.5", + "ptr_meta", + "rustc-hash", + "triomphe", +] + +[[package]] +name = "swc_atoms" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" +dependencies = [ + "hstr", + "once_cell", + "rustc-hash", + "serde", +] + +[[package]] +name = "swc_bundler" +version = "0.237.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77c112c218a09635d99a45802a81b4f341d6c28c81076aa2c29ba3bcd9151a9" +dependencies = [ + "anyhow", + "crc", + "indexmap", + "is-macro", + "once_cell", + "parking_lot", + "petgraph", + "radix_fmt", + "relative-path", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_loader", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_optimization", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", + "swc_graph_analyzer", + "tracing", +] + +[[package]] +name = "swc_cached" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83406221c501860fce9c27444f44125eafe9e598b8b81be7563d7036784cd05c" +dependencies = [ + "ahash", + "anyhow", + "dashmap", + "once_cell", + "regex", + "serde", +] + +[[package]] +name = "swc_common" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" +dependencies = [ + "ast_node", + "better_scoped_tls", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "rustc-hash", + "serde", + "siphasher", + "sourcemap 9.1.0", + "swc_allocator", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_config" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" +dependencies = [ + "anyhow", + "indexmap", + "serde", + "serde_json", + "swc_cached", + "swc_config_macro", +] + +[[package]] +name = "swc_config_macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c5f56139042c1a95b54f5ca48baa0e0172d369bcc9d3d473dad1de36bae8399" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "swc_ecma_ast" +version = "0.118.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" +dependencies = [ + "bitflags 2.6.0", + "is-macro", + "num-bigint", + "phf", + "scoped-tls", + "serde", + "string_enum", + "swc_atoms", + "swc_common", + "unicode-id-start", +] + +[[package]] +name = "swc_ecma_codegen" +version = "0.155.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7641608ef117cfbef9581a99d02059b522fcca75e5244fa0cbbd8606689c6f" +dependencies = [ + "memchr", + "num-bigint", + "once_cell", + "serde", + "sourcemap 9.1.0", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_codegen_macros", + "tracing", +] + +[[package]] +name = "swc_ecma_codegen_macros" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859fabde36db38634f3fad548dd5e3410c1aebba1b67a3c63e67018fa57a0bca" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "swc_ecma_loader" +version = "0.49.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55fa3d55045b97894bfb04d38aff6d6302ac8a6a38e3bb3dfb0d20475c4974a9" +dependencies = [ + "anyhow", + "pathdiff", + "serde", + "swc_atoms", + "swc_common", + "tracing", +] + +[[package]] +name = "swc_ecma_parser" +version = "0.149.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683dada14722714588b56481399c699378b35b2ba4deb5c4db2fb627a97fb54b" +dependencies = [ + "either", + "new_debug_unreachable", + "num-bigint", + "num-traits", + "phf", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_transforms_base" +version = "0.145.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" +dependencies = [ + "better_scoped_tls", + "bitflags 2.6.0", + "indexmap", + "once_cell", + "phf", + "rustc-hash", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_classes" +version = "0.134.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3d884594385bea9405a2e1721151470d9a14d3ceec5dd773c0ca6894791601" +dependencies = [ + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_macros" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500a1dadad1e0e41e417d633b3d6d5de677c9e0d3159b94ba3348436cdb15aab" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "swc_ecma_transforms_optimization" +version = "0.208.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98d8447ea20ef76958a8240feef95743702485a84331e6df5bdbe7e383c87838" +dependencies = [ + "dashmap", + "indexmap", + "once_cell", + "petgraph", + "rustc-hash", + "serde_json", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", + "swc_fast_graph", + "tracing", +] + +[[package]] +name = "swc_ecma_transforms_proposal" +version = "0.179.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79938ff510fc647febd8c6c3ef4143d099fdad87a223680e632623d056dae2dd" +dependencies = [ + "either", + "rustc-hash", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_classes", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_react" +version = "0.191.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" +dependencies = [ + "base64 0.21.7", + "dashmap", + "indexmap", + "once_cell", + "serde", + "sha1", + "string_enum", + "swc_allocator", + "swc_atoms", + "swc_common", + "swc_config", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "swc_ecma_transforms_macros", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_transforms_typescript" +version = "0.198.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15455da4768f97186c40523e83600495210c11825d3a44db43383fd81eace88d" +dependencies = [ + "ryu-js", + "serde", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_transforms_base", + "swc_ecma_transforms_react", + "swc_ecma_utils", + "swc_ecma_visit", +] + +[[package]] +name = "swc_ecma_utils" +version = "0.134.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" +dependencies = [ + "indexmap", + "num_cpus", + "once_cell", + "rustc-hash", + "ryu-js", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", + "tracing", + "unicode-id", +] + +[[package]] +name = "swc_ecma_visit" +version = "0.104.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1c6802e68e51f336e8bc9644e9ff9da75d7da9c1a6247d532f2e908aa33e81" +dependencies = [ + "new_debug_unreachable", + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63db0adcff29d220c3d151c5b25c0eabe7e32dd936212b84cdaa1392e3130497" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "swc_fast_graph" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357e2c97bb51431d65080f25b436bc4e2fc1a7f64a643bc21a8353e478dc799f" +dependencies = [ + "indexmap", + "petgraph", + "rustc-hash", + "swc_common", +] + +[[package]] +name = "swc_graph_analyzer" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84e1d24a0d6e4066b42cfc00ab9b3109e314465aa199dd3e16849ed9566dce7" +dependencies = [ + "auto_impl", + "petgraph", + "swc_common", + "swc_fast_graph", + "tracing", +] + +[[package]] +name = "swc_macros_common" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f486687bfb7b5c560868f69ed2d458b880cebc9babebcb67e49f31b55c5bf847" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "swc_visit" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ceb044142ba2719ef9eb3b6b454fce61ab849eb696c34d190f04651955c613d" +dependencies = [ + "either", + "new_debug_unreachable", +] + +[[package]] +name = "swc_visit_macros" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92807d840959f39c60ce8a774a3f83e8193c658068e6d270dbe0a05e40e90b41" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.87", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "syntect" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" +dependencies = [ + "bincode", + "bitflags 1.3.2", + "flate2", + "fnv", + "once_cell", + "onig", + "regex-syntax 0.8.5", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "walkdir", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tar" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "text-size" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a" + +[[package]] +name = "text_lines" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf" +dependencies = [ + "serde", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny_pretty" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b3f46f0549180b9c6f7f76270903f1a06867c43a03998b99dce81aa1760c3b2" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "tinyvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tokio-metrics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eace09241d62c98b7eeb1107d4c5c64ca3bd7da92e8c218c153ab3a78f9be112" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tokio-stream", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "futures-util", + "hashbrown 0.14.5", + "pin-project-lite", + "slab", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "async-compression", + "bitflags 2.6.0", + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "parking_lot", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-unwrap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4e33415be97f5ae70322d6fefc696bbc08887d8835400d6c77f059469b30354" +dependencies = [ + "tracing", +] + +[[package]] +name = "triomphe" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" +dependencies = [ + "serde", + "stable_deref_trait", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "rand", + "static_assertions", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unic-char-property" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" +dependencies = [ + "unic-char-range", +] + +[[package]] +name = "unic-char-range" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" + +[[package]] +name = "unic-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" + +[[package]] +name = "unic-ucd-ident" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" +dependencies = [ + "unic-char-property", + "unic-char-range", + "unic-ucd-version", +] + +[[package]] +name = "unic-ucd-version" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" +dependencies = [ + "unic-common", +] + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + +[[package]] +name = "unicode-id-start" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f322b60f6b9736017344fa0635d64be2f458fbc04eef65f6be22976dd1ffd5b" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna 0.4.0", + "percent-encoding", + "serde", +] + +[[package]] +name = "urlpattern" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" +dependencies = [ + "regex", + "serde", + "unic-ucd-ident", + "url", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" +dependencies = [ + "getrandom", + "serde", + "sha1_smol", +] + +[[package]] +name = "v8" +version = "0.106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a381badc47c6f15acb5fe0b5b40234162349ed9d4e4fd7c83a7f5547c0fc69c5" +dependencies = [ + "bindgen", + "bitflags 2.6.0", + "fslock", + "gzip-header", + "home", + "miniz_oxide", + "once_cell", + "paste", + "which 6.0.1", +] + +[[package]] +name = "v8_valueserializer" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97599c400fc79925922b58303e98fcb8fa88f573379a08ddb652e72cbd2e70f6" +dependencies = [ + "bitflags 2.6.0", + "encoding_rs", + "indexmap", + "num-bigint", + "serde", + "thiserror", + "wtf8", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-trait" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9170e001f458781e92711d2ad666110f153e4e50bfd5cbd02db6547625714187" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "arrayvec", + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c6dfa3ac045bc517de14c7b1384298de1dbd229d38e08e169d9ae8c170937c" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "wgpu-core" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50819ab545b867d8a454d1d756b90cd5f15da1f2943334ca314af10583c9d39" +dependencies = [ + "arrayvec", + "bit-vec", + "bitflags 2.6.0", + "cfg_aliases", + "codespan-reporting", + "document-features", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "profiling", + "raw-window-handle", + "ron", + "rustc-hash", + "serde", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "172e490a87295564f3fcc0f165798d87386f6231b04d4548bca458cbbfd63222" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.6.0", + "block", + "cfg_aliases", + "core-graphics-types", + "d3d12", + "glow", + "glutin_wgl_sys", + "gpu-alloc", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libc", + "libloading 0.8.4", + "log", + "metal", + "naga", + "ndk-sys", + "objc", + "once_cell", + "parking_lot", + "profiling", + "range-alloc", + "raw-window-handle", + "rustc-hash", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1353d9a46bff7f955a680577f34c69122628cc2076e1d6f3a9be6ef00ae793ef" +dependencies = [ + "bitflags 2.6.0", + "js-sys", + "serde", + "web-sys", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "which" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "whoami" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +dependencies = [ + "redox_syscall 0.4.1", + "wasite", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winres" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" +dependencies = [ + "toml", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wtf8" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01ae8492c38f52376efd3a17d0994b6bcf3df1e39c0226d458b7d81670b2a06" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xattr" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +dependencies = [ + "libc", + "linux-raw-sys", + "rustix", +] + +[[package]] +name = "xml-rs" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" + +[[package]] +name = "xtask" +version = "0.3.0" +dependencies = [ + "clap", + "color-eyre", + "denort", + "tracing", + "tracing-subscriber", + "tracing-unwrap", +] + +[[package]] +name = "yaml_parser" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c551c67700672ec050a94d5d917487c0ecd644a12735133df65564779c5b7b" +dependencies = [ + "rowan", + "winnow", +] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure 0.13.1", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure 0.13.1", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zeromq" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0560d00172817b7f7c2265060783519c475702ae290b154115ca75e976d4d0" +dependencies = [ + "async-trait", + "asynchronous-codec", + "bytes", + "crossbeam-queue", + "dashmap", + "futures-channel", + "futures-io", + "futures-task", + "futures-util", + "log", + "num-traits", + "once_cell", + "parking_lot", + "rand", + "regex", + "thiserror", + "tokio", + "tokio-util", + "uuid", +] + +[[package]] +name = "zip" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "memchr", + "thiserror", +] + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.11+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e9fcbbf --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[workspace] +members = ["src/*"] +resolver = "2" + +[workspace.package] +version = "0.3.0" +edition = "2021" + +[workspace.dependencies] +denort = { path = "src/denort" } + +color-eyre = "0.6" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = [ + "env-filter", + "parking_lot", + "tracing-log" +] } +tracing-unwrap = "1.0" diff --git a/ghjk.ts b/ghjk.ts index 8c7952b..57c16d6 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -1,20 +1,40 @@ // @ts-nocheck: Ghjkfile based on Deno export { sophon } from "./hack.ts"; -import { config, install, task } from "./hack.ts"; +import { config, env, install, task } from "./hack.ts"; import * as ports from "./ports/mod.ts"; import { sedLock } from "./std.ts"; config({ - defaultBaseEnv: "test", + defaultEnv: "dev", enableRuntimes: true, allowedBuildDeps: [ports.cpy_bs({ version: "3.12.7" })], }); -// these are just for quick testing +env("_rust") + .install( + ports.protoc(), + ports.pipi({ packageName: "cmake" })[0], + // keep in sync with deno's reqs + ports.rust({ + version: "1.82.0", + profile: "default", + components: ["rustfmt", "clippy",], + }), + ); + +const RUSTY_V8_MIRROR = "~/.cache/rusty_v8"; + +env("dev") + .inherit("_rust") + .vars({ + RUSTY_V8_MIRROR, + }); + +// these are just for quick testing install(); -const DENO_VERSION = "1.44.2"; +const DENO_VERSION = "2.0.6"; // these are used for developing ghjk install( @@ -32,6 +52,9 @@ task( $.path(import.meta.dirname!), { lines: { + "./Cargo.toml": [ + [/(version = ").*(")/, GHJK_VERSION], + ], "./.github/workflows/*.yml": [ [/(DENO_VERSION: ").*(")/, DENO_VERSION], ], diff --git a/src/denort/Cargo.toml b/src/denort/Cargo.toml new file mode 100644 index 0000000..777b642 --- /dev/null +++ b/src/denort/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "denort" +version.workspace = true +edition.workspace = true + +[lib] +path = "lib.rs" + +[dependencies] +tracing-unwrap.workspace = true + +color-eyre.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true + +deno = { git = "https://github.com/metatypedev/deno", branch = "v2.0.6-embeddable" } +# deno_core = "=0.291.0" +# breaking changes to .18 +# https://github.com/JelteF/derive_more/issues/373 +derive_more = "=0.99.17" diff --git a/src/denort/lib.rs b/src/denort/lib.rs new file mode 100644 index 0000000..430bc96 --- /dev/null +++ b/src/denort/lib.rs @@ -0,0 +1,411 @@ +#![allow(dead_code, clippy::let_and_return)] + +mod interlude { + pub use std::future::Future; + pub use std::path::{Path, PathBuf}; + pub use std::sync::Arc; + + pub use color_eyre::eyre; + pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; + pub use tracing::{debug, error, info, trace, warn}; + pub use tracing_unwrap::*; +} +use crate::interlude::*; + +pub use deno; +use deno::{ + deno_runtime::{ + deno_core::{futures::FutureExt, unsync::JoinHandle, ModuleSpecifier}, + deno_permissions, + deno_permissions::PermissionsOptions, + tokio_util::create_and_run_current_thread_with_maybe_metrics, + }, + *, +}; + +#[rustfmt::skip] +use deno_runtime::deno_core as deno_core; // necessary for re-exported macros to work + +use std::path::PathBuf; + +const DEFAULT_UNSTABLE_FLAGS: &[&str] = &["worker-options", "net"]; +const CACHE_BLOCKLIST: &[&str] = &[]; + +/// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these +/// futures are very large, this prevents the stack from getting blown out from passing them by value up +/// the callchain (especially in debug mode when Rust doesn't have a chance to elide copies!). +#[inline(always)] +fn spawn_subcommand + 'static>(f: F) -> JoinHandle<()> { + // the boxed_local() is important in order to get windows to not blow the stack in debug + deno_core::unsync::spawn(f.boxed_local()) +} + +pub fn run_sync( + main_mod: ModuleSpecifier, + import_map_url: Option, + permissions: PermissionsOptions, + custom_extensions: Arc, +) { + create_and_run_current_thread_with_maybe_metrics(async move { + spawn_subcommand(async move { + run(main_mod, import_map_url, permissions, custom_extensions) + .await + .unwrap() + }) + .await + .unwrap() + }); +} + +pub async fn run( + main_module: ModuleSpecifier, + import_map_url: Option, + permissions: PermissionsOptions, + custom_extensions: Arc, +) -> Res<()> { + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); + + deno_permissions::set_prompt_callbacks( + Box::new(util::draw_thread::DrawThread::hide), + Box::new(util::draw_thread::DrawThread::show), + ); + + let flags = args::Flags { + // NOTE: avoid using the Run subcommand + // as it breaks our custom_extensions patch for some reason + import_map_path: import_map_url, + unstable_config: args::UnstableConfig { + features: DEFAULT_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..Default::default() + }, + #[cfg(debug_assertions)] + cache_blocklist: CACHE_BLOCKLIST + .iter() + .cloned() + .map(str::to_string) + .collect(), + ..Default::default() + }; + + let cli_factory = factory::CliFactory::from_flags(flags)?.with_custom_ext_cb(custom_extensions); + + let worker_factory = cli_factory.create_cli_main_worker_factory().await?; + let permissions = deno_permissions::PermissionsContainer::new( + deno_permissions::Permissions::from_options(&permissions)?, + ); + let mut worker = worker_factory + .create_main_worker( + deno_runtime::WorkerExecutionMode::Run, + main_module, + permissions, + ) + .await?; + info!("running worker"); + let exit_code = worker.run().await?; + println!("exit_code: {exit_code}"); + Ok(()) +} + +pub fn test_sync( + files: deno_config::glob::FilePatterns, + permissions: PermissionsOptions, + custom_extensions: Arc, + config_file: Option, + coverage_dir: Option, + argv: Vec, +) { + new_thread_builder() + .spawn(|| { + create_and_run_current_thread_with_maybe_metrics(async move { + spawn_subcommand(async move { + test( + files, + config_file, + permissions, + coverage_dir, + custom_extensions, + argv, + ) + .await + .unwrap() + }) + .await + .unwrap() + }) + }) + .unwrap() + .join() + .unwrap(); +} + +pub async fn test( + files: deno_config::glob::FilePatterns, + custom_extensions: Arc, + permissions: PermissionsOptions, + config_file: Option, + coverage_dir: Option, + argv: Vec, +) -> Res<()> { + use deno::tools::test::*; + + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); + + deno_permissions::set_prompt_callbacks( + Box::new(util::draw_thread::DrawThread::hide), + Box::new(util::draw_thread::DrawThread::show), + ); + let pattern_to_str = |pattern| match pattern { + deno_config::glob::PathOrPattern::Path(path) => path.to_string_lossy().to_string(), + deno_config::glob::PathOrPattern::Pattern(pattern) => pattern.as_str().to_string(), + deno_config::glob::PathOrPattern::RemoteUrl(url) => url.as_str().to_owned(), + deno_config::glob::PathOrPattern::NegatedPath(path) => path.to_string_lossy().to_string(), + }; + + let test_flags = args::TestFlags { + files: args::FileFlags { + include: files + .include + .clone() + .map(|set| set.into_path_or_patterns().into_iter()) + .unwrap_or_default() + .map(pattern_to_str) + .collect(), + ignore: files + .exclude + .clone() + .into_path_or_patterns() + .into_iter() + .map(pattern_to_str) + .collect(), + }, + doc: false, + trace_leaks: true, + coverage_dir, + ..Default::default() + }; + let flags = args::Flags { + unstable_config: args::UnstableConfig { + features: DEFAULT_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..Default::default() + }, + type_check_mode: args::TypeCheckMode::Local, + config_flag: config_file + .map(|config_file| deno_config::ConfigFlag::Path(config_file.to_string_lossy().into())) + .unwrap_or(deno_config::ConfigFlag::Discover), + argv, + subcommand: args::DenoSubcommand::Test(test_flags.clone()), + cache_blocklist: CACHE_BLOCKLIST + .iter() + .cloned() + .map(str::to_string) + .collect(), + ..Default::default() + }; + + let cli_factory = factory::CliFactory::from_flags(flags)?.with_custom_ext_cb(custom_extensions); + + let options = cli_factory.cli_options().clone(); + + let test_options = args::TestOptions { + files, + ..options.resolve_test_options(test_flags)? + }; + let file_fetcher = cli_factory.file_fetcher()?; + + // Various test files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. + let permissions = deno_permissions::Permissions::from_options(&permissions)?; + + let specifiers_with_mode = fetch_specifiers_with_test_mode( + options.as_ref(), + file_fetcher, + test_options.files, + &test_options.doc, + ) + .await?; + + if !test_options.allow_none && specifiers_with_mode.is_empty() { + return Err(deno_core::error::generic_error("No test modules found")); + } + + let main_graph_container = cli_factory.main_module_graph_container().await?; + + check_specifiers( + file_fetcher, + main_graph_container, + specifiers_with_mode.clone(), + ) + .await?; + + if test_options.no_run { + return Ok(()); + } + + let worker_factory = cli_factory.create_cli_main_worker_factory().await?; + let worker_factory = Arc::new(worker_factory); + + test_specifiers( + worker_factory, + &permissions, + specifiers_with_mode + .into_iter() + .filter_map(|(s, m)| match m { + TestMode::Documentation => None, + _ => Some(s), + }) + .collect(), + TestSpecifiersOptions { + cwd: deno_core::url::Url::from_directory_path(options.initial_cwd()).map_err(|_| { + ferr!( + "Unable to construct URL from the path of cwd: {}", + options.initial_cwd().to_string_lossy(), + ) + })?, + concurrent_jobs: test_options.concurrent_jobs, + fail_fast: test_options.fail_fast, + log_level: options.log_level(), + filter: test_options.filter.is_some(), + reporter: test_options.reporter, + junit_path: test_options.junit_path, + specifier: TestSpecifierOptions { + filter: TestFilter::from_flag(&test_options.filter), + shuffle: test_options.shuffle, + trace_leaks: test_options.trace_leaks, + }, + }, + ) + .await?; + + Ok(()) +} + +fn new_thread_builder() -> std::thread::Builder { + let builder = std::thread::Builder::new(); + let builder = if cfg!(debug_assertions) { + // this is only relevant for WebWorkers + // FIXME: find a better location for this as tihs won't work + // if a new thread has already launched by this point + if std::env::var("RUST_MIN_STACK").is_err() { + std::env::set_var("RUST_MIN_STACK", "8388608"); + } + // deno & swc need 8 MiB with dev profile (release is ok) + // https://github.com/swc-project/swc/blob/main/CONTRIBUTING.md + builder.stack_size(8 * 1024 * 1024) + } else { + // leave default: https://doc.rust-lang.org/std/thread/#stack-size + builder + }; + builder +} + +pub fn bench_sync( + files: deno_config::glob::FilePatterns, + config_file: PathBuf, + permissions: PermissionsOptions, + custom_extensions: Arc, + argv: Vec, +) { + new_thread_builder() + .spawn(|| { + create_and_run_current_thread_with_maybe_metrics(async move { + spawn_subcommand(async move { + bench(files, config_file, permissions, custom_extensions, argv) + .await + .unwrap() + }) + .await + .unwrap() + }) + }) + .unwrap() + .join() + .unwrap(); +} + +pub async fn bench( + files: deno_config::glob::FilePatterns, + config_file: PathBuf, + permissions: PermissionsOptions, + custom_extensions: Arc, + argv: Vec, +) -> Res<()> { + use deno::tools::bench::*; + use deno::tools::test::TestFilter; + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); + + deno_permissions::set_prompt_callbacks( + Box::new(util::draw_thread::DrawThread::hide), + Box::new(util::draw_thread::DrawThread::show), + ); + let flags = args::Flags { + unstable_config: args::UnstableConfig { + features: DEFAULT_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..Default::default() + }, + type_check_mode: args::TypeCheckMode::Local, + config_flag: deno_config::ConfigFlag::Path(config_file.to_string_lossy().into()), + argv, + ..Default::default() + }; + + let bench_options = args::BenchOptions { + ..args::BenchOptions::resolve( + Some(deno_config::BenchConfig { files }), + None, + &std::env::current_dir()?, + )? + }; + let cli_factory = factory::CliFactory::from_flags(flags)?.with_custom_ext_cb(custom_extensions); + + let options = cli_factory.cli_options(); + + // Various bench files should not share the same permissions in terms of + // `PermissionsContainer` - otherwise granting/revoking permissions in one + // file would have impact on other files, which is undesirable. + let permissions = deno_permissions::Permissions::from_options(&permissions)?; + + let specifiers = util::fs::collect_specifiers( + bench_options.files, + options.vendor_dir_path().map(ToOwned::to_owned), + is_supported_bench_path, + )?; + + if specifiers.is_empty() { + return Err(deno_core::error::generic_error("No bench modules found")); + } + + let main_graph_container = cli_factory.main_module_graph_container().await?; + main_graph_container.check_specifiers(&specifiers).await?; + + if bench_options.no_run { + return Ok(()); + } + + let log_level = options.log_level(); + let worker_factory = Arc::new(cli_factory.create_cli_main_worker_factory().await?); + bench_specifiers( + worker_factory, + &permissions, + specifiers, + BenchSpecifierOptions { + filter: TestFilter::from_flag(&bench_options.filter), + json: bench_options.json, + log_level, + }, + ) + .await?; + Ok(()) +} diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml new file mode 100644 index 0000000..dca833b --- /dev/null +++ b/src/ghjk/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "ghjk" +version.workspace = true +edition.workspace = true + +[[bin]] +name = "ghjk" +path = "main.rs" + +[dependencies] +denort.workspace = true + +serde = "1" +serde_json = "1" +ahash = { version = "0.8", features = ["serde"] } +# serde_repr = { version = "0.1" } + +regex = "1.10" +rand = "0.8" +time = { version = "0.3", features = ["serde"] } +once_cell = "1.19" +parking_lot = "*" +bitflags = "*" +itertools = "*" + +smallvec = { version = "1", features = [ + "serde", + "const_generics", + "const_new", + "union", +] } +smartstring = { version = "1", features = ["serde"] } + +educe = "0.6" + +thiserror = "1" +tracing-error = "0.2" +tracing-unwrap.workspace = true + +color-eyre.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +tracing-appender = "0.2" +tracing-futures = "0.2" + +futures-lite = "2" +tokio = { version = "1", features = ["full", "parking_lot"] } +tokio-stream = "0.1" + +dashmap = { version = "5.5", features = ["serde"]} + +# version must match on clap in `deno` +# clap = { version = "=4.4", features = ["derive", "env"] } diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs new file mode 100644 index 0000000..232ec40 --- /dev/null +++ b/src/ghjk/main.rs @@ -0,0 +1,153 @@ +mod interlude { + pub use crate::utils::{default, CHeapStr, DHashMap}; + + pub use std::future::Future; + pub use std::path::{Path, PathBuf}; + pub use std::sync::Arc; + + pub use color_eyre::eyre; + pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; + pub use futures_lite::{future::Boxed as BoxedFut, FutureExt}; + pub use serde::{Deserialize, Serialize}; + pub use serde_json::json; + pub use smallvec::smallvec as svec; + pub use smallvec::SmallVec as Svec; + pub use tracing::{debug, error, info, trace, warn}; + pub use tracing_unwrap::*; +} +mod utils; + +use crate::interlude::*; + +fn main() -> Res<()> { + utils::setup_tracing()?; + + denort::run( + "main.ts".parse()?, + None, + deno::deno_runtime::permissions::PermissionsOptions { + allow_all: true, + ..default() + }, + Arc::new(|| None), + ); + + Ok(()) +} + +mod play {} + +fn play() { + struct GraphQlTransport; + impl GraphQlTransport { + fn new() -> Self { + Self + } + } + + struct SelctFieldParamUnselected { + args: Args, + _phantom: std::marker::PhantomData, - } - impl SelctFieldParamUnselected { - fn select(self, select: Select) -> SelectFieldParam { - SelectFieldParam { - args: self.args, - select, - } - } - } - - struct SelectFieldParam { - args: Args, - select: Select, - } - - struct QueryGraph; - impl QueryGraph { - fn new() -> Self { - Self - } - fn graphql(&self) -> GraphQlTransport { - GraphQlTransport::new() - } - - fn args(&self, args: Args) -> SelectFieldParam { - SelctFieldParamUnselected { - args, - _phantom: std::marker::PhantomData, - } - } - - fn get_user(&self, args: GetUserArgs) -> GetUserUnselected { - return GetUserUnselected { args }; - } - } - - trait QueryNode { - type Out; - } - - #[derive(Default)] - struct UserPartial { - id: Option, - email: Option, - posts: Option>, - } - struct GetUserArgs { - id: String, - } - struct GetUserUnselected { - args: GetUserArgs, - } - impl GetUserUnselected { - fn select(self, args: GetUserSelect) -> GetUserNode { - GetUserNode { - args: self.args, - select, - } - } - } - - struct GetUserNode { - args: GetUserArgs, - select: GetUserSelect, - } - impl QueryNode for GetUserNode { - type Out = UserPartial; - } - - #[derive(Default)] - struct GetUserSelect { - email: bool, - posts: Option>, - } - #[derive(Default)] - struct PostPartial { - slug: Option, - title: Option, - } - #[derive(Default)] - struct PostArgs { - filter: String, - } - #[derive(Default)] - struct PostSelectParams { - slug: bool, - title: bool, - } - - let api1 = QueryGraph::new(); - let gql_client = api1.graphql(); - - let (user, posts) = gql_client.query(( - api1.get_user(GetUserArgs { id: "1234".into() }) - .select(GetUserSelect { - email: true, - posts: Some(api1.args("hey")), - }), - api1.get_post(PostArgs { - filter: "today".into(), - }), - )); -} diff --git a/src/xtask/Cargo.toml b/src/xtask/Cargo.toml index 19a288b..d754ad9 100644 --- a/src/xtask/Cargo.toml +++ b/src/xtask/Cargo.toml @@ -15,5 +15,6 @@ tracing-unwrap.workspace = true color-eyre.workspace = true tracing.workspace = true tracing-subscriber.workspace = true +once_cell.workspace = true # version must match on clap in `deno` clap = { version = "=4.5", features = ["derive", "env"] } diff --git a/src/xtask/main.rs b/src/xtask/main.rs index 9185ca5..a4d1dd3 100644 --- a/src/xtask/main.rs +++ b/src/xtask/main.rs @@ -1,3 +1,4 @@ +#[allow(unused)] mod interlude { pub use std::future::Future; pub use std::path::{Path, PathBuf}; @@ -10,32 +11,38 @@ mod interlude { } use crate::interlude::*; +mod utils; + fn main() -> Res<()> { + utils::setup_tracing()?; + use clap::Parser; let args = Args::parse(); match args.command { - Commands::Test { files } => { + Commands::Test { files, filter } => { use denort::deno::deno_config; - use denort::deno::deno_runtime; + let cwd = std::process::working_dir(); denort::test_sync( deno_config::glob::FilePatterns { - base: std::env::current_dir()?, include: files.map(|vec| { deno_config::glob::PathOrPatternSet::new( vec.into_iter() - .map(deno_config::glob::PathOrPattern::Path) - .collect(), + .map(|path| { + deno_config::glob::PathOrPattern::from_relative(&cwd, path) + }) + .collect::>()?, ) }), exclude: deno_config::glob::PathOrPatternSet::new(vec![]), }, - deno_runtime::permissions::PermissionsOptions { + "deno.jsonc".into(), + denort::deno::args::PermissionFlags { allow_all: true, ..Default::default() }, - Arc::new(|| None), - None, None, + filter, + Arc::new(|| vec![]), vec![], ) } @@ -56,5 +63,8 @@ enum Commands { Test { /// Files to test files: Option>, + /// Tests to include + #[arg(long)] + filter: Option, }, } diff --git a/src/xtask/utils.rs b/src/xtask/utils.rs new file mode 100644 index 0000000..ed0c548 --- /dev/null +++ b/src/xtask/utils.rs @@ -0,0 +1,28 @@ +use crate::interlude::*; + +// Ensure that the `tracing` stack is only initialised once using `once_cell` +// isn't required in cargo-nextest since each test runs in a new process +pub fn setup_tracing_once() { + use once_cell::sync::Lazy; + static TRACING: Lazy<()> = Lazy::new(|| { + setup_tracing().expect("failed to init tracing"); + }); + Lazy::force(&TRACING); +} + +pub fn setup_tracing() -> eyre::Result<()> { + color_eyre::install()?; + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "info"); + } + + // tracing_log::LogTracer::init()?; + tracing_subscriber::fmt() + .compact() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .with_timer(tracing_subscriber::fmt::time::uptime()) + .try_init() + .map_err(|err| eyre::eyre!(err))?; + + Ok(()) +} diff --git a/std/sedLock.ts b/std/sedLock.ts index c94961b..a32af00 100644 --- a/std/sedLock.ts +++ b/std/sedLock.ts @@ -1,3 +1,7 @@ +/** + * TODO: show diff on replacement. + */ + import { $, Path, unwrapZodRes } from "../utils/mod.ts"; import { std_fs, zod } from "../deps/common.ts"; diff --git a/utils/mod.ts b/utils/mod.ts index 0468842..f471c2d 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -409,6 +409,7 @@ export type DownloadFileArgs = { export async function downloadFile( args: DownloadFileArgs, ) { + logger().debug("downloading", args); const { name, mode, url, downloadPath, tmpDirPath, headers } = { name: $.path(args.url).basename(), mode: 0o666, @@ -542,33 +543,37 @@ export function thinInstallConfig(fat: InstallConfigFat) { export type OrRetOf = T extends () => infer Inner ? Inner : T; +/** + * This tries to emulate a rust `match` statement but in a typesafe + * way. This is a WIP function. + * ```ts + * const pick: 2 = switchMap( + * "hello", + * { + * hey: () => 1, + * hello: () => 2, + * hi: 3, + * holla: 4, + * }, + * ); + * ``` + */ export function switchMap< K extends string | number | symbol, All extends { - [Key in K]: All[K]; + [Key in K]?: All[K]; }, ->( +> // D = undefined, +( val: K, branches: All, - // def?: D, + // def?: (val: K) => D, ): K extends keyof All ? OrRetOf - : /* All[keyof All] | */ undefined { - // return branches[val]; + : OrRetOf | undefined { const branch = branches[val]; return typeof branch == "function" ? branch() : branch; } -switchMap( - "holla" as string, - { - hey: () => 1, - hello: () => 2, - hi: 3, - holla: 4, - } as const, - // () =>5 -); - export async function expandGlobsAndAbsolutize( path: string, wd: string, diff --git a/utils/unarchive.ts b/utils/unarchive.ts index 4ff3b3f..cbc2b5b 100644 --- a/utils/unarchive.ts +++ b/utils/unarchive.ts @@ -4,7 +4,6 @@ import { std_fs, std_io, std_path, - std_streams, std_untar, } from "../deps/ports.ts"; @@ -45,7 +44,7 @@ export async function untgz( await Foras.initBundledOnce(); const tgzFile = await Deno.open(path, { read: true }); const gzDec = new Foras.GzDecoder(); - await std_streams.copy(tgzFile, { + await std_io.copy(tgzFile, { write(buf) { const mem = new Foras.Memory(buf); gzDec.write(mem); @@ -77,7 +76,7 @@ export async function untar( * This does not close the reader. */ export async function untarReader( - reader: Deno.Reader, + reader: std_io.Reader, dest = "./", ) { for await (const entry of new std_untar.Untar(reader)) { @@ -93,7 +92,7 @@ export async function untarReader( write: true, mode: entry.fileMode, }); - await std_streams.copy(entry, file); + await std_io.copy(entry, file); file.close(); } } From 08ad55a1418f2aa7d93d3797ad68ded112f8ef32 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:48:43 +0300 Subject: [PATCH 04/15] refactor: cargo x test --- .ghjk/lock.json | 32 +++++++++++++++++++++----- .pre-commit-config.yaml | 13 +++++++++++ ghjk.ts | 50 ++++++++++++++++++++++++----------------- src/denort/lib.rs | 10 ++++----- src/ghjk/main.rs | 2 +- src/ghjk/utils.rs | 10 ++++----- src/xtask/main.rs | 26 +++++++++++++-------- src/xtask/utils.rs | 3 ++- tests/utils.ts | 1 + utils/mod.ts | 1 + 10 files changed, 100 insertions(+), 48 deletions(-) diff --git a/.ghjk/lock.json b/.ghjk/lock.json index 391b826..b597a41 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -224,6 +224,30 @@ "rust-src" ], "specifiedVersion": true + }, + "bciqar6zz2xgxmu5i2jp5nuj4wsogcl7pxsqs3w55mibcsbks5iimsyy": { + "version": "1.82.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "default", + "components": [ + "rust-src" + ], + "specifiedVersion": true } } }, @@ -253,7 +277,7 @@ "installs": [ "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", - "bciqlfevxqitow2d3l3bbsvpy2p42aqcwhyhbavt2pvp4v3n2z22xzza", + "bciqgkc6fegmxehj4whmusfuurxyp4ayeysn6qa2t6q64baac5is7uui", "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", @@ -266,7 +290,7 @@ "bciqlmoqot4jk2lb2b34pldr5iiwsfm3biuipzesjkkwmc2n2o6nlw4q", "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", - "bciqlfevxqitow2d3l3bbsvpy2p42aqcwhyhbavt2pvp4v3n2z22xzza", + "bciqgkc6fegmxehj4whmusfuurxyp4ayeysn6qa2t6q64baac5is7uui", "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", @@ -810,7 +834,7 @@ }, "packageName": "cmake" }, - "bciqlfevxqitow2d3l3bbsvpy2p42aqcwhyhbavt2pvp4v3n2z22xzza": { + "bciqgkc6fegmxehj4whmusfuurxyp4ayeysn6qa2t6q64baac5is7uui": { "version": "1.82.0", "port": { "ty": "denoWorker@v1", @@ -845,8 +869,6 @@ }, "profile": "default", "components": [ - "rustfmt", - "clippy", "rust-src" ] }, diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 456dbb5..f92f43a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -66,3 +66,16 @@ repos: pass_filenames: false types: - ts + - repo: https://github.com/doublify/pre-commit-rust + rev: v1.0 + hooks: + - id: fmt + exclude: tests/metagen/typegraphs/sample/rs/client.rs + - id: clippy + args: + - "--locked" + - "--all-features" + - "--all-targets" + - "--" + - "--deny" + - "warnings" diff --git a/ghjk.ts b/ghjk.ts index 3cb25af..9cf3a48 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -5,7 +5,7 @@ import { config, env, install, task } from "./hack.ts"; import { switchMap } from "./port.ts"; import * as ports from "./ports/mod.ts"; import { sedLock } from "./std.ts"; -import { dbg, downloadFile, DownloadFileArgs } from "./utils/mod.ts"; +import { downloadFile, DownloadFileArgs } from "./utils/mod.ts"; import { unarchive } from "./utils/unarchive.ts"; config({ @@ -22,7 +22,7 @@ env("_rust") ports.rust({ version: "1.82.0", profile: "default", - components: ["rustfmt", "clippy", "rust-src"], + components: ["rust-src"], }), ); @@ -31,6 +31,7 @@ const RUSTY_V8_MIRROR = `${import.meta.dirname}/.dev/rusty_v8`; env("dev") .inherit("_rust") .vars({ + // V8_FORCE_DEBUG: "true", RUSTY_V8_MIRROR, }); @@ -62,31 +63,38 @@ task( inherit: "_rust", fn: async ($) => { const tmpDirPath = await Deno.makeTempDir({}); - const v8Versions = (await $`cargo tree -p v8 --depth 0 --locked` - .text()) - .matchAll(/^v8 (v[\d.]*)/) - .map((match) => match[1]); + const v8Versions = [ + ...(await $`cargo tree -p v8 --depth 0 --locked` + .text()) + .matchAll(/^v8 (v[\d.]*)/g) + .map((match) => match[1]), + ]; - $.co( - v8Versions.map( - async (version) => { - const archiveName = `librusty_v8_release_${Deno.build.arch}-${ - switchMap(Deno.build.os, { + await $.co( + v8Versions + .flatMap( + (version) => { + const os = switchMap(Deno.build.os, { linux: "unknown-linux-gnu", darwin: "apple-darwin", - }) ?? "NOT_SUPPORTED" - }.a.gz`; - const archivePath = await downloadFile( - { + }) ?? "NOT_SUPPORTED"; + const arch = Deno.build.arch; + return [ + `librusty_v8_release_${arch}-${os}.a.gz`, + `librusty_v8_debug_${arch}-${os}.a.gz`, + ].map((archiveName) => ({ + archiveName, url: `https://github.com/denoland/rusty_v8/releases/download/${version}/${archiveName}`, - downloadPath: $.path(RUSTY_V8_MIRROR).join(version) - .toString(), + downloadPath: $.path(RUSTY_V8_MIRROR).join(version).toString(), tmpDirPath, - } satisfies DownloadFileArgs, - ); - }, - ), + } satisfies DownloadFileArgs)); + }, + ) + .filter((args) => + !$.path(args.downloadPath).join(args.archiveName).existsSync() + ) + .map((args) => downloadFile(args)), ); await $.path(tmpDirPath).remove({ recursive: true }); }, diff --git a/src/denort/lib.rs b/src/denort/lib.rs index fe1bb04..9c31b69 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -49,6 +49,7 @@ pub fn run_sync( permissions: args::PermissionFlags, custom_extensions: Arc, ) { + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); new_thread_builder() .spawn(|| { create_and_run_current_thread_with_maybe_metrics(async move { @@ -72,8 +73,6 @@ pub async fn run( permissions: args::PermissionFlags, custom_extensions: Arc, ) -> anyhow::Result<()> { - deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); - deno_permissions::set_prompt_callbacks( Box::new(util::draw_thread::DrawThread::hide), Box::new(util::draw_thread::DrawThread::show), @@ -125,6 +124,7 @@ pub fn test_sync( custom_extensions: Arc, argv: Vec, ) { + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); new_thread_builder() .spawn(|| { create_and_run_current_thread_with_maybe_metrics(async move { @@ -161,8 +161,6 @@ pub async fn test( ) -> anyhow::Result<()> { use deno::tools::test::*; - deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); - deno_permissions::set_prompt_callbacks( Box::new(util::draw_thread::DrawThread::hide), Box::new(util::draw_thread::DrawThread::show), @@ -174,7 +172,7 @@ pub async fn test( deno_config::glob::PathOrPattern::NegatedPath(path) => path.to_string_lossy().to_string(), }; - let test_flags = dbg!(args::TestFlags { + let test_flags = args::TestFlags { files: args::FileFlags { include: files .include @@ -197,7 +195,7 @@ pub async fn test( filter, concurrent_jobs: std::thread::available_parallelism().ok(), ..Default::default() - }); + }; let flags = args::Flags { permissions, unstable_config: args::UnstableConfig { diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index 51788db..bfbfb5b 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -30,7 +30,7 @@ fn main() -> Res<()> { allow_all: true, ..default() }, - Arc::new(|| vec![]), + Arc::new(std::vec::Vec::new), ); Ok(()) diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index dd3f23f..d43cd9b 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -2,7 +2,7 @@ use crate::interlude::*; // Ensure that the `tracing` stack is only initialised once using `once_cell` // isn't required in cargo-nextest since each test runs in a new process -pub fn setup_tracing_once() { +pub fn _setup_tracing_once() { use once_cell::sync::Lazy; static TRACING: Lazy<()> = Lazy::new(|| { setup_tracing().expect("failed to init tracing"); @@ -101,7 +101,7 @@ mod cheapstr { impl PartialOrd for CHeapStr { fn partial_cmp(&self, other: &Self) -> Option { - self.string.partial_cmp(&other.string) + Some(self.cmp(other)) } } @@ -127,8 +127,8 @@ mod cheapstr { } } - impl Into for CHeapStr { - fn into(self) -> String { + impl From for String { + fn from(value: CHeapStr) -> String { // FIXME: optmize this /* let string = if let Some(s) = Arc::get_mut(&mut self.0) { unsafe { @@ -143,7 +143,7 @@ mod cheapstr { }; std::mem::forget(self.0); string */ - self.string.into_owned() + value.string.into_owned() } } diff --git a/src/xtask/main.rs b/src/xtask/main.rs index a4d1dd3..5baa34f 100644 --- a/src/xtask/main.rs +++ b/src/xtask/main.rs @@ -15,25 +15,28 @@ mod utils; fn main() -> Res<()> { utils::setup_tracing()?; + let cwd = std::env::current_dir()?; use clap::Parser; let args = Args::parse(); match args.command { Commands::Test { files, filter } => { use denort::deno::deno_config; - let cwd = std::process::working_dir(); denort::test_sync( deno_config::glob::FilePatterns { - include: files.map(|vec| { - deno_config::glob::PathOrPatternSet::new( + include: if let Some(vec) = files { + Some(deno_config::glob::PathOrPatternSet::new( vec.into_iter() .map(|path| { - deno_config::glob::PathOrPattern::from_relative(&cwd, path) + deno_config::glob::PathOrPattern::from_relative(&cwd, &path) }) - .collect::>()?, - ) - }), + .collect::, _>>()?, + )) + } else { + None + }, exclude: deno_config::glob::PathOrPatternSet::new(vec![]), + base: cwd, }, "deno.jsonc".into(), denort::deno::args::PermissionFlags { @@ -42,7 +45,7 @@ fn main() -> Res<()> { }, None, filter, - Arc::new(|| vec![]), + Arc::new(std::vec::Vec::new), vec![], ) } @@ -59,10 +62,15 @@ struct Args { #[derive(Debug, clap::Subcommand)] enum Commands { + /* #[clap(visible_alias = "r")] + Run { + /// Script arg + argv: Vec, + }, */ #[clap(visible_alias = "t")] Test { /// Files to test - files: Option>, + files: Option>, /// Tests to include #[arg(long)] filter: Option, diff --git a/src/xtask/utils.rs b/src/xtask/utils.rs index ed0c548..32026b1 100644 --- a/src/xtask/utils.rs +++ b/src/xtask/utils.rs @@ -2,7 +2,8 @@ use crate::interlude::*; // Ensure that the `tracing` stack is only initialised once using `once_cell` // isn't required in cargo-nextest since each test runs in a new process -pub fn setup_tracing_once() { +#[cfg(test)] +pub fn _setup_tracing_once() { use once_cell::sync::Lazy; static TRACING: Lazy<()> = Lazy::new(|| { setup_tracing().expect("failed to init tracing"); diff --git a/tests/utils.ts b/tests/utils.ts index 3c147e5..81c9af2 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -134,6 +134,7 @@ export async function localE2eTest(testCase: E2eTestCase) { ghjkDenoCacheDir: Deno.env.get("DENO_DIR") ?? $.path(Deno.env.get("HOME")!).join(".cache", "deno").toString(), ghjkShareDir: ghjkShareDir.toString(), + ghjkExecDenoExec: "deno", // don't modify system shell configs shellsToHook: [], }); diff --git a/utils/mod.ts b/utils/mod.ts index f471c2d..8ec530f 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -281,6 +281,7 @@ export const $ = dax.build$( } return pathRef; }, + dbg, }, }, ); From 5448f06dd649f8dd2b24e4b28b0f441f4a0bbd61 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Thu, 21 Nov 2024 22:00:05 +0300 Subject: [PATCH 05/15] wip: proof of concept --- Cargo.lock | 299 +++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 4 + src/denort/lib.rs | 157 ++++++++++++++++++----- src/ghjk/Cargo.toml | 12 +- src/ghjk/build.rs | 3 + src/ghjk/main.rs | 159 +++++++++++++++++++++-- src/xtask/Cargo.toml | 3 +- 7 files changed, 578 insertions(+), 59 deletions(-) create mode 100644 src/ghjk/build.rs diff --git a/Cargo.lock b/Cargo.lock index 7439524..b5b389e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -649,6 +649,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -861,6 +867,32 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_fn" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "373e9fafaa20882876db20562275ff58d50e0caa2590077fe7ce7bef90211d0d" + +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -873,6 +905,16 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147be55d677052dabc6b22252d5dd0fd4c29c8c27aa4f2fbef0f94aa003b406f" +[[package]] +name = "cordyceps" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec10f0a762d93c4498d2e97a333805cb6250d60bead623f71d8034f9a4152ba3" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1202,7 +1244,7 @@ dependencies = [ "markup_fmt", "memmem", "monch", - "nix", + "nix 0.27.1", "node_resolver", "notify", "once_cell", @@ -1574,7 +1616,7 @@ dependencies = [ "filetime", "junction", "libc", - "nix", + "nix 0.27.1", "rand", "rayon", "serde", @@ -2020,7 +2062,7 @@ dependencies = [ "libc", "log", "netif", - "nix", + "nix 0.27.1", "node_resolver", "notify", "ntapi", @@ -2425,6 +2467,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + [[package]] name = "digest" version = "0.10.7" @@ -2944,6 +2992,15 @@ dependencies = [ "serde", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -3030,6 +3087,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.0.30" @@ -3169,6 +3232,18 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34acda8ae8b63fbe0b2195c998b180cff89a8212fb2622a78b572a9f1c6f7684" +dependencies = [ + "cordyceps", + "diatomic-waker", + "futures-core", + "pin-project-lite", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -3179,6 +3254,21 @@ dependencies = [ "futures-sink", ] +[[package]] +name = "futures-concurrency" +version = "7.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b724496da7c26fcce66458526ce68fc2ecf4aaaa994281cf322ded5755520c" +dependencies = [ + "fixedbitset 0.5.7", + "futures-buffered", + "futures-core", + "futures-lite", + "pin-project", + "slab", + "smallvec", +] + [[package]] name = "futures-core" version = "0.3.30" @@ -3204,15 +3294,17 @@ checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" -version = "2.3.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", + "memchr", "parking", "pin-project-lite", + "waker-fn", ] [[package]] @@ -3256,6 +3348,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -3296,18 +3401,23 @@ version = "0.3.0" dependencies = [ "ahash", "bitflags 2.6.0", + "clap", "color-eyre", "dashmap", "denort", "educe", - "futures-lite", + "futures", + "futures-concurrency", + "indexmap", "itertools 0.13.0", + "nix 0.29.0", "once_cell", "parking_lot", "rand", "regex", "serde", "serde_json", + "shadow-rs", "smallvec", "smartstring", "thiserror", @@ -3328,6 +3438,19 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "git2" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" +dependencies = [ + "bitflags 2.6.0", + "libc", + "libgit2-sys", + "log", + "url", +] + [[package]] name = "gl_generator" version = "0.14.0" @@ -3830,6 +3953,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -3954,6 +4100,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipconfig" version = "0.3.2" @@ -4023,6 +4178,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_debug" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" + [[package]] name = "is_terminal_polyfill" version = "1.70.0" @@ -4219,6 +4380,18 @@ dependencies = [ "cc", ] +[[package]] +name = "libgit2-sys" +version = "0.17.0+1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + [[package]] name = "libloading" version = "0.7.4" @@ -4329,6 +4502,19 @@ dependencies = [ "serde", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -4589,6 +4775,18 @@ dependencies = [ "libc", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + [[package]] name = "node_resolver" version = "0.16.0" @@ -4759,6 +4957,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -5079,7 +5286,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ - "fixedbitset", + "fixedbitset 0.4.2", "indexmap", ] @@ -5963,7 +6170,7 @@ dependencies = [ "libc", "log", "memchr", - "nix", + "nix 0.27.1", "radix_trie", "unicode-segmentation", "unicode-width", @@ -6238,6 +6445,19 @@ dependencies = [ "keccak", ] +[[package]] +name = "shadow-rs" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cfcd0643497a9f780502063aecbcc4a3212cbe4948fd25ee8fd179c2cf9a18" +dependencies = [ + "const_format", + "git2", + "is_debug", + "time", + "tzdb", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -7085,7 +7305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.1.0", "rustix", "windows-sys 0.52.0", ] @@ -7162,7 +7382,9 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -7501,6 +7723,35 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "tz-rs" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4" +dependencies = [ + "const_fn", +] + +[[package]] +name = "tzdb" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b580f6b365fa89f5767cdb619a55d534d04a4e14c2d7e5b9a31e94598687fb1" +dependencies = [ + "iana-time-zone", + "tz-rs", + "tzdb_data", +] + +[[package]] +name = "tzdb_data" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "654c1ec546942ce0594e8d220e6b8e3899e0a0a8fe70ddd54d32a376dfefe3f8" +dependencies = [ + "tz-rs", +] + [[package]] name = "ucd-trie" version = "0.1.6" @@ -7772,6 +8023,12 @@ dependencies = [ "quote", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.3.2" @@ -7895,7 +8152,7 @@ dependencies = [ "arrayvec", "bit-vec", "bitflags 2.6.0", - "cfg_aliases", + "cfg_aliases 0.1.1", "codespan-reporting", "document-features", "indexmap", @@ -7927,7 +8184,7 @@ dependencies = [ "bit-set", "bitflags 2.6.0", "block", - "cfg_aliases", + "cfg_aliases 0.1.1", "core-graphics-types", "d3d12", "glow", @@ -8041,6 +8298,24 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 2a291a1..8203d4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,7 @@ tracing-subscriber = { version = "0.3", features = [ ] } tracing-unwrap = "1.0" once_cell = "1" + +# version must match on clap in `deno` +clap = "=4.5" +shadow-rs = "0.36.0" diff --git a/src/denort/lib.rs b/src/denort/lib.rs index 9c31b69..aa16fa6 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -27,12 +27,6 @@ use deno::{ use deno_runtime::deno_core as deno_core; // necessary for re-exported macros to work const DEFAULT_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv" /* "net", "http" */]; -const CACHE_BLOCKLIST: &[&str] = &[ - "npm:/@typegraph/sdk", - "npm:/@typegraph/sdk/", - "npm:@typegraph/sdk", - "npm:@typegraph/sdk/", -]; /// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these /// futures are very large, this prevents the stack from getting blown out from passing them by value up @@ -43,13 +37,26 @@ fn spawn_subcommand + 'static>(f: F) -> JoinHandle<()> { deno_core::unsync::spawn(f.boxed_local()) } +/// This must be called on the main thread as early as possible +/// or one will encounter stack overflows and segmentation faults +pub fn init() { + deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); + // The stack will blow on debug builds unless we increase the size + if cfg!(debug_assertions) { + // We must do this early before any new threads are started + // since std::thread might cache RUST_MIN_STACK once it's read this env + if std::env::var("RUST_MIN_STACK").is_err() { + std::env::set_var("RUST_MIN_STACK", "8388608"); + } + }; +} + pub fn run_sync( main_mod: ModuleSpecifier, import_map_url: Option, permissions: args::PermissionFlags, custom_extensions: Arc, ) { - deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); new_thread_builder() .spawn(|| { create_and_run_current_thread_with_maybe_metrics(async move { @@ -67,17 +74,122 @@ pub fn run_sync( .unwrap(); } +pub struct Context { + pub cli_factory: deno::factory::CliFactory, + worker_factory: deno::worker::CliMainWorkerFactory, + custom_extensions_cb: Option>, + graph: Arc, +} + +impl Context { + pub async fn from_config( + flags: deno::args::Flags, + custom_extensions_cb: Option>, + ) -> Res { + deno_permissions::set_prompt_callbacks( + Box::new(util::draw_thread::DrawThread::hide), + Box::new(util::draw_thread::DrawThread::show), + ); + + let flags = args::Flags { ..flags }; + let flags = Arc::new(flags); + let cli_factory = factory::CliFactory::from_flags(flags); + let cli_factory = if let Some(custom_extensions_cb) = &custom_extensions_cb { + cli_factory.with_custom_ext_cb(custom_extensions_cb.clone()) + } else { + cli_factory + }; + let worker_factory = cli_factory + .create_cli_main_worker_factory() + .await + .map_err(|err| ferr!(Box::new(err)))?; + + let graph = cli_factory + .main_module_graph_container() + .await + .map_err(|err| ferr!(Box::new(err)))? + .clone(); + Ok(Self { + cli_factory, + worker_factory, + custom_extensions_cb, + graph, + }) + } + + pub async fn run_module( + &self, + main_module: ModuleSpecifier, + permissions: &deno_permissions::PermissionsOptions, + mode: deno_runtime::WorkerExecutionMode, + stdio: deno_runtime::deno_io::Stdio, + ) -> Res { + let desc_parser = self + .cli_factory + .permission_desc_parser() + .map_err(|err| ferr!(Box::new(err)))? + .clone(); + let permissions = + deno_permissions::Permissions::from_options(desc_parser.as_ref(), permissions)?; + let permissions = deno_permissions::PermissionsContainer::new(desc_parser, permissions); + let worker = self + .worker_factory + .create_custom_worker( + mode, + main_module.clone(), + permissions, + self.custom_extensions_cb + .as_ref() + .map(|cb| cb()) + .unwrap_or_default(), + stdio, + ) + .await + .map_err(|err| ferr!(Box::new(err)))?; + Ok(ModuleWorker { + main_module, + worker, + graph: self.graph.clone(), + }) + } +} + +pub struct ModuleWorker { + main_module: deno_core::ModuleSpecifier, + worker: deno::worker::CliMainWorker, + graph: Arc, +} + +impl ModuleWorker { + pub fn visted_files(&self) -> Vec { + use deno::graph_container::*; + self.graph + .graph() + .walk( + [&self.main_module].into_iter(), + deno::deno_graph::WalkOptions { + kind: deno::deno_graph::GraphKind::CodeOnly, + check_js: false, + follow_dynamic: true, + prefer_fast_check_graph: false, + }, + ) + .filter(|(url, _)| url.scheme() == "file") + .map(|(url, _)| url.clone()) + .collect() + } + + pub async fn run(&mut self) -> Res { + self.worker.run().await.map_err(|err| ferr!(Box::new(err))) + } +} + pub async fn run( main_module: ModuleSpecifier, import_map_url: Option, permissions: args::PermissionFlags, custom_extensions: Arc, ) -> anyhow::Result<()> { - deno_permissions::set_prompt_callbacks( - Box::new(util::draw_thread::DrawThread::hide), - Box::new(util::draw_thread::DrawThread::show), - ); - // NOTE: avoid using the Run subcommand // as it breaks our custom_extensions patch for some reason let flags = args::Flags { @@ -91,12 +203,6 @@ pub async fn run( .collect(), ..Default::default() }, - #[cfg(debug_assertions)] - cache_blocklist: CACHE_BLOCKLIST - .iter() - .cloned() - .map(str::to_string) - .collect(), ..Default::default() }; @@ -112,6 +218,7 @@ pub async fn run( tracing::info!("running worker"); let exit_code = worker.run().await?; println!("exit_code: {exit_code}"); + Ok(()) } @@ -124,7 +231,6 @@ pub fn test_sync( custom_extensions: Arc, argv: Vec, ) { - deno::util::v8::init_v8_flags(&[], &[], deno::util::v8::get_v8_flags_from_env()); new_thread_builder() .spawn(|| { create_and_run_current_thread_with_maybe_metrics(async move { @@ -210,11 +316,6 @@ pub async fn test( config_flag: args::ConfigFlag::Path(config_file.to_string_lossy().into()), argv, subcommand: args::DenoSubcommand::Test(test_flags.clone()), - cache_blocklist: CACHE_BLOCKLIST - .iter() - .cloned() - .map(str::to_string) - .collect(), ..Default::default() }; @@ -311,14 +412,6 @@ pub async fn test( pub fn new_thread_builder() -> std::thread::Builder { let builder = std::thread::Builder::new(); let builder = if cfg!(debug_assertions) { - // this is only relevant for WebWorkers - // FIXME: find a better location for this as tihs won't work - // if a second thread has already launched by this point - if std::env::var("RUST_MIN_STACK").is_err() { - unsafe { - std::env::set_var("RUST_MIN_STACK", "8388608"); - } - } // deno & swc need 8 MiB with dev profile (release is ok) // https://github.com/swc-project/swc/blob/main/CONTRIBUTING.md builder.stack_size(8 * 1024 * 1024) diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index dca833b..d465326 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -43,11 +43,17 @@ tracing-subscriber.workspace = true tracing-appender = "0.2" tracing-futures = "0.2" -futures-lite = "2" tokio = { version = "1", features = ["full", "parking_lot"] } tokio-stream = "0.1" dashmap = { version = "5.5", features = ["serde"]} -# version must match on clap in `deno` -# clap = { version = "=4.4", features = ["derive", "env"] } +clap = { workspace = true, features = ["derive", "env"] } +shadow-rs.workspace = true +nix = { version = "0.29.0", features = ["signal"] } +indexmap = { version = "2.6.0", features = ["serde"] } +futures-concurrency = "7.6.2" +futures = { version = "=0.3.30", default-features = false, features = ["std", "async-await"] } + +[build-dependencies] +shadow-rs.workspace = true diff --git a/src/ghjk/build.rs b/src/ghjk/build.rs new file mode 100644 index 0000000..4a0dfc4 --- /dev/null +++ b/src/ghjk/build.rs @@ -0,0 +1,3 @@ +fn main() -> shadow_rs::SdResult<()> { + shadow_rs::new() +} diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index bfbfb5b..6664f3f 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -8,7 +8,8 @@ mod interlude { pub use color_eyre::eyre; pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; - pub use futures_lite::{future::Boxed as BoxedFut, FutureExt}; + pub use futures::{future::BoxFuture, FutureExt}; + use futures_concurrency::prelude::*; pub use serde::{Deserialize, Serialize}; pub use serde_json::json; pub use smallvec::smallvec as svec; @@ -21,17 +22,155 @@ mod utils; use crate::interlude::*; fn main() -> Res<()> { + // FIXME: change signal handler for children + // FIXME: use unix_sigpipe once https://github.com/rust-lang/rust/issues/97889 lands + unsafe { + use nix::sys::signal::*; + signal(Signal::SIGPIPE, SigHandler::SigDfl)?; + } utils::setup_tracing()?; + denort::init(); - denort::run_sync( - "main.ts".parse()?, - None, - denort::deno::args::PermissionFlags { - allow_all: true, - ..default() - }, - Arc::new(std::vec::Vec::new), - ); + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()? + .block_on(cli())?; + Ok(()) +} + +use denort::deno::deno_runtime; +use shadow_rs::shadow; +shadow!(build); + +const DEFAULT_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; + +async fn cli() -> Res<()> { + debug!(version = build::VERSION, "ghjk CLI"); + + let cwd = std::env::current_dir()?; + + let gcx = GhjkCtx { + deno: denort::Context::from_config( + denort::deno::args::Flags { + unstable_config: denort::deno::args::UnstableConfig { + features: DEFAULT_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..default() + }, + ..default() + }, + Some(Arc::new(Vec::new)), + ) + .await?, + }; + { + let main_module = deno_runtime::deno_core::resolve_url_or_path("play.ts", &cwd) + .wrap_err("error resolving main module")?; + let mut worker = gcx + .deno + .run_module( + main_module.clone(), + &deno_runtime::deno_permissions::PermissionsOptions { + allow_env: Some(vec![]), + allow_import: Some(vec![]), + allow_read: Some(vec![]), + allow_net: Some(vec![]), + ..default() + }, + deno_runtime::WorkerExecutionMode::Run, + deno_runtime::deno_io::Stdio::default(), + ) + .await?; + let exit_code = worker.run().await?; + info!(%exit_code, %main_module, "module done"); + for url in worker.visted_files() { + info!(%url, %main_module, "visited files"); + } + } Ok(()) } + +struct GhjkCtx { + deno: denort::Context, +} + +#[derive(Debug)] +struct Config { + ghjkfile: PathBuf, + share_dir: PathBuf, + ghjk_dir: PathBuf, +} + +async fn look_for_ghjkfile() {} + +#[tracing::instrument] +async fn commands_from_ghjkfile(config: &Config) { + // let lockfile_path = config.ghjk_dir.join("lock.json"); + // let hashfile_path = config.ghjk_dir.join("hash.json"); +} + +// #[tracing::instrument] +// async fn read_ghjkfile(config: &Config) { +// match config.ghjkfile.extension() { +// Some("") | Some("ts") => { +// if let Some("") = config.ghjkfile.extension() { +// warn!("ghjkfile has no extension, assuming deno ghjkfile") +// } +// debug!("serializing deno ghjkfile") +// } +// } +// } + +struct SerializationResult { + config: serde_json::Value, + accessed_env_keys: Vec, + read_file_paths: Vec, + listed_file_paths: Vec, +} + +async fn serialize_ghjk_ts() -> Res { + Ok(todo!()) +} + +mod hashflile { + use crate::interlude::*; + + #[derive(Debug, Serialize, Deserialize)] + struct HashObj { + version: String, + /// Hash of the ghjkfile contents. + ghjkfile_hash: String, + /// Hashes of all env vars that were read. + env_var_hashes: indexmap::IndexMap>, + /// Hashes of all files that were read. + read_file_hashes: indexmap::IndexMap>, + /// File paths that were observed from the fs but not necessarily + /// read. + listed_files: Vec, + } + + /// The hash.json file stores the digests of all external accesses + /// of a ghjkfile during serialization. The primary purpose is to + /// do "cache invalidation" on ghjkfiles, re-serializing them if + /// any of the digests change. + async fn read_hash_file(path: &Path) -> Res { + let raw = tokio::fs::read(path) + .await + .wrap_err("error reading hash.json")?; + serde_json::from_slice(&raw).wrap_err("error parsing hash.json") + } +} + +/* mod files { + mod deno {} +} + +mod modules { + mod envs {} + mod ports {} + mod tasks {} +} */ diff --git a/src/xtask/Cargo.toml b/src/xtask/Cargo.toml index d754ad9..8bda8e0 100644 --- a/src/xtask/Cargo.toml +++ b/src/xtask/Cargo.toml @@ -16,5 +16,4 @@ color-eyre.workspace = true tracing.workspace = true tracing-subscriber.workspace = true once_cell.workspace = true -# version must match on clap in `deno` -clap = { version = "=4.5", features = ["derive", "env"] } +clap = { workspace = true, features = ["derive", "env"] } From 24c7d1d3ecae39b3c432d7a9e34b06e4aeb7d437 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Sun, 24 Nov 2024 03:32:54 +0300 Subject: [PATCH 06/15] wip: ghjk host --- .vscode/settings.json | 4 +- Cargo.lock | 68 ++++- Cargo.toml | 6 + files/deno/mod2.ts | 24 ++ files/deno/worker.ts | 2 +- src/denort/Cargo.toml | 10 +- src/denort/lib.rs | 232 +++++++++++++--- src/ghjk/Cargo.toml | 10 +- src/ghjk/host.rs | 600 ++++++++++++++++++++++++++++++++++++++++++ src/ghjk/main.rs | 203 +++++++------- src/ghjk/utils.rs | 84 ++++++ 11 files changed, 1086 insertions(+), 157 deletions(-) create mode 100644 files/deno/mod2.ts create mode 100644 src/ghjk/host.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index cd2b681..2d317f4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,7 +22,9 @@ "DENO", "ghjk", "ghjkfile", + "ghjkfiles", "Hashfile", + "indexmap", "POSIX", "runtimes", "sophon" @@ -35,4 +37,4 @@ "latex", "plaintext" ] -} +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index b5b389e..3d4538b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -942,6 +942,15 @@ dependencies = [ "libc", ] +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "countme" version = "3.0.1" @@ -2353,7 +2362,8 @@ dependencies = [ "anyhow", "color-eyre", "deno", - "derive_more", + "educe", + "tokio", "tracing", "tracing-subscriber", "tracing-unwrap", @@ -2485,6 +2495,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs" version = "5.0.1" @@ -3404,19 +3423,25 @@ dependencies = [ "clap", "color-eyre", "dashmap", + "data-encoding", "denort", + "directories", "educe", "futures", "futures-concurrency", "indexmap", "itertools 0.13.0", + "json-canon", + "multihash", "nix 0.29.0", "once_cell", "parking_lot", + "pathdiff", "rand", "regex", "serde", "serde_json", + "sha2", "shadow-rs", "smallvec", "smartstring", @@ -4238,6 +4263,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-canon" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447ae153a2bd47d61acc0d131295408e32ef87ed9785825a6f4ecef85afc0edb" +dependencies = [ + "ryu-js 0.2.2", + "serde", + "serde_json", +] + [[package]] name = "jsonc-parser" version = "0.26.2" @@ -4691,6 +4727,16 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b52c1b33ff98142aecea13138bd399b68aa7ab5d9546c300988c345004001eea" +[[package]] +name = "multihash" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc41f430805af9d1cf4adae4ed2149c759b877b01d909a1f40256188d09345d2" +dependencies = [ + "core2", + "unsigned-varint", +] + [[package]] name = "multimap" version = "0.8.3" @@ -5206,9 +5252,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "pbkdf2" @@ -6195,6 +6241,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "ryu-js" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" + [[package]] name = "ryu-js" version = "1.0.1" @@ -7101,7 +7153,7 @@ version = "0.198.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15455da4768f97186c40523e83600495210c11825d3a44db43383fd81eace88d" dependencies = [ - "ryu-js", + "ryu-js 1.0.1", "serde", "swc_atoms", "swc_common", @@ -7122,7 +7174,7 @@ dependencies = [ "num_cpus", "once_cell", "rustc-hash", - "ryu-js", + "ryu-js 1.0.1", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -7875,6 +7927,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 8203d4d..ff7cc9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ edition = "2021" [workspace.dependencies] denort = { path = "src/denort" } +educe = "0.6" + color-eyre = "0.6" anyhow = "1" tracing = "0.1" @@ -18,8 +20,12 @@ tracing-subscriber = { version = "0.3", features = [ "tracing-log" ] } tracing-unwrap = "1.0" + once_cell = "1" # version must match on clap in `deno` clap = "=4.5" shadow-rs = "0.36.0" + + +tokio = "1" \ No newline at end of file diff --git a/files/deno/mod2.ts b/files/deno/mod2.ts new file mode 100644 index 0000000..61a1505 --- /dev/null +++ b/files/deno/mod2.ts @@ -0,0 +1,24 @@ +//! this loads the ghjk.ts module and provides a program for it + +//// +/// + +// all imports in here should be dynamic imports as we want to +// modify the Deno namespace before anyone touches it + +// NOTE: only import types +import { shimDenoNamespace } from "../../utils/worker.ts"; + +const shimHandle = shimDenoNamespace(Deno.env.toObject()); +const { setup: setupLogger } = await import("../../utils/logger.ts"); +setupLogger(); +const uri = import.meta.resolve("../../ghjk.ts"); +const mod = await import(uri); +const rawConfig = await mod.sophon.getConfig(uri, mod.secureConfig); +const config = JSON.parse(JSON.stringify(rawConfig)); +console.log({ + config, + accessedEnvKeys: shimHandle.getAccessedEnvKeys(), + readFiles: shimHandle.getReadFiles(), + listedFiles: shimHandle.getListedFiles(), +}); diff --git a/files/deno/worker.ts b/files/deno/worker.ts index 5a9528f..ca55221 100644 --- a/files/deno/worker.ts +++ b/files/deno/worker.ts @@ -6,8 +6,8 @@ // all imports in here should be dynamic imports as we want to // modify the Deno namespace before anyone touches it -// NOTE: only import types import { shimDenoNamespace } from "../../utils/worker.ts"; +// NOTE: only import types import type { DriverRequests, DriverResponse } from "./mod.ts"; self.onmessage = onMsg; diff --git a/src/denort/Cargo.toml b/src/denort/Cargo.toml index 1cf5b7e..2d20b59 100644 --- a/src/denort/Cargo.toml +++ b/src/denort/Cargo.toml @@ -9,13 +9,15 @@ path = "lib.rs" [dependencies] tracing-unwrap.workspace = true +educe.workspace = true + color-eyre.workspace = true anyhow.workspace = true + tracing.workspace = true tracing-subscriber.workspace = true deno = { git = "https://github.com/metatypedev/deno", branch = "v2.0.6-embeddable" } -# deno_core = "=0.291.0" -# breaking changes to .18 -# https://github.com/JelteF/derive_more/issues/373 -derive_more = "=0.99.17" + +tokio.workspace = true +# deno_core = "=0.291.0" \ No newline at end of file diff --git a/src/denort/lib.rs b/src/denort/lib.rs index aa16fa6..d346a3c 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -28,15 +28,6 @@ use deno_runtime::deno_core as deno_core; // necessary for re-exported macros to const DEFAULT_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv" /* "net", "http" */]; -/// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these -/// futures are very large, this prevents the stack from getting blown out from passing them by value up -/// the callchain (especially in debug mode when Rust doesn't have a chance to elide copies!). -#[inline(always)] -fn spawn_subcommand + 'static>(f: F) -> JoinHandle<()> { - // the boxed_local() is important in order to get windows to not blow the stack in debug - deno_core::unsync::spawn(f.boxed_local()) -} - /// This must be called on the main thread as early as possible /// or one will encounter stack overflows and segmentation faults pub fn init() { @@ -51,38 +42,88 @@ pub fn init() { }; } -pub fn run_sync( - main_mod: ModuleSpecifier, - import_map_url: Option, - permissions: args::PermissionFlags, - custom_extensions: Arc, -) { - new_thread_builder() - .spawn(|| { - create_and_run_current_thread_with_maybe_metrics(async move { - spawn_subcommand(async move { - run(main_mod, import_map_url, permissions, custom_extensions) - .await - .unwrap() - }) - .await - .unwrap() - }) - }) - .unwrap() - .join() - .unwrap(); +/// This starts a new thread and uses it to run all the tasks +/// that'll need to touch deno internals. Deno is single threaded. +/// +/// Returned handles will use channels internally to communicate to this worker. +pub async fn worker( + flags: deno::args::Flags, + custom_extensions_cb: Option>, +) -> Res { + let cx = WorkerContext::from_config(flags, custom_extensions_cb).await?; + + let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); + let rt = tokio::runtime::Handle::current(); + std::thread::spawn(move || { + let local = tokio::task::LocalSet::new(); + + local.spawn_local(async move { + while let Some(req) = rx.recv().await { + match req { + DenoWorkerReq::PrepareModule { + response_channel, + main_module, + permissions, + mode, + stdio, + } => { + let mut module_cx = match cx + .prepare_module(main_module, &permissions, mode, stdio) + .await + { + Ok(val) => val, + Err(err) => { + response_channel + .send(Err(err)) + .expect_or_log("channel error"); + continue; + } + }; + + let (module_tx, mut module_rx) = + tokio::sync::mpsc::unbounded_channel::(); + tokio::task::spawn_local(async move { + while let Some(req) = module_rx.recv().await { + match req { + ModuleWorkerReq::Run { response_channel } => response_channel + .send(module_cx.run().await) + .expect_or_log("channel error"), + ModuleWorkerReq::GetVisitedFiles { response_channel } => { + response_channel + .send(module_cx.get_visited_files()) + .expect_or_log("channel error") + } + } + } + }); + + response_channel + .send(Ok(ModuleWorkerHandle { sender: module_tx })) + .expect_or_log("channel error"); + } + } + } + }); + rt.block_on(local); + }); + Ok(DenoWorkerHandle { sender: tx }) } -pub struct Context { - pub cli_factory: deno::factory::CliFactory, +#[derive(educe::Educe)] +#[educe(Debug)] +struct WorkerContext { + #[educe(Debug(ignore))] + cli_factory: deno::factory::CliFactory, + #[educe(Debug(ignore))] worker_factory: deno::worker::CliMainWorkerFactory, + #[educe(Debug(ignore))] custom_extensions_cb: Option>, + #[educe(Debug(ignore))] graph: Arc, } -impl Context { - pub async fn from_config( +impl WorkerContext { + async fn from_config( flags: deno::args::Flags, custom_extensions_cb: Option>, ) -> Res { @@ -117,13 +158,13 @@ impl Context { }) } - pub async fn run_module( + async fn prepare_module( &self, main_module: ModuleSpecifier, permissions: &deno_permissions::PermissionsOptions, mode: deno_runtime::WorkerExecutionMode, stdio: deno_runtime::deno_io::Stdio, - ) -> Res { + ) -> Res { let desc_parser = self .cli_factory .permission_desc_parser() @@ -146,7 +187,8 @@ impl Context { ) .await .map_err(|err| ferr!(Box::new(err)))?; - Ok(ModuleWorker { + + Ok(ModuleWorkerContext { main_module, worker, graph: self.graph.clone(), @@ -154,14 +196,55 @@ impl Context { } } -pub struct ModuleWorker { +enum DenoWorkerReq { + PrepareModule { + response_channel: tokio::sync::oneshot::Sender>, + main_module: ModuleSpecifier, + permissions: deno_permissions::PermissionsOptions, + mode: deno_runtime::WorkerExecutionMode, + stdio: deno_runtime::deno_io::Stdio, + }, +} + +#[derive(Clone, Debug)] +pub struct DenoWorkerHandle { + sender: tokio::sync::mpsc::UnboundedSender, +} + +impl DenoWorkerHandle { + pub async fn prepare_module( + &self, + main_module: ModuleSpecifier, + permissions: deno_permissions::PermissionsOptions, + mode: deno_runtime::WorkerExecutionMode, + stdio: deno_runtime::deno_io::Stdio, + ) -> Res { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(DenoWorkerReq::PrepareModule { + response_channel: tx, + main_module, + permissions, + mode, + stdio, + }) + .expect_or_log("channel error"); + rx.await.expect_or_log("channel error") + } +} + +#[derive(educe::Educe)] +#[educe(Debug)] +struct ModuleWorkerContext { main_module: deno_core::ModuleSpecifier, + #[educe(Debug(ignore))] worker: deno::worker::CliMainWorker, + #[educe(Debug(ignore))] graph: Arc, } -impl ModuleWorker { - pub fn visted_files(&self) -> Vec { +impl ModuleWorkerContext { + fn get_visited_files(&self) -> Vec { use deno::graph_container::*; self.graph .graph() @@ -179,11 +262,78 @@ impl ModuleWorker { .collect() } - pub async fn run(&mut self) -> Res { + async fn run(&mut self) -> Res { self.worker.run().await.map_err(|err| ferr!(Box::new(err))) } } +enum ModuleWorkerReq { + Run { + response_channel: tokio::sync::oneshot::Sender>, + }, + GetVisitedFiles { + response_channel: tokio::sync::oneshot::Sender>, + }, +} + +#[derive(Clone, Debug)] +pub struct ModuleWorkerHandle { + sender: tokio::sync::mpsc::UnboundedSender, +} +impl ModuleWorkerHandle { + pub async fn get_visited_files(&mut self) -> Vec { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::GetVisitedFiles { + response_channel: tx, + }) + .expect_or_log("channel error"); + // FIXME: can use sync oneshot here + rx.await.expect_or_log("channel error") + } + + pub async fn run(&mut self) -> Res { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::Run { + response_channel: tx, + }) + .expect_or_log("channel error"); + rx.await.expect_or_log("channel error") + } +} + +/// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these +/// futures are very large, this prevents the stack from getting blown out from passing them by value up +/// the callchain (especially in debug mode when Rust doesn't have a chance to elide copies!). +#[inline(always)] +fn spawn_subcommand + 'static>(f: F) -> JoinHandle<()> { + // the boxed_local() is important in order to get windows to not blow the stack in debug + deno_core::unsync::spawn(f.boxed_local()) +} +pub fn run_sync( + main_mod: ModuleSpecifier, + import_map_url: Option, + permissions: args::PermissionFlags, + custom_extensions: Arc, +) { + new_thread_builder() + .spawn(|| { + create_and_run_current_thread_with_maybe_metrics(async move { + spawn_subcommand(async move { + run(main_mod, import_map_url, permissions, custom_extensions) + .await + .unwrap() + }) + .await + .unwrap() + }) + }) + .unwrap() + .join() + .unwrap(); +} + pub async fn run( main_module: ModuleSpecifier, import_map_url: Option, diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index d465326..0a03832 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -31,7 +31,7 @@ smallvec = { version = "1", features = [ ] } smartstring = { version = "1", features = ["serde"] } -educe = "0.6" +educe.workspace = true thiserror = "1" tracing-error = "0.2" @@ -43,7 +43,7 @@ tracing-subscriber.workspace = true tracing-appender = "0.2" tracing-futures = "0.2" -tokio = { version = "1", features = ["full", "parking_lot"] } +tokio = { workspace = true, features = ["full", "parking_lot"] } tokio-stream = "0.1" dashmap = { version = "5.5", features = ["serde"]} @@ -54,6 +54,12 @@ nix = { version = "0.29.0", features = ["signal"] } indexmap = { version = "2.6.0", features = ["serde"] } futures-concurrency = "7.6.2" futures = { version = "=0.3.30", default-features = false, features = ["std", "async-await"] } +multihash = "0.19.2" +json-canon = "0.1.3" +data-encoding = "2.6.0" +sha2 = "0.10.8" +pathdiff = "0.2.2" +directories = "5.0.1" [build-dependencies] shadow-rs.workspace = true diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs new file mode 100644 index 0000000..94329ee --- /dev/null +++ b/src/ghjk/host.rs @@ -0,0 +1,600 @@ +use crate::{interlude::*, utils}; + +#[derive(educe::Educe)] +#[educe(Debug)] +enum ModuleManifest { + Todo, +} + +impl ModuleManifest { + pub fn init(&self) -> ModuleInstance { + ModuleInstance::Todo + } +} +enum ModuleInstance { + Todo, +} + +type ModuleLockEntry = Box; +type ModuleContext = Box; + +impl ModuleInstance { + pub async fn load_lock_entry( + &mut self, + gcx: &GhjkCtx, + raw: serde_json::Value, + ) -> Res { + Ok(Box::new("todo")) + } + + pub async fn gen_lock_entry( + &mut self, + gcx: &GhjkCtx, + mcx: &ModuleContext, + ) -> Res { + Ok(serde_json::json!("todo")) + } + + pub async fn load_config( + &mut self, + gcx: &GhjkCtx, + bb: &ConfigBlackboard, + lock_entry: Option, + ) -> Res { + Ok(Box::new("todo")) + } +} + +#[derive(Debug)] +pub struct Config { + /// Discard serialization cache. + pub re_serialize: bool, + /// Discard any resolved values in lockfile. + pub re_resolve: bool, + /// Force use serialization cache. + pub locked: bool, + pub env_vars: IndexMap, + pub cwd: PathBuf, +} + +#[derive(Debug)] +pub struct HostCtx { + pub gcx: Arc, + config: Config, + pub modules: HashMap, + pub file_hash_memo: DHashMap, +} + +impl HostCtx { + pub fn new(gcx: Arc, config: Config) -> Self { + Self { + gcx, + config, + modules: [ + ("envs".into(), ModuleManifest::Todo), + ("ports".into(), ModuleManifest::Todo), + ("tasks".into(), ModuleManifest::Todo), + ] + .into_iter() + .collect(), + file_hash_memo: default(), + } + } +} + +pub async fn modules_from_ghjkfile(hcx: Arc) -> Res> { + let (hashfile_path, lockfile_path) = ( + hcx.gcx.ghjk_dir_path.join("hash.json"), + hcx.gcx.ghjk_dir_path.join("lock.json"), + ); + + let (hash_obj, lock_obj) = ( + HashObj::from_file(&hashfile_path), + LockObj::from_file(&lockfile_path), + ) + .join() + .await; + + let (mut hash_obj, mut lock_obj) = ( + hash_obj.inspect_err(|err| warn!("{err}")).ok(), + lock_obj.inspect_err(|err| warn!("{err}")).ok(), + ); + + if hcx.config.locked { + if hash_obj.is_none() { + eyre::bail!("locked flag is set but no hashfile found"); + } + if lock_obj.is_none() { + eyre::bail!("locked flag is set but no lockfile found"); + } + } + + let (ghjkfile_exists, ghjkfile_hash) = if let Some(path) = &hcx.gcx.ghjkfile_path { + ( + matches!(tokio::fs::try_exists(path).await, Ok(true)), + Some(file_content_digest_hash(hcx.as_ref(), path).await?), + ) + } else { + (false, None) + }; + + // check if we need to discard the hashfile + if let Some(obj) = &mut hash_obj { + // TODO: version migrator + if obj.version != "0" { + eyre::bail!("unsupported hashfile version: {:?}", obj.version); + } + if !hcx.config.locked + && (hcx.config.re_serialize + || ghjkfile_hash.is_none() + || obj + .is_stale(hcx.as_ref(), ghjkfile_hash.as_ref().unwrap()) + .await?) + { + hash_obj = None; + } + } + // check if we need to discard the lockfile + if let Some(obj) = &mut lock_obj { + // TODO: version migrator + if obj.version != "0" { + eyre::bail!("unsupported hashfile version: {:?}", obj.version); + } + // if obj.version != "0" { + // hash_obj = None; + // } + } + // TODO: + // if hcx.re_resolve {} + + let mut lock_entries = HashMap::new(); + + if let Some(lock_obj) = &mut lock_obj { + debug!(?lockfile_path, "loading lockfile"); + for mod_conf in &lock_obj.config.modules { + let Some(mod_man) = hcx.modules.get(&mod_conf.id) else { + eyre::bail!( + "unrecognized module found in lockfile config: {:?}", + mod_conf.id + ); + }; + let Some(mod_lock) = lock_obj.module_entries.swap_remove(&mod_conf.id) else { + eyre::bail!( + "no lock entry found for module specified by lockfile config: {:?}", + mod_conf.id + ); + }; + let mut mod_inst = mod_man.init(); + lock_entries.insert( + mod_conf.id.clone(), + mod_inst.load_lock_entry(&hcx.gcx, mod_lock).await?, + ); + } + } + + let mut fresh_serialized = false; + + let (config, hash_obj) = if let (Some(lock_obj), Some(hash_obj)) = (&lock_obj, hash_obj) { + // Only recover the old config if the hash_obj and lock_obj haven't + // been discarded by the cache invalidation checks above. + // Assumes that a hashfile tags the specific serialized version of the ghjkfile + // and it's context put in the lockfile + (lock_obj.config.clone(), hash_obj) + } else if let Some(ghjkfile_path) = &hcx.gcx.ghjkfile_path { + if !ghjkfile_exists { + eyre::bail!("no file found at ghjkfile path {ghjkfile_path:?}"); + } + if hcx.config.locked { + unreachable!("code should have early exited"); + } + info!(?ghjkfile_path, "serializing ghjkfile"); + fresh_serialized = true; + serialize_ghjkfile(hcx.as_ref(), ghjkfile_path) + .await + .wrap_err("error serializing ghjkfile")? + } else { + if hcx.config.locked { + unreachable!("code should have early exited"); + } + return Ok(None); + }; + + let mod_instances = { + let mut mod_instances = IndexMap::new(); + for mod_conf in &config.modules { + let Some(mod_man) = hcx.modules.get(&mod_conf.id) else { + eyre::bail!( + "unrecognized module specified by ghjkfile: {:?}", + mod_conf.id + ); + }; + let mut mod_inst = mod_man.init(); + let mod_cx = mod_inst + .load_config( + &hcx.gcx, + &config.blackboard, + lock_entries.remove(&mod_conf.id), + ) + .await + .wrap_err_with(|| format!("error loading module config: {:?}", mod_conf.id))?; + mod_instances.insert(mod_conf.id.clone(), (mod_inst, mod_cx)); + } + mod_instances + }; + + Ok(Some(GhjkfileModules { + hcx, + config, + mod_instances, + hash_obj, + old_lock_obj: lock_obj, + lockfile_path, + hashfile_path, + fresh_serialized, + hashfile_written: false, + })) +} + +pub struct GhjkfileModules { + hcx: Arc, + config: Arc, + hash_obj: HashObj, + mod_instances: IndexMap, + old_lock_obj: Option, + lockfile_path: PathBuf, + hashfile_path: PathBuf, + fresh_serialized: bool, + hashfile_written: bool, +} + +impl GhjkfileModules { + async fn write_lockfile(&mut self) -> Res<()> { + let mut lock_obj = LockObj { + version: "0".into(), + config: self.config.clone(), + module_entries: default(), + }; + // generate the lock entries after *all* the modules + // are done processing their config to allow + // any shared stores to be properly populated + // e.g. the resolution memo store + for (mod_id, (mod_inst, mcx)) in &mut self.mod_instances { + let lock_entry = mod_inst + .gen_lock_entry(&self.hcx.gcx, mcx) + .await + .wrap_err_with(|| { + format!("error generating lock entry for module: {:?}", mod_id) + })?; + lock_obj.module_entries.insert(mod_id.clone(), lock_entry); + } + + if self.old_lock_obj.is_none() + || matches!(self.old_lock_obj.as_ref(), Some(old) if !old.eq(&lock_obj)) + { + if self.hcx.config.locked { + warn!("locked flag set, changes to lockfile discarded"); + } else { + tokio::fs::write( + &self.lockfile_path, + serde_json::to_vec_pretty(&lock_obj).expect_or_log("error jsonifying lockfile"), + ) + .await + .wrap_err("error writing to lockfile")?; + self.old_lock_obj.replace(lock_obj); + } + } + + // Only write out hashfile when a fresh serialization + // result was saved in the lock file. + if self.fresh_serialized && !self.hashfile_written { + if self.hcx.config.locked { + unreachable!("code should have early exited"); + } + tokio::fs::write( + &self.lockfile_path, + serde_json::to_vec_pretty(&self.hash_obj) + .expect_or_log("error jsonifying hashfile"), + ) + .await + .wrap_err("error writing to lockfile")?; + self.hashfile_written = true; + } + Ok(()) + } +} + +async fn serialize_ghjkfile(hcx: &HostCtx, path: &Path) -> Res<(Arc, HashObj)> { + let ext = path.extension(); + let res = if ext.map(|ext| ext == "ts" || ext == "js") == Some(true) { + debug!("serializing deno ghjkfile"); + serialize_deno_ghjkfile(hcx, path).await? + } else { + eyre::bail!("unrecognized ghjkfile extension: {path:?}") + }; + Ok(( + Arc::new(res.config), + HashObj { + version: "0".into(), + env_var_hashes: env_var_digests( + &hcx.config.env_vars, + res.accessed_env_keys.iter().map(|key| key.as_ref()), + ), + ghjkfile_hash: file_digest_hash(hcx, path).await?.unwrap(), + listed_files: res + .listed_file_paths + .into_iter() + .map(|path| pathdiff::diff_paths(path, &hcx.config.cwd).unwrap_or_log()) + .collect(), + read_file_hashes: file_digests( + hcx, + res.read_file_paths + .iter() + .map(|path| path.as_ref()) + .collect(), + ) + .await?, + }, + )) +} + +async fn serialize_deno_ghjkfile(hcx: &HostCtx, path: &Path) -> Res { + use denort::deno::deno_runtime; + let main_module = deno_runtime::deno_core::resolve_path( + hcx.gcx.repo_root.join("./files/deno/mod2.ts"), + &hcx.config.cwd, + ) + .wrap_err("error resolving main module")?; + + // let (stdout_r, stdout_w) = deno_runtime::deno_io::pipe()?; + // let (stderr_r, stderr_w) = deno_runtime::deno_io::pipe()?; + let mut worker = hcx + .gcx + .deno + .prepare_module( + main_module.clone(), + deno_runtime::deno_permissions::PermissionsOptions { + allow_env: Some(vec![]), + allow_import: Some(vec![]), + allow_read: Some(vec![]), + allow_net: Some(vec![]), + ..default() + }, + deno_runtime::WorkerExecutionMode::Run, + deno_runtime::deno_io::Stdio { + // stdout: deno_runtime::deno_io::StdioPipe::file(stdout_w), + // stderr: deno_runtime::deno_io::StdioPipe::file(stderr_w), + ..default() + }, + ) + .await?; + + let exit_code = worker.run().await?; + info!(%exit_code, %main_module, "module done"); + for url in worker.get_visited_files().await { + info!(%url, %main_module, "visited files"); + } + Ok(todo!()) +} + +struct SerializationResult { + config: SerializedConfig, + accessed_env_keys: Vec, + read_file_paths: Vec, + listed_file_paths: Vec, +} + +type ModuleId = CHeapStr; + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +struct ModuleConfig { + pub id: ModuleId, + pub config: serde_json::Value, +} + +type ConfigBlackboard = serde_json::Map; + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +struct SerializedConfig { + modules: Vec, + blackboard: ConfigBlackboard, +} + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub struct LockObj { + pub version: String, + pub module_entries: indexmap::IndexMap, + pub config: Arc, +} + +impl LockObj { + /// The lock.json file stores the serialized config and some entries + /// from modules. It's primary purpose is as a memo store to avoid + /// re-serialization on each CLI invocation. + pub async fn from_file(path: &Path) -> Res { + let raw = tokio::fs::read(path) + .await + .wrap_err("error reading hash.json")?; + serde_json::from_slice(&raw).wrap_err("error parsing lock.json") + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct HashObj { + pub version: String, + /// Hash of the ghjkfile contents. + pub ghjkfile_hash: String, + /// Hashes of all env vars that were read. + pub env_var_hashes: indexmap::IndexMap>, + /// Hashes of all files that were read. + pub read_file_hashes: indexmap::IndexMap>, + /// File paths that were observed from the fs but not necessarily + /// read. + pub listed_files: Vec, +} + +impl HashObj { + /// The hash.json file stores the digests of all external accesses + /// of a ghjkfile during serialization. The primary purpose is to + /// do "cache invalidation" on ghjkfiles, re-serializing them if + /// any of the digests change. + pub async fn from_file(path: &Path) -> Res { + let raw = tokio::fs::read(path) + .await + .wrap_err("error reading hash.json")?; + serde_json::from_slice(&raw).wrap_err("error parsing hash.json") + } + + pub async fn is_stale(&self, hcx: &HostCtx, ghjkfile_hash: &str) -> Res { + if self.ghjkfile_hash != ghjkfile_hash { + return Ok(true); + } + { + let new_digest = env_var_digests( + &hcx.config.env_vars, + self.env_var_hashes.keys().map(|key| &key[..]), + ); + if self.env_var_hashes != new_digest { + return Ok(true); + } + } + { + for path in &self.listed_files { + if !matches!(tokio::fs::try_exists(path).await, Ok(true)) { + return Ok(true); + } + } + } + { + if self.read_file_hashes + != file_digests( + &hcx, + self.read_file_hashes + .keys() + .map(|path| path.as_ref()) + .collect(), + ) + .await? + { + return Ok(true); + } + } + Ok(false) + } +} + +fn env_var_digests<'a>( + all: &IndexMap, + accessed: impl Iterator, +) -> IndexMap> { + accessed + .map(|key| { + ( + key.to_owned(), + match all.get(key) { + Some(val) => Some(utils::hash_str(val)), + None => None, + }, + ) + }) + .collect() +} + +async fn file_digests( + hcx: &HostCtx, + read_files: Vec<&Path>, +) -> Res>> { + let out = read_files + .into_co_stream() + .map(|path| async move { + let path = tokio::fs::canonicalize(path).await?; + let hash = file_digest_hash(hcx, &path).await?; + let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); + Ok((relative_path, hash)) + }) + .collect::>>() + .await?; + Ok(out.into_iter().collect()) +} + +async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> { + let path = tokio::fs::canonicalize(path) + .await + .wrap_err("error resolving realpath")?; + match tokio::fs::metadata(&path).await { + Ok(stat) => { + let content_hash = if stat.file_type().is_file() || stat.file_type().is_symlink() { + Some(file_content_digest_hash(hcx, &path).await?) + } else { + None + }; + + Ok(Some(crate::utils::hash_obj(&serde_json::json!({ + "content_hash": content_hash, + "stat": StatMeta::from(stat) + })))) + } + Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None), + Err(err) => Err(err).wrap_err("error on file stat"), + } +} + +async fn file_content_digest_hash(hcx: &HostCtx, path: &Path) -> Res { + let path = tokio::fs::canonicalize(path) + .await + .wrap_err("error resolving realpath")?; + use dashmap::mapref::entry::*; + match hcx.file_hash_memo.entry(path.clone()) { + Entry::Occupied(occupied_entry) => Ok(occupied_entry.get().clone()), + Entry::Vacant(vacant_entry) => { + // FIXME: optimize by stream hashing, this reads whole file into memory + let file = tokio::fs::read(path) + .await + .wrap_err("error reading file for")?; + let hash: CHeapStr = crate::utils::encode_base32_multibase(file).into(); + vacant_entry.insert(hash.clone()); + Ok(hash) + } + } +} + +#[derive(Serialize)] +struct StatMeta { + accessed: Option, + created: Option, + modified: Option, + is_file: bool, + is_dir: bool, + is_symlink: bool, + size: u64, + #[cfg(unix)] + mode: u32, +} + +impl From for StatMeta { + fn from(value: std::fs::Metadata) -> Self { + fn unwrap_opt_sys_time(inp: std::io::Result) -> Option { + inp.map_err(|_| ()) + .and_then(|ts| { + ts.duration_since(std::time::SystemTime::UNIX_EPOCH) + .map_err(|_| ()) + }) + .and_then(|dur| Ok(dur.as_secs())) + .ok() + } + #[cfg(unix)] + use std::os::unix::fs::PermissionsExt; + + Self { + // file_type: match value.file_type() {}, + accessed: unwrap_opt_sys_time(value.accessed()), + created: unwrap_opt_sys_time(value.created()), + modified: unwrap_opt_sys_time(value.modified()), + is_file: value.is_file(), + is_symlink: value.is_symlink(), + is_dir: value.is_dir(), + size: value.len(), + #[cfg(unix)] + mode: value.permissions().mode(), + } + } +} diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index 6664f3f..b88084c 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -2,14 +2,18 @@ mod interlude { pub use crate::utils::{default, CHeapStr, DHashMap}; + pub use std::collections::HashMap; pub use std::future::Future; pub use std::path::{Path, PathBuf}; pub use std::sync::Arc; + pub use crate::GhjkCtx; + pub use color_eyre::eyre; pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; pub use futures::{future::BoxFuture, FutureExt}; - use futures_concurrency::prelude::*; + pub use futures_concurrency::{future::Join, prelude::*}; + pub use indexmap::IndexMap; pub use serde::{Deserialize, Serialize}; pub use serde_json::json; pub use smallvec::smallvec as svec; @@ -17,6 +21,10 @@ mod interlude { pub use tracing::{debug, error, info, trace, warn}; pub use tracing_unwrap::*; } + +mod host; + +mod cli {} mod utils; use crate::interlude::*; @@ -38,131 +46,120 @@ fn main() -> Res<()> { Ok(()) } -use denort::deno::deno_runtime; use shadow_rs::shadow; shadow!(build); -const DEFAULT_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; +const DENO_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; async fn cli() -> Res<()> { debug!(version = build::VERSION, "ghjk CLI"); let cwd = std::env::current_dir()?; - let gcx = GhjkCtx { - deno: denort::Context::from_config( - denort::deno::args::Flags { - unstable_config: denort::deno::args::UnstableConfig { - features: DEFAULT_UNSTABLE_FLAGS - .iter() - .copied() - .map(String::from) - .collect(), - ..default() - }, - ..default() - }, - Some(Arc::new(Vec::new)), - ) - .await?, + let ghjk_dir_path = match std::env::var("GHJK_DIR") { + Ok(path) => Some(PathBuf::from(path)), + Err(std::env::VarError::NotUnicode(os_str)) => Some(PathBuf::from(os_str)), + Err(std::env::VarError::NotPresent) => utils::find_entry_recursive(&cwd, ".ghjk").await?, }; - { - let main_module = deno_runtime::deno_core::resolve_url_or_path("play.ts", &cwd) - .wrap_err("error resolving main module")?; - let mut worker = gcx - .deno - .run_module( - main_module.clone(), - &deno_runtime::deno_permissions::PermissionsOptions { - allow_env: Some(vec![]), - allow_import: Some(vec![]), - allow_read: Some(vec![]), - allow_net: Some(vec![]), - ..default() - }, - deno_runtime::WorkerExecutionMode::Run, - deno_runtime::deno_io::Stdio::default(), + let ghjk_dir_path = if let Some(path) = ghjk_dir_path { + Some(tokio::fs::canonicalize(path).await?) + } else { + None + }; + + let ghjkfile_path = match &ghjk_dir_path { + Some(ghjkfile_path) => { + utils::find_entry_recursive( + ghjkfile_path + .parent() + .expect_or_log("invalid GHJK_DIR path"), + "ghjk.ts", ) - .await?; - let exit_code = worker.run().await?; - info!(%exit_code, %main_module, "module done"); - for url in worker.visted_files() { - info!(%url, %main_module, "visited files"); + .await? } + None => utils::find_entry_recursive(&cwd, "ghjk.ts").await?, + }; + + let ghjkfile_path = if let Some(path) = ghjkfile_path { + Some(tokio::fs::canonicalize(path).await?) + } else { + None + }; + + if ghjk_dir_path.is_none() && ghjkfile_path.is_none() { + warn!("ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.",); } - Ok(()) -} -struct GhjkCtx { - deno: denort::Context, -} + let share_dir_path = match std::env::var("GHJK_SHARE_DIR") { + Ok(path) => PathBuf::from(path), + Err(std::env::VarError::NotUnicode(os_str)) => PathBuf::from(os_str), + Err(std::env::VarError::NotPresent) => directories::BaseDirs::new() + .expect_or_log("unable to resolve home dir") + .data_local_dir() + .join("ghjk"), + }; -#[derive(Debug)] -struct Config { - ghjkfile: PathBuf, - share_dir: PathBuf, - ghjk_dir: PathBuf, -} + if let Some(ghjk_dir_path) = ghjk_dir_path { + let gcx = GhjkCtx { + ghjk_dir_path, + ghjkfile_path, + share_dir_path, + repo_root: cwd.clone(), + deno: denort::worker( + denort::deno::args::Flags { + unstable_config: denort::deno::args::UnstableConfig { + features: DENO_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..default() + }, + ..default() + }, + Some(Arc::new(Vec::new)), + ) + .await?, + }; + let gcx = Arc::new(gcx); + + let hcx = host::HostCtx::new( + gcx, + host::Config { + re_resolve: false, + locked: false, + re_serialize: false, + env_vars: std::env::vars().collect(), + cwd, + }, + ); -async fn look_for_ghjkfile() {} + let hcx = Arc::new(hcx); -#[tracing::instrument] -async fn commands_from_ghjkfile(config: &Config) { - // let lockfile_path = config.ghjk_dir.join("lock.json"); - // let hashfile_path = config.ghjk_dir.join("hash.json"); -} + if let Some(modules) = host::modules_from_ghjkfile(hcx).await? { + } else { + warn!("no ghjkfile found"); + } + } -// #[tracing::instrument] -// async fn read_ghjkfile(config: &Config) { -// match config.ghjkfile.extension() { -// Some("") | Some("ts") => { -// if let Some("") = config.ghjkfile.extension() { -// warn!("ghjkfile has no extension, assuming deno ghjkfile") -// } -// debug!("serializing deno ghjkfile") -// } -// } -// } - -struct SerializationResult { - config: serde_json::Value, - accessed_env_keys: Vec, - read_file_paths: Vec, - listed_file_paths: Vec, + Ok(()) } -async fn serialize_ghjk_ts() -> Res { - Ok(todo!()) +#[derive(Debug)] +pub struct GhjkCtx { + deno: denort::DenoWorkerHandle, + repo_root: PathBuf, + ghjkfile_path: Option, + ghjk_dir_path: PathBuf, + share_dir_path: PathBuf, } -mod hashflile { - use crate::interlude::*; - - #[derive(Debug, Serialize, Deserialize)] - struct HashObj { - version: String, - /// Hash of the ghjkfile contents. - ghjkfile_hash: String, - /// Hashes of all env vars that were read. - env_var_hashes: indexmap::IndexMap>, - /// Hashes of all files that were read. - read_file_hashes: indexmap::IndexMap>, - /// File paths that were observed from the fs but not necessarily - /// read. - listed_files: Vec, - } - - /// The hash.json file stores the digests of all external accesses - /// of a ghjkfile during serialization. The primary purpose is to - /// do "cache invalidation" on ghjkfiles, re-serializing them if - /// any of the digests change. - async fn read_hash_file(path: &Path) -> Res { - let raw = tokio::fs::read(path) - .await - .wrap_err("error reading hash.json")?; - serde_json::from_slice(&raw).wrap_err("error parsing hash.json") - } +#[derive(Debug)] +struct Config { + ghjkfile_path: Option, + ghjk_dir_path: Option, + share_dir_path: PathBuf, } /* mod files { diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index d43cd9b..07e7667 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -1,3 +1,5 @@ +use std::io::Write; + use crate::interlude::*; // Ensure that the `tracing` stack is only initialised once using `once_cell` @@ -153,3 +155,85 @@ mod cheapstr { } } } + +const SHA2_256: u64 = 0x12; + +pub fn hash_obj(obj: &T) -> String { + use sha2::Digest; + let mut hash = sha2::Sha256::new(); + json_canon::to_writer(&mut hash, obj).expect("error serializing manifest"); + let hash = hash.finalize(); + + let hash = multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect("error multihashing"); + encode_base32_multibase(hash.digest()) +} + +pub fn hash_str(string: &str) -> String { + use sha2::Digest; + let mut hash = sha2::Sha256::new(); + hash.write(string.as_bytes()) + .expect_or_log("error writing to hasher"); + let hash = hash.finalize(); + + let hash = multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect("error multihashing"); + encode_base32_multibase(hash.digest()) +} + +pub fn encode_base32_multibase>(source: T) -> String { + format!("b{}", data_encoding::BASE32_NOPAD.encode(source.as_ref())) +} + +// Consider z-base32 https://en.wikipedia.org/wiki/Base32#z-base-32 +pub fn decode_base32_multibase(source: &str) -> eyre::Result> { + match ( + &source[0..1], + data_encoding::BASE32_NOPAD.decode(source[1..].as_bytes()), + ) { + ("b", Ok(bytes)) => Ok(bytes), + (prefix, Ok(_)) => Err(eyre::format_err!( + "unexpected multibase prefix for base32 multibase: {prefix}" + )), + (_, Err(err)) => Err(eyre::format_err!("error decoding base32: {err}")), + } +} + +pub fn encode_hex_multibase>(source: T) -> String { + format!( + "f{}", + data_encoding::HEXLOWER_PERMISSIVE.encode(source.as_ref()) + ) +} + +pub fn decode_hex_multibase(source: &str) -> eyre::Result> { + match ( + &source[0..1], + data_encoding::HEXLOWER_PERMISSIVE.decode(source[1..].as_bytes()), + ) { + ("f", Ok(bytes)) => Ok(bytes), + (prefix, Ok(_)) => Err(eyre::format_err!( + "unexpected multibase prefix for hex multibase: {prefix}" + )), + (_, Err(err)) => Err(eyre::format_err!("error decoding hex: {err}")), + } +} + +pub async fn find_entry_recursive(from: &Path, name: &str) -> Res> { + let mut cur = from; + loop { + let location = cur.join(name); + match tokio::fs::try_exists(&location).await { + Ok(_) => { + return Ok(Some(location)); + } + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + let Some(next_cur) = cur.parent() else { + return Ok(None); + }; + cur = next_cur; + } + Err(err) => { + return Err(err).wrap_err("error on file stat"); + } + } + } +} From b3529a5e79bfcbb9901bedc62af7ff19574db77e Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:44:33 +0300 Subject: [PATCH 07/15] feat: working serialization --- .vscode/settings.json | 3 +- Cargo.lock | 57 ++++----- Cargo.toml | 6 +- files/deno/mod2.ts | 34 ++++-- src/denort/Cargo.toml | 3 +- src/denort/lib.rs | 138 +++++++++++---------- src/ghjk/Cargo.toml | 1 + src/ghjk/deno.rs | 82 +++++++++++++ src/ghjk/deno/00_runtime.js | 34 ++++++ src/ghjk/deno/runtime.d.ts | 13 ++ src/ghjk/deno/runtime.js | 9 ++ src/ghjk/host.rs | 235 ++---------------------------------- src/ghjk/host/deno.rs | 76 ++++++++++++ src/ghjk/host/hashfile.rs | 184 ++++++++++++++++++++++++++++ src/ghjk/main.rs | 10 ++ src/ghjk/utils.rs | 6 + 16 files changed, 560 insertions(+), 331 deletions(-) create mode 100644 src/ghjk/deno.rs create mode 100644 src/ghjk/deno/00_runtime.js create mode 100644 src/ghjk/deno/runtime.d.ts create mode 100644 src/ghjk/deno/runtime.js create mode 100644 src/ghjk/host/deno.rs create mode 100644 src/ghjk/host/hashfile.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index 2d317f4..6317ba2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,6 +25,7 @@ "ghjkfiles", "Hashfile", "indexmap", + "kwargs", "POSIX", "runtimes", "sophon" @@ -37,4 +38,4 @@ "latex", "plaintext" ] -} \ No newline at end of file +} diff --git a/Cargo.lock b/Cargo.lock index 3d4538b..e54e388 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1189,7 +1189,7 @@ dependencies = [ [[package]] name = "deno" version = "2.0.6" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "anstream", "async-trait", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "deno_broadcast_channel" version = "0.171.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-trait", "deno_core", @@ -1367,7 +1367,7 @@ dependencies = [ [[package]] name = "deno_cache" version = "0.109.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-trait", "deno_core", @@ -1401,7 +1401,7 @@ dependencies = [ [[package]] name = "deno_canvas" version = "0.46.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_webgpu", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "deno_console" version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", ] @@ -1483,7 +1483,7 @@ checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1" [[package]] name = "deno_cron" version = "0.57.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "anyhow", "async-trait", @@ -1497,7 +1497,7 @@ dependencies = [ [[package]] name = "deno_crypto" version = "0.191.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "aes", "aes-gcm", @@ -1560,7 +1560,7 @@ dependencies = [ [[package]] name = "deno_fetch" version = "0.201.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "base64 0.21.7", "bytes", @@ -1593,7 +1593,7 @@ dependencies = [ [[package]] name = "deno_ffi" version = "0.164.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_permissions", @@ -1614,7 +1614,7 @@ dependencies = [ [[package]] name = "deno_fs" version = "0.87.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-trait", "base32", @@ -1666,7 +1666,7 @@ dependencies = [ [[package]] name = "deno_http" version = "0.175.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-compression", "async-trait", @@ -1703,7 +1703,7 @@ dependencies = [ [[package]] name = "deno_io" version = "0.87.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-trait", "deno_core", @@ -1725,7 +1725,7 @@ dependencies = [ [[package]] name = "deno_kv" version = "0.85.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "anyhow", "async-trait", @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "deno_napi" version = "0.108.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_permissions", @@ -1826,7 +1826,7 @@ dependencies = [ [[package]] name = "deno_net" version = "0.169.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_permissions", @@ -1844,7 +1844,7 @@ dependencies = [ [[package]] name = "deno_node" version = "0.114.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "aead-gcm-stream", "aes", @@ -1994,7 +1994,7 @@ dependencies = [ [[package]] name = "deno_permissions" version = "0.37.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_path_util", @@ -2013,7 +2013,7 @@ dependencies = [ [[package]] name = "deno_resolver" version = "0.9.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "anyhow", "base32", @@ -2029,7 +2029,7 @@ dependencies = [ [[package]] name = "deno_runtime" version = "0.186.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "color-print", "deno_ast", @@ -2147,7 +2147,7 @@ dependencies = [ [[package]] name = "deno_tls" version = "0.164.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_native_certs", @@ -2197,7 +2197,7 @@ dependencies = [ [[package]] name = "deno_url" version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "thiserror", @@ -2207,7 +2207,7 @@ dependencies = [ [[package]] name = "deno_web" version = "0.208.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "async-trait", "base64-simd 0.8.0", @@ -2226,7 +2226,7 @@ dependencies = [ [[package]] name = "deno_webgpu" version = "0.144.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "raw-window-handle", @@ -2240,7 +2240,7 @@ dependencies = [ [[package]] name = "deno_webidl" version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", ] @@ -2248,7 +2248,7 @@ dependencies = [ [[package]] name = "deno_websocket" version = "0.182.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "bytes", "deno_core", @@ -2271,7 +2271,7 @@ dependencies = [ [[package]] name = "deno_webstorage" version = "0.172.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "deno_core", "deno_web", @@ -3424,6 +3424,7 @@ dependencies = [ "color-eyre", "dashmap", "data-encoding", + "deno_core", "denort", "directories", "educe", @@ -4768,7 +4769,7 @@ dependencies = [ [[package]] name = "napi_sym" version = "0.107.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "quote", "serde", @@ -4836,7 +4837,7 @@ dependencies = [ [[package]] name = "node_resolver" version = "0.16.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#c1a873ec2de8aba7e7dad79667ae2ed74b18f091" +source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index ff7cc9c..4464176 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,10 @@ edition = "2021" [workspace.dependencies] denort = { path = "src/denort" } +deno = { git = "https://github.com/metatypedev/deno", branch = "v2.0.6-embeddable" } +# needed to get deno_core::op2 working +# must track version used by deno +deno_core = "=0.318.0" educe = "0.6" @@ -28,4 +32,4 @@ clap = "=4.5" shadow-rs = "0.36.0" -tokio = "1" \ No newline at end of file +tokio = "1" diff --git a/files/deno/mod2.ts b/files/deno/mod2.ts index 61a1505..ccb1da5 100644 --- a/files/deno/mod2.ts +++ b/files/deno/mod2.ts @@ -8,17 +8,27 @@ // NOTE: only import types import { shimDenoNamespace } from "../../utils/worker.ts"; +import { zod } from "../../deps/common.ts"; -const shimHandle = shimDenoNamespace(Deno.env.toObject()); -const { setup: setupLogger } = await import("../../utils/logger.ts"); -setupLogger(); -const uri = import.meta.resolve("../../ghjk.ts"); -const mod = await import(uri); -const rawConfig = await mod.sophon.getConfig(uri, mod.secureConfig); -const config = JSON.parse(JSON.stringify(rawConfig)); -console.log({ - config, - accessedEnvKeys: shimHandle.getAccessedEnvKeys(), - readFiles: shimHandle.getReadFiles(), - listedFiles: shimHandle.getListedFiles(), +const serializeArgs = zod.object({ + uri: zod.string(), }); + +async function serialize(args: zod.infer) { + const shimHandle = shimDenoNamespace(Deno.env.toObject()); + const { setup: setupLogger } = await import("../../utils/logger.ts"); + setupLogger(); + const mod = await import(args.uri); + const rawConfig = await mod.sophon.getConfig(args.uri, mod.secureConfig); + const config = JSON.parse(JSON.stringify(rawConfig)); + return { + config, + accessedEnvKeys: shimHandle.getAccessedEnvKeys(), + readFilePaths: shimHandle.getReadFiles(), + listedFilePaths: shimHandle.getListedFiles(), + }; +} + +const args = serializeArgs.parse(Ghjk.blackboard.get("args")); +const resp = await serialize(args); +Ghjk.blackboard.set("resp", resp); diff --git a/src/denort/Cargo.toml b/src/denort/Cargo.toml index 2d20b59..54c4a0c 100644 --- a/src/denort/Cargo.toml +++ b/src/denort/Cargo.toml @@ -17,7 +17,6 @@ anyhow.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -deno = { git = "https://github.com/metatypedev/deno", branch = "v2.0.6-embeddable" } +deno.workspace = true tokio.workspace = true -# deno_core = "=0.291.0" \ No newline at end of file diff --git a/src/denort/lib.rs b/src/denort/lib.rs index d346a3c..4769097 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -54,59 +54,75 @@ pub async fn worker( let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); let rt = tokio::runtime::Handle::current(); - std::thread::spawn(move || { - let local = tokio::task::LocalSet::new(); - - local.spawn_local(async move { - while let Some(req) = rx.recv().await { - match req { - DenoWorkerReq::PrepareModule { - response_channel, - main_module, - permissions, - mode, - stdio, - } => { - let mut module_cx = match cx - .prepare_module(main_module, &permissions, mode, stdio) - .await - { - Ok(val) => val, - Err(err) => { - response_channel - .send(Err(err)) - .expect_or_log("channel error"); - continue; - } - }; - - let (module_tx, mut module_rx) = - tokio::sync::mpsc::unbounded_channel::(); - tokio::task::spawn_local(async move { - while let Some(req) = module_rx.recv().await { - match req { - ModuleWorkerReq::Run { response_channel } => response_channel - .send(module_cx.run().await) - .expect_or_log("channel error"), - ModuleWorkerReq::GetVisitedFiles { response_channel } => { - response_channel - .send(module_cx.get_visited_files()) - .expect_or_log("channel error") + + let join_handle = new_thread_builder() + .spawn(move || { + let local = tokio::task::LocalSet::new(); + + local.spawn_local(async move { + while let Some(req) = rx.recv().await { + match req { + DenoWorkerReq::PrepareModule { + response_channel, + main_module, + permissions, + mode, + stdio, + custom_extensions_cb, + } => { + let mut module_cx = match cx + .prepare_module( + main_module, + &permissions, + mode, + stdio, + custom_extensions_cb, + ) + .await + { + Ok(val) => val, + Err(err) => { + response_channel + .send(Err(err)) + .expect_or_log("channel error"); + continue; + } + }; + + let (module_tx, mut module_rx) = + tokio::sync::mpsc::unbounded_channel::(); + tokio::task::spawn_local(async move { + while let Some(req) = module_rx.recv().await { + match req { + ModuleWorkerReq::Run { response_channel } => { + response_channel + .send(module_cx.run().await) + .expect_or_log("channel error") + } + ModuleWorkerReq::GetLoadedModules { response_channel } => { + response_channel + .send(module_cx.get_loaded_modules()) + .expect_or_log("channel error") + } } } - } - }); + }); - response_channel - .send(Ok(ModuleWorkerHandle { sender: module_tx })) - .expect_or_log("channel error"); + response_channel + .send(Ok(ModuleWorkerHandle { sender: module_tx })) + .expect_or_log("channel error"); + } } } - } - }); - rt.block_on(local); - }); - Ok(DenoWorkerHandle { sender: tx }) + }); + rt.block_on(local); + }) + .unwrap(); + let join_handle = Arc::new(join_handle); + Ok(DenoWorkerHandle { + sender: tx, + join_handle, + }) } #[derive(educe::Educe)] @@ -117,15 +133,13 @@ struct WorkerContext { #[educe(Debug(ignore))] worker_factory: deno::worker::CliMainWorkerFactory, #[educe(Debug(ignore))] - custom_extensions_cb: Option>, - #[educe(Debug(ignore))] graph: Arc, } impl WorkerContext { async fn from_config( flags: deno::args::Flags, - custom_extensions_cb: Option>, + root_custom_extensions_cb: Option>, ) -> Res { deno_permissions::set_prompt_callbacks( Box::new(util::draw_thread::DrawThread::hide), @@ -135,7 +149,7 @@ impl WorkerContext { let flags = args::Flags { ..flags }; let flags = Arc::new(flags); let cli_factory = factory::CliFactory::from_flags(flags); - let cli_factory = if let Some(custom_extensions_cb) = &custom_extensions_cb { + let cli_factory = if let Some(custom_extensions_cb) = &root_custom_extensions_cb { cli_factory.with_custom_ext_cb(custom_extensions_cb.clone()) } else { cli_factory @@ -153,7 +167,6 @@ impl WorkerContext { Ok(Self { cli_factory, worker_factory, - custom_extensions_cb, graph, }) } @@ -164,6 +177,7 @@ impl WorkerContext { permissions: &deno_permissions::PermissionsOptions, mode: deno_runtime::WorkerExecutionMode, stdio: deno_runtime::deno_io::Stdio, + custom_extensions_cb: Option>, ) -> Res { let desc_parser = self .cli_factory @@ -179,10 +193,7 @@ impl WorkerContext { mode, main_module.clone(), permissions, - self.custom_extensions_cb - .as_ref() - .map(|cb| cb()) - .unwrap_or_default(), + custom_extensions_cb, stdio, ) .await @@ -203,12 +214,14 @@ enum DenoWorkerReq { permissions: deno_permissions::PermissionsOptions, mode: deno_runtime::WorkerExecutionMode, stdio: deno_runtime::deno_io::Stdio, + custom_extensions_cb: Option>, }, } #[derive(Clone, Debug)] pub struct DenoWorkerHandle { sender: tokio::sync::mpsc::UnboundedSender, + join_handle: Arc>, } impl DenoWorkerHandle { @@ -218,6 +231,7 @@ impl DenoWorkerHandle { permissions: deno_permissions::PermissionsOptions, mode: deno_runtime::WorkerExecutionMode, stdio: deno_runtime::deno_io::Stdio, + custom_extensions_cb: Option>, ) -> Res { let (tx, rx) = tokio::sync::oneshot::channel(); self.sender @@ -227,6 +241,7 @@ impl DenoWorkerHandle { permissions, mode, stdio, + custom_extensions_cb, }) .expect_or_log("channel error"); rx.await.expect_or_log("channel error") @@ -244,7 +259,7 @@ struct ModuleWorkerContext { } impl ModuleWorkerContext { - fn get_visited_files(&self) -> Vec { + fn get_loaded_modules(&self) -> Vec { use deno::graph_container::*; self.graph .graph() @@ -257,7 +272,6 @@ impl ModuleWorkerContext { prefer_fast_check_graph: false, }, ) - .filter(|(url, _)| url.scheme() == "file") .map(|(url, _)| url.clone()) .collect() } @@ -271,7 +285,7 @@ enum ModuleWorkerReq { Run { response_channel: tokio::sync::oneshot::Sender>, }, - GetVisitedFiles { + GetLoadedModules { response_channel: tokio::sync::oneshot::Sender>, }, } @@ -281,10 +295,10 @@ pub struct ModuleWorkerHandle { sender: tokio::sync::mpsc::UnboundedSender, } impl ModuleWorkerHandle { - pub async fn get_visited_files(&mut self) -> Vec { + pub async fn get_loaded_modules(&mut self) -> Vec { let (tx, rx) = tokio::sync::oneshot::channel(); self.sender - .send(ModuleWorkerReq::GetVisitedFiles { + .send(ModuleWorkerReq::GetLoadedModules { response_channel: tx, }) .expect_or_log("channel error"); diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index 0a03832..89bb4b7 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -9,6 +9,7 @@ path = "main.rs" [dependencies] denort.workspace = true +deno_core.workspace = true serde = "1" serde_json = "1" diff --git a/src/ghjk/deno.rs b/src/ghjk/deno.rs new file mode 100644 index 0000000..c8506f4 --- /dev/null +++ b/src/ghjk/deno.rs @@ -0,0 +1,82 @@ +use crate::interlude::*; + +#[rustfmt::skip] +use deno_core as deno_core; // necessary for re-exported macros to work + +pub fn extensions(config: ExtConfig) -> Arc { + // let atom = std::sync::atomic::AtomicBool::new(false); + Arc::new(move || { + // if atom.load(std::sync::atomic::Ordering::SeqCst) { + // return vec![]; + // } + // atom.store(true, std::sync::atomic::Ordering::SeqCst); + vec![ghjk_deno_ext::init_ops_and_esm(config.clone())] + }) +} + +// This is used to populate the deno_core::OpState with dependencies +// used by the different ops +#[derive(Clone)] +pub struct ExtConfig { + pub blackboard: Arc>, +} + +impl ExtConfig { + pub fn new(blackboard: Arc>) -> Self { + Self { blackboard } + } + + fn inject(self, state: &mut deno_core::OpState) { + state.put(ExtContext { + blackboard: self.blackboard.clone(), + }); + } +} + +deno_core::extension!( + ghjk_deno_ext, + ops = [op_get_blackboard, op_set_blackboard], + options = { config: ExtConfig }, + state = |state, opt| { + opt.config.inject(state); + }, + customizer = |ext: &mut deno_core::Extension| { + customizer(ext); + }, + docs = "Kitchen sink extension for all ghjk needs.", +); + +fn customizer(ext: &mut deno_core::Extension) { + ext.esm_files + .to_mut() + .push(deno_core::ExtensionFileSource::new( + "ext:ghjk_deno_ext/00_runtime.js", + deno_core::ascii_str_include!("deno/00_runtime.js"), + )); + ext.esm_entry_point = Some("ext:ghjk_deno_ext/00_runtime.js"); +} + +struct ExtContext { + blackboard: Arc>, +} + +#[deno_core::op2] +#[serde] +pub fn op_get_blackboard( + #[state] ctx: &ExtContext, + #[string] key: &str, +) -> Option { + ctx.blackboard.get(key).map(|val| val.clone()) +} + +#[deno_core::op2] +#[serde] +pub fn op_set_blackboard( + #[state] ctx: &ExtContext, + #[string] key: String, + #[serde] val: serde_json::Value, +) -> Option { + ctx.blackboard + .insert(key.into(), val) + .map(|val| val.clone()) +} diff --git a/src/ghjk/deno/00_runtime.js b/src/ghjk/deno/00_runtime.js new file mode 100644 index 0000000..e4ce282 --- /dev/null +++ b/src/ghjk/deno/00_runtime.js @@ -0,0 +1,34 @@ +// const { core } = Deno[Deno.internal]; +const { core } = Deno; +const { ops } = core; +// const fastops = core.ensureFastOps(); // TODO: investigate + +// NOTE: use the following import if ever switching to snaphsots +// import * as ops from "ext:core/ops"; + +function getOp(name) { + // Note: always get the op right away. + // the core.ops object is a proxy + // that retrieves the named op + // when requested i.e. not a + // hashmap prepopulated by the ops. + // If we don't get the op now, the + // proxy behvior won't be avail later at runtime + const op = ops[name]; + if (!op) { + throw Error(`op: ${name} not found`); + } + return op; +} + +/** + * @type {import('./runtime.d.ts').GhjkNs} + */ +const Ghjk = { + blackboard: { + get: getOp("op_get_blackboard"), + set: getOp("op_set_blackboard"), + }, +}; + +globalThis.Ghjk = Ghjk; diff --git a/src/ghjk/deno/runtime.d.ts b/src/ghjk/deno/runtime.d.ts new file mode 100644 index 0000000..1e2a931 --- /dev/null +++ b/src/ghjk/deno/runtime.d.ts @@ -0,0 +1,13 @@ +type JsonLiteral = string | number | boolean | null; + +export type JsonObject = { [key: string]: Json }; +export type JsonArray = Json[]; +export type Json = JsonLiteral | JsonObject | JsonArray; + +type GhjkNs = { + blackboard: { + get: (key: string) => Json | undefined; + set: (key: string, value: Json) => Json | undefined; + }; +}; +export const Ghjk: GhjkNs; diff --git a/src/ghjk/deno/runtime.js b/src/ghjk/deno/runtime.js new file mode 100644 index 0000000..c7d977e --- /dev/null +++ b/src/ghjk/deno/runtime.js @@ -0,0 +1,9 @@ +/// + +//! This file provides the import point for types and values defined in: +// - ./00_runtime.js: which is preloaded by the custom deno runtime +// - ./runtime.d.ts: which types the objects from the preload +// +// The preload directly adds the Meta object the global scope but we can hide +// that implementation detail and users will "import" `Meta` from this file instead. +// Or at least that is what will appear to be happening to in the type system. diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index 94329ee..df01517 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -1,4 +1,8 @@ -use crate::{interlude::*, utils}; +use crate::interlude::*; + +mod deno; +mod hashfile; +use hashfile::*; #[derive(educe::Educe)] #[educe(Debug)] @@ -237,7 +241,7 @@ pub async fn modules_from_ghjkfile(hcx: Arc) -> Res, - config: Arc, + pub config: Arc, hash_obj: HashObj, mod_instances: IndexMap, old_lock_obj: Option, @@ -248,7 +252,7 @@ pub struct GhjkfileModules { } impl GhjkfileModules { - async fn write_lockfile(&mut self) -> Res<()> { + pub async fn write_lockfile(&mut self) -> Res<()> { let mut lock_obj = LockObj { version: "0".into(), config: self.config.clone(), @@ -307,7 +311,7 @@ async fn serialize_ghjkfile(hcx: &HostCtx, path: &Path) -> Res<(Arc Res<(Arc Res { - use denort::deno::deno_runtime; - let main_module = deno_runtime::deno_core::resolve_path( - hcx.gcx.repo_root.join("./files/deno/mod2.ts"), - &hcx.config.cwd, - ) - .wrap_err("error resolving main module")?; - - // let (stdout_r, stdout_w) = deno_runtime::deno_io::pipe()?; - // let (stderr_r, stderr_w) = deno_runtime::deno_io::pipe()?; - let mut worker = hcx - .gcx - .deno - .prepare_module( - main_module.clone(), - deno_runtime::deno_permissions::PermissionsOptions { - allow_env: Some(vec![]), - allow_import: Some(vec![]), - allow_read: Some(vec![]), - allow_net: Some(vec![]), - ..default() - }, - deno_runtime::WorkerExecutionMode::Run, - deno_runtime::deno_io::Stdio { - // stdout: deno_runtime::deno_io::StdioPipe::file(stdout_w), - // stderr: deno_runtime::deno_io::StdioPipe::file(stderr_w), - ..default() - }, - ) - .await?; - - let exit_code = worker.run().await?; - info!(%exit_code, %main_module, "module done"); - for url in worker.get_visited_files().await { - info!(%url, %main_module, "visited files"); - } - Ok(todo!()) -} - struct SerializationResult { config: SerializedConfig, accessed_env_keys: Vec, read_file_paths: Vec, listed_file_paths: Vec, + loaded_modules: Vec, } type ModuleId = CHeapStr; @@ -394,7 +360,7 @@ struct ModuleConfig { type ConfigBlackboard = serde_json::Map; #[derive(Debug, Serialize, Deserialize, PartialEq)] -struct SerializedConfig { +pub struct SerializedConfig { modules: Vec, blackboard: ConfigBlackboard, } @@ -417,184 +383,3 @@ impl LockObj { serde_json::from_slice(&raw).wrap_err("error parsing lock.json") } } - -#[derive(Debug, Serialize, Deserialize)] -pub struct HashObj { - pub version: String, - /// Hash of the ghjkfile contents. - pub ghjkfile_hash: String, - /// Hashes of all env vars that were read. - pub env_var_hashes: indexmap::IndexMap>, - /// Hashes of all files that were read. - pub read_file_hashes: indexmap::IndexMap>, - /// File paths that were observed from the fs but not necessarily - /// read. - pub listed_files: Vec, -} - -impl HashObj { - /// The hash.json file stores the digests of all external accesses - /// of a ghjkfile during serialization. The primary purpose is to - /// do "cache invalidation" on ghjkfiles, re-serializing them if - /// any of the digests change. - pub async fn from_file(path: &Path) -> Res { - let raw = tokio::fs::read(path) - .await - .wrap_err("error reading hash.json")?; - serde_json::from_slice(&raw).wrap_err("error parsing hash.json") - } - - pub async fn is_stale(&self, hcx: &HostCtx, ghjkfile_hash: &str) -> Res { - if self.ghjkfile_hash != ghjkfile_hash { - return Ok(true); - } - { - let new_digest = env_var_digests( - &hcx.config.env_vars, - self.env_var_hashes.keys().map(|key| &key[..]), - ); - if self.env_var_hashes != new_digest { - return Ok(true); - } - } - { - for path in &self.listed_files { - if !matches!(tokio::fs::try_exists(path).await, Ok(true)) { - return Ok(true); - } - } - } - { - if self.read_file_hashes - != file_digests( - &hcx, - self.read_file_hashes - .keys() - .map(|path| path.as_ref()) - .collect(), - ) - .await? - { - return Ok(true); - } - } - Ok(false) - } -} - -fn env_var_digests<'a>( - all: &IndexMap, - accessed: impl Iterator, -) -> IndexMap> { - accessed - .map(|key| { - ( - key.to_owned(), - match all.get(key) { - Some(val) => Some(utils::hash_str(val)), - None => None, - }, - ) - }) - .collect() -} - -async fn file_digests( - hcx: &HostCtx, - read_files: Vec<&Path>, -) -> Res>> { - let out = read_files - .into_co_stream() - .map(|path| async move { - let path = tokio::fs::canonicalize(path).await?; - let hash = file_digest_hash(hcx, &path).await?; - let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); - Ok((relative_path, hash)) - }) - .collect::>>() - .await?; - Ok(out.into_iter().collect()) -} - -async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> { - let path = tokio::fs::canonicalize(path) - .await - .wrap_err("error resolving realpath")?; - match tokio::fs::metadata(&path).await { - Ok(stat) => { - let content_hash = if stat.file_type().is_file() || stat.file_type().is_symlink() { - Some(file_content_digest_hash(hcx, &path).await?) - } else { - None - }; - - Ok(Some(crate::utils::hash_obj(&serde_json::json!({ - "content_hash": content_hash, - "stat": StatMeta::from(stat) - })))) - } - Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None), - Err(err) => Err(err).wrap_err("error on file stat"), - } -} - -async fn file_content_digest_hash(hcx: &HostCtx, path: &Path) -> Res { - let path = tokio::fs::canonicalize(path) - .await - .wrap_err("error resolving realpath")?; - use dashmap::mapref::entry::*; - match hcx.file_hash_memo.entry(path.clone()) { - Entry::Occupied(occupied_entry) => Ok(occupied_entry.get().clone()), - Entry::Vacant(vacant_entry) => { - // FIXME: optimize by stream hashing, this reads whole file into memory - let file = tokio::fs::read(path) - .await - .wrap_err("error reading file for")?; - let hash: CHeapStr = crate::utils::encode_base32_multibase(file).into(); - vacant_entry.insert(hash.clone()); - Ok(hash) - } - } -} - -#[derive(Serialize)] -struct StatMeta { - accessed: Option, - created: Option, - modified: Option, - is_file: bool, - is_dir: bool, - is_symlink: bool, - size: u64, - #[cfg(unix)] - mode: u32, -} - -impl From for StatMeta { - fn from(value: std::fs::Metadata) -> Self { - fn unwrap_opt_sys_time(inp: std::io::Result) -> Option { - inp.map_err(|_| ()) - .and_then(|ts| { - ts.duration_since(std::time::SystemTime::UNIX_EPOCH) - .map_err(|_| ()) - }) - .and_then(|dur| Ok(dur.as_secs())) - .ok() - } - #[cfg(unix)] - use std::os::unix::fs::PermissionsExt; - - Self { - // file_type: match value.file_type() {}, - accessed: unwrap_opt_sys_time(value.accessed()), - created: unwrap_opt_sys_time(value.created()), - modified: unwrap_opt_sys_time(value.modified()), - is_file: value.is_file(), - is_symlink: value.is_symlink(), - is_dir: value.is_dir(), - size: value.len(), - #[cfg(unix)] - mode: value.permissions().mode(), - } - } -} diff --git a/src/ghjk/host/deno.rs b/src/ghjk/host/deno.rs new file mode 100644 index 0000000..c78168b --- /dev/null +++ b/src/ghjk/host/deno.rs @@ -0,0 +1,76 @@ +use crate::interlude::*; + +use denort::deno::deno_runtime; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct InternalSerializationResult { + config: super::SerializedConfig, + accessed_env_keys: Vec, + read_file_paths: Vec, + listed_file_paths: Vec, +} + +pub async fn serialize_deno_ghjkfile( + hcx: &super::HostCtx, + path: &Path, +) -> Res { + let main_module = deno_runtime::deno_core::resolve_path( + hcx.gcx.repo_root.join("./files/deno/mod2.ts"), + &hcx.config.cwd, + ) + .wrap_err("error resolving main module")?; + + let blackboard = [ + // blackboard is used as communication means + // with the deno side of the code + ( + "args".into(), + serde_json::json!({ + "uri": url::Url::from_file_path(path).unwrap_or_log(), + }), + ), + ] + .into_iter() + .collect::>(); + + let blackboard = Arc::new(blackboard); + + let mut worker = hcx + .gcx + .deno + .prepare_module( + main_module.clone(), + deno_runtime::deno_permissions::PermissionsOptions { + allow_env: Some(vec![]), + allow_import: Some(vec![]), + allow_read: Some(vec![]), + allow_net: Some(vec![]), + ..default() + }, + deno_runtime::WorkerExecutionMode::Run, + default(), + Some(crate::deno::extensions(crate::deno::ExtConfig { + blackboard: blackboard.clone(), + })), + ) + .await?; + + let exit_code = worker.run().await?; + if exit_code != 0 { + eyre::bail!("non-zero exit code running deno module"); + } + let loaded_modules = worker.get_loaded_modules().await; + + let (_, resp) = blackboard.remove("resp").expect_or_log("resp missing"); + let resp: InternalSerializationResult = + serde_json::from_value(resp).expect_or_log("error deserializing resp"); + + Ok(super::SerializationResult { + config: resp.config, + accessed_env_keys: resp.accessed_env_keys, + listed_file_paths: resp.listed_file_paths, + read_file_paths: resp.read_file_paths, + loaded_modules, + }) +} diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs new file mode 100644 index 0000000..97d4c8d --- /dev/null +++ b/src/ghjk/host/hashfile.rs @@ -0,0 +1,184 @@ +use crate::interlude::*; + +use super::HostCtx; + +#[derive(Debug, Serialize, Deserialize)] +pub struct HashObj { + pub version: String, + /// Hash of the ghjkfile contents. + pub ghjkfile_hash: String, + /// Hashes of all env vars that were read. + pub env_var_hashes: indexmap::IndexMap>, + /// Hashes of all files that were read. + pub read_file_hashes: indexmap::IndexMap>, + /// File paths that were observed from the fs but not necessarily + /// read. + pub listed_files: Vec, +} + +impl HashObj { + /// The hash.json file stores the digests of all external accesses + /// of a ghjkfile during serialization. The primary purpose is to + /// do "cache invalidation" on ghjkfiles, re-serializing them if + /// any of the digests change. + pub async fn from_file(path: &Path) -> Res { + let raw = tokio::fs::read(path) + .await + .wrap_err("error reading hash.json")?; + serde_json::from_slice(&raw).wrap_err("error parsing hash.json") + } + + pub async fn is_stale(&self, hcx: &HostCtx, ghjkfile_hash: &str) -> Res { + if self.ghjkfile_hash != ghjkfile_hash { + return Ok(true); + } + { + let new_digest = env_var_digests( + &hcx.config.env_vars, + self.env_var_hashes.keys().map(|key| &key[..]), + ); + if self.env_var_hashes != new_digest { + return Ok(true); + } + } + { + for path in &self.listed_files { + if !matches!(tokio::fs::try_exists(path).await, Ok(true)) { + return Ok(true); + } + } + } + { + if self.read_file_hashes + != file_digests( + &hcx, + self.read_file_hashes + .keys() + .map(|path| path.as_ref()) + .collect(), + ) + .await? + { + return Ok(true); + } + } + Ok(false) + } +} + +pub fn env_var_digests<'a>( + all: &IndexMap, + accessed: impl Iterator, +) -> IndexMap> { + accessed + .map(|key| { + ( + key.to_owned(), + match all.get(key) { + Some(val) => Some(crate::utils::hash_str(val)), + None => None, + }, + ) + }) + .collect() +} + +pub async fn file_digests( + hcx: &HostCtx, + read_files: Vec<&Path>, +) -> Res>> { + let out = read_files + .into_co_stream() + .map(|path| async move { + let path = tokio::fs::canonicalize(path).await?; + let hash = file_digest_hash(hcx, &path).await?; + let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); + Ok((relative_path, hash)) + }) + .collect::>>() + .await?; + Ok(out.into_iter().collect()) +} + +pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> { + let path = tokio::fs::canonicalize(path) + .await + .wrap_err("error resolving realpath")?; + match tokio::fs::metadata(&path).await { + Ok(stat) => { + let content_hash = if stat.file_type().is_file() || stat.file_type().is_symlink() { + Some(file_content_digest_hash(hcx, &path).await?) + } else { + None + }; + + Ok(Some(crate::utils::hash_obj(&serde_json::json!({ + "content_hash": content_hash, + "stat": StatMeta::from(stat) + })))) + } + Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None), + Err(err) => Err(err).wrap_err("error on file stat"), + } +} + +pub async fn file_content_digest_hash(hcx: &HostCtx, path: &Path) -> Res { + let path = tokio::fs::canonicalize(path) + .await + .wrap_err("error resolving realpath")?; + use dashmap::mapref::entry::*; + match hcx.file_hash_memo.entry(path.clone()) { + Entry::Occupied(occupied_entry) => Ok(occupied_entry.get().clone()), + Entry::Vacant(vacant_entry) => { + // FIXME: optimize by stream hashing, this reads whole file into memory + let file = tokio::fs::read(path) + .await + .wrap_err("error reading file for")?; + let hash: CHeapStr = crate::utils::encode_base32_multibase(file).into(); + vacant_entry.insert(hash.clone()); + Ok(hash) + } + } +} + +#[derive(Serialize)] +struct StatMeta { + accessed: Option, + created: Option, + modified: Option, + is_file: bool, + is_dir: bool, + is_symlink: bool, + size: u64, + #[cfg(unix)] + mode: u32, +} + +impl From for StatMeta { + fn from(value: std::fs::Metadata) -> Self { + fn unwrap_opt_sys_time(inp: std::io::Result) -> Option { + inp.map_err(|_| ()) + .and_then(|ts| { + ts.duration_since(std::time::SystemTime::UNIX_EPOCH) + .map_err(|_| ()) + }) + .and_then(|dur| Ok(dur.as_secs())) + .ok() + } + #[cfg(unix)] + use std::os::unix::fs::PermissionsExt; + + Self { + // file_type: match value.file_type() {}, + accessed: unwrap_opt_sys_time(value.accessed()), + created: unwrap_opt_sys_time(value.created()), + modified: unwrap_opt_sys_time(value.modified()), + is_file: value.is_file(), + is_symlink: value.is_symlink(), + is_dir: value.is_dir(), + size: value.len(), + #[cfg(unix)] + mode: value.permissions().mode(), + } + } +} diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index b88084c..25f172f 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -10,6 +10,13 @@ mod interlude { pub use crate::GhjkCtx; pub use color_eyre::eyre; + pub use denort::deno::{ + self, + deno_runtime::{ + self, + deno_core::{self, url}, + }, + }; pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; pub use futures::{future::BoxFuture, FutureExt}; pub use futures_concurrency::{future::Join, prelude::*}; @@ -25,6 +32,7 @@ mod interlude { mod host; mod cli {} +mod deno; mod utils; use crate::interlude::*; @@ -138,6 +146,8 @@ async fn cli() -> Res<()> { let hcx = Arc::new(hcx); if let Some(modules) = host::modules_from_ghjkfile(hcx).await? { + let conf_json = serde_json::to_string_pretty(&modules.config)?; + info!(%conf_json); } else { warn!("no ghjkfile found"); } diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index 07e7667..d71783f 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -121,6 +121,12 @@ mod cheapstr { } } + impl std::borrow::Borrow for CHeapStr { + fn borrow(&self) -> &str { + &self[..] + } + } + impl From for CHeapStr { fn from(string: String) -> Self { /* let byte_arc: Arc<[u8]> = string.into_bytes().into(); From 3e054d29ced38f6f46e654abeae82be325dfb371 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Sun, 1 Dec 2024 23:21:37 +0300 Subject: [PATCH 08/15] feat: `DenoSystems` --- .ghjk/lock.json | 38 +- Cargo.lock | 6 +- Cargo.toml | 1 + deno.lock | 720 +++++++++++++--------------- deps/common.ts | 2 +- files/deno/{mod2.ts => bindings.ts} | 1 + ghjk.ts | 4 + host/mod.ts | 18 +- modules/envs/mod.ts | 33 +- modules/mod.ts | 19 +- modules/ports/mod.ts | 31 +- modules/tasks/mod.ts | 35 +- src/deno_systems/bindings.ts | 126 +++++ src/deno_systems/mod.ts | 10 + src/denort/lib.rs | 415 ++++++++++++---- src/denort/promises.rs | 70 +++ src/ghjk/Cargo.toml | 3 + src/ghjk/deno.rs | 82 ---- src/ghjk/ext.rs | 125 +++++ src/ghjk/ext/callbacks.rs | 293 +++++++++++ src/ghjk/host.rs | 184 +++---- src/ghjk/host/deno.rs | 47 +- src/ghjk/host/hashfile.rs | 9 +- src/ghjk/{deno => js}/00_runtime.js | 13 +- src/ghjk/js/mock.sfx.ts | 20 + src/ghjk/{deno => js}/runtime.d.ts | 7 +- src/ghjk/{deno => js}/runtime.js | 0 src/ghjk/log.rs | 95 ++++ src/ghjk/main.rs | 158 +++--- src/ghjk/systems.rs | 112 +++++ src/ghjk/systems/deno.rs | 256 ++++++++++ src/ghjk/utils.rs | 64 +-- utils/mod.ts | 11 +- 33 files changed, 2116 insertions(+), 892 deletions(-) rename files/deno/{mod2.ts => bindings.ts} (95%) create mode 100644 src/deno_systems/bindings.ts create mode 100644 src/deno_systems/mod.ts create mode 100644 src/denort/promises.rs delete mode 100644 src/ghjk/deno.rs create mode 100644 src/ghjk/ext.rs create mode 100644 src/ghjk/ext/callbacks.rs rename src/ghjk/{deno => js}/00_runtime.js (74%) create mode 100644 src/ghjk/js/mock.sfx.ts rename src/ghjk/{deno => js}/runtime.d.ts (59%) rename src/ghjk/{deno => js}/runtime.js (100%) create mode 100644 src/ghjk/log.rs create mode 100644 src/ghjk/systems.rs create mode 100644 src/ghjk/systems/deno.rs diff --git a/.ghjk/lock.json b/.ghjk/lock.json index b597a41..410bbd9 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -308,13 +308,13 @@ "lock-sed": { "ty": "denoFile@v1", "key": "lock-sed", - "envKey": "bciqa3gn6bjbmgjf7mvk7cv6wfjo23wj3vyppgtpqt4ovvxkpzjrcvua" + "envKey": "bciqlneazfye2nq2cb4jsgigjqisrzm25gdkyitmotyl3qmq5nf3nb7y" }, "cache-v8": { "ty": "denoFile@v1", "key": "cache-v8", "desc": "Install the V8 builds to a local cache.", - "envKey": "bciqjzvefargmop4vyqujvr7igrjunekxn5dmfqezjd2rgrdji5xpdai" + "envKey": "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny" } }, "tasksNamed": [ @@ -327,33 +327,53 @@ "id": "envs", "config": { "envs": { - "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya": { + "bciqazjf2gsxfy4wt2gd6qsou4pciedy7dyhdch5l7gsmoq62boo2s7a": { "desc": "the default default environment.", "provides": [ + { + "ty": "posix.envVar", + "key": "RUST_LOG", + "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + }, { "ty": "ghjk.ports.InstallSetRef", "setId": "ghjkEnvProvInstSet___main" } ] }, - "bciqa3gn6bjbmgjf7mvk7cv6wfjo23wj3vyppgtpqt4ovvxkpzjrcvua": { + "bciqlneazfye2nq2cb4jsgigjqisrzm25gdkyitmotyl3qmq5nf3nb7y": { "provides": [ + { + "ty": "posix.envVar", + "key": "RUST_LOG", + "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + }, { "ty": "ghjk.ports.InstallSetRef", "setId": "ghjkEnvProvInstSet___main" } ] }, - "bciqjzvefargmop4vyqujvr7igrjunekxn5dmfqezjd2rgrdji5xpdai": { + "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny": { "provides": [ + { + "ty": "posix.envVar", + "key": "RUST_LOG", + "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + }, { "ty": "ghjk.ports.InstallSetRef", "setId": "ghjkEnvProvInstSet____rust" } ] }, - "bciqjiedgfyl4fsp2j64t4xk2sc7ei4eri75x2wqyczcmnthtgupg33a": { + "bciqe26fbb6fkfbou7w3rf3t2uqw4neldvakclhcecktgtpcuxwnzgja": { "provides": [ + { + "ty": "posix.envVar", + "key": "RUST_LOG", + "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + }, { "ty": "posix.envVar", "key": "RUSTY_V8_MIRROR", @@ -368,9 +388,9 @@ }, "defaultEnv": "dev", "envsNamed": { - "main": "bciqfzekhtsrjd72noxifmici3ssck4jgvbjwhxwhhwtirzm7yomhxya", - "_rust": "bciqjzvefargmop4vyqujvr7igrjunekxn5dmfqezjd2rgrdji5xpdai", - "dev": "bciqjiedgfyl4fsp2j64t4xk2sc7ei4eri75x2wqyczcmnthtgupg33a" + "main": "bciqazjf2gsxfy4wt2gd6qsou4pciedy7dyhdch5l7gsmoq62boo2s7a", + "_rust": "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny", + "dev": "bciqe26fbb6fkfbou7w3rf3t2uqw4neldvakclhcecktgtpcuxwnzgja" } } } diff --git a/Cargo.lock b/Cargo.lock index e54e388..421172d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -309,9 +309,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -3419,6 +3419,8 @@ name = "ghjk" version = "0.3.0" dependencies = [ "ahash", + "anyhow", + "async-trait", "bitflags 2.6.0", "clap", "color-eyre", diff --git a/Cargo.toml b/Cargo.toml index 4464176..2372000 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = ["src/*"] +exclude = ["src/deno_systems"] resolver = "2" [workspace.package] diff --git a/deno.lock b/deno.lock index 77a1293..6d7581e 100644 --- a/deno.lock +++ b/deno.lock @@ -1,381 +1,347 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@david/dax@0.40.1": "jsr:@david/dax@0.40.1", - "jsr:@david/dax@0.41.0": "jsr:@david/dax@0.41.0", - "jsr:@david/which@0.3": "jsr:@david/which@0.3.0", - "jsr:@david/which@^0.4.1": "jsr:@david/which@0.4.1", - "jsr:@ghjk/dax@0.40.2-alpha-ghjk": "jsr:@ghjk/dax@0.40.2-alpha-ghjk", - "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0", - "jsr:@std/bytes@^0.221.0": "jsr:@std/bytes@0.221.0", - "jsr:@std/fmt@^0.221.0": "jsr:@std/fmt@0.221.0", - "jsr:@std/fs@0.221.0": "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0": "jsr:@std/io@0.221.0", - "jsr:@std/io@^0.221.0": "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0": "jsr:@std/path@0.221.0", - "jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0": "jsr:@std/streams@0.221.0", - "npm:@livekit/rtc-node@0.11.1": "npm:@livekit/rtc-node@0.11.1", - "npm:@noble/hashes@1.4.0": "npm:@noble/hashes@1.4.0", - "npm:@types/node": "npm:@types/node@18.16.19", - "npm:livekit-server-sdk@2.7.2": "npm:livekit-server-sdk@2.7.2", - "npm:lodash": "npm:lodash@4.17.21", - "npm:mathjs@11.11.1": "npm:mathjs@11.11.1", - "npm:multiformats@13.1.0": "npm:multiformats@13.1.0", - "npm:pg": "npm:pg@8.12.0", - "npm:validator": "npm:validator@13.12.0", - "npm:zod-validation-error": "npm:zod-validation-error@3.1.0_zod@3.23.3", - "npm:zod-validation-error@3.2.0": "npm:zod-validation-error@3.2.0_zod@3.23.3", - "npm:zod-validation-error@3.3.0": "npm:zod-validation-error@3.3.0_zod@3.23.3", - "npm:zod@3.23.8": "npm:zod@3.23.8" - }, - "jsr": { - "@david/dax@0.40.1": { - "integrity": "0c71d32a0484d3904f586417995f8ec26d45144f0eba95d3e5bb03b640b6df59", - "dependencies": [ - "jsr:@david/which@0.3", - "jsr:@std/fmt@^0.221.0", - "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0" - ] - }, - "@david/dax@0.41.0": { - "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8", - "dependencies": [ - "jsr:@david/which@^0.4.1", - "jsr:@std/fmt@^0.221.0", - "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0" - ] - }, - "@david/which@0.3.0": { - "integrity": "6bdb62c40ac90edcf328e854fa8103a8db21e7c326089cbe3c3a1cf7887d3204" - }, - "@david/which@0.4.1": { - "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" - }, - "@ghjk/dax@0.40.2-alpha-ghjk": { - "integrity": "87bc93e9947779cb2f3922fe277e21ea8c716de804b2627f80ba9e7bc3d0d019", - "dependencies": [ - "jsr:@david/which@0.3", - "jsr:@std/fmt@^0.221.0", - "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0" - ] - }, - "@std/assert@0.221.0": { - "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" - }, - "@std/bytes@0.221.0": { - "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" - }, - "@std/fmt@0.221.0": { - "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" - }, - "@std/fs@0.221.0": { - "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", - "dependencies": [ - "jsr:@std/assert@^0.221.0", - "jsr:@std/path@^0.221.0" - ] - }, - "@std/io@0.221.0": { - "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", - "dependencies": [ - "jsr:@std/assert@^0.221.0", - "jsr:@std/bytes@^0.221.0" - ] - }, - "@std/path@0.221.0": { - "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", - "dependencies": [ - "jsr:@std/assert@^0.221.0" - ] - }, - "@std/streams@0.221.0": { - "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61", - "dependencies": [ - "jsr:@std/io@^0.221.0" - ] - } - }, - "npm": { - "@babel/runtime@7.24.7": { - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", - "dependencies": { - "regenerator-runtime": "regenerator-runtime@0.14.1" - } - }, - "@bufbuild/protobuf@1.10.0": { - "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==", - "dependencies": {} - }, - "@bufbuild/protobuf@2.2.2": { - "integrity": "sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==", - "dependencies": {} - }, - "@livekit/mutex@1.1.0": { - "integrity": "sha512-XRLG+z/0uoyDioupjUiskjI06Y51U/IXVPJn7qJ+R3J75XX01irYVBM9MpxeJahpVoe9QhU4moIEolX+HO9U9g==", - "dependencies": {} - }, - "@livekit/protocol@1.27.1": { - "integrity": "sha512-ISEp7uWdV82mtCR1eyHFTzdRZTVbe2+ZztjmjiMPzR/KPrI1Ma/u5kLh87NNuY3Rn8wv1VlEvGHHsFjQ+dKVUw==", - "dependencies": { - "@bufbuild/protobuf": "@bufbuild/protobuf@1.10.0" - } - }, - "@livekit/rtc-node-darwin-arm64@0.11.1": { - "integrity": "sha512-M+Ui87H06ae19GGI7r937dS6hI84MBBTQAkkNlL7qd+pvdCAk25u0FYa8r4SOElKJ0VR3AbzeDoXTihLgpvjMg==", - "dependencies": {} - }, - "@livekit/rtc-node-darwin-x64@0.11.1": { - "integrity": "sha512-7G92fyuK2p+jdTH2cUJTNeAmtknTGsXuy0xbI727V7VzQvHFDXULCExRlgwn4t9TxvNlIjUpiltiQ6RCSai6zw==", - "dependencies": {} - }, - "@livekit/rtc-node-linux-arm64-gnu@0.11.1": { - "integrity": "sha512-vqZN9+87Pvxit7auYVW69M+GvUPnf+EwipIJ92GgCJA3Ir1Tcceu5ud5/Ic+0FzSoV0cotVVlQNm74F0tQvyCg==", - "dependencies": {} - }, - "@livekit/rtc-node-linux-x64-gnu@0.11.1": { - "integrity": "sha512-smHZUMfgILQh6/eoauYNe/VlKwQCp4/4jWxiIADHY+mtDtVSvQ9zB6y4GP8FrpohRwFWesKCUpvPBypU0Icrng==", - "dependencies": {} - }, - "@livekit/rtc-node-win32-x64-msvc@0.11.1": { - "integrity": "sha512-bTWVtb+UiRPFjiuhrqq40gt5vs5mMPTa1e+kd2jGQPTOlKZPLArQ0WgFcep2TAy1zmcpOgfeM1XRPVFhZl7G1A==", - "dependencies": {} - }, - "@livekit/rtc-node@0.11.1": { - "integrity": "sha512-EFw+giPll12fcXATZpN2zKkE3umYJAdHvfjW+Yu0aBjwfxbUBXu8rz6le2CzDNvGmRwR888DSZXFZfYikwZgiw==", - "dependencies": { - "@bufbuild/protobuf": "@bufbuild/protobuf@2.2.2", - "@livekit/mutex": "@livekit/mutex@1.1.0", - "@livekit/rtc-node-darwin-arm64": "@livekit/rtc-node-darwin-arm64@0.11.1", - "@livekit/rtc-node-darwin-x64": "@livekit/rtc-node-darwin-x64@0.11.1", - "@livekit/rtc-node-linux-arm64-gnu": "@livekit/rtc-node-linux-arm64-gnu@0.11.1", - "@livekit/rtc-node-linux-x64-gnu": "@livekit/rtc-node-linux-x64-gnu@0.11.1", - "@livekit/rtc-node-win32-x64-msvc": "@livekit/rtc-node-win32-x64-msvc@0.11.1", - "@livekit/typed-emitter": "@livekit/typed-emitter@3.0.0" - } - }, - "@livekit/typed-emitter@3.0.0": { - "integrity": "sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg==", - "dependencies": {} - }, - "@noble/hashes@1.4.0": { - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dependencies": {} - }, - "@types/node@18.16.19": { - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==", - "dependencies": {} - }, - "camelcase-keys@9.1.3": { - "integrity": "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==", - "dependencies": { - "camelcase": "camelcase@8.0.0", - "map-obj": "map-obj@5.0.0", - "quick-lru": "quick-lru@6.1.2", - "type-fest": "type-fest@4.26.1" - } - }, - "camelcase@8.0.0": { - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dependencies": {} - }, - "complex.js@2.1.1": { - "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", - "dependencies": {} - }, - "decimal.js@10.4.3": { - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dependencies": {} - }, - "escape-latex@1.2.0": { - "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", - "dependencies": {} - }, - "fraction.js@4.3.4": { - "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==", - "dependencies": {} - }, - "javascript-natural-sort@0.7.1": { - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dependencies": {} - }, - "jose@5.9.6": { - "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", - "dependencies": {} - }, - "livekit-server-sdk@2.7.2": { - "integrity": "sha512-qDNRXeo+WMnY5nKSug7KHJ9er9JIuKi+r7H9ZaSBbmbaOt62i0b4BrHBMFSMr8pAuWzuSxihCFa29q5QvFc5fw==", - "dependencies": { - "@livekit/protocol": "@livekit/protocol@1.27.1", - "camelcase-keys": "camelcase-keys@9.1.3", - "jose": "jose@5.9.6" - } - }, - "lodash@4.17.21": { - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dependencies": {} - }, - "map-obj@5.0.0": { - "integrity": "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==", - "dependencies": {} - }, - "mathjs@11.11.1": { - "integrity": "sha512-uWrwMrhU31TCqHKmm1yFz0C352njGUVr/I1UnpMOxI/VBTTbCktx/mREUXx5Vyg11xrFdg/F3wnMM7Ql/csVsQ==", - "dependencies": { - "@babel/runtime": "@babel/runtime@7.24.7", - "complex.js": "complex.js@2.1.1", - "decimal.js": "decimal.js@10.4.3", - "escape-latex": "escape-latex@1.2.0", - "fraction.js": "fraction.js@4.3.4", - "javascript-natural-sort": "javascript-natural-sort@0.7.1", - "seedrandom": "seedrandom@3.0.5", - "tiny-emitter": "tiny-emitter@2.1.0", - "typed-function": "typed-function@4.2.1" - } - }, - "multiformats@13.1.0": { - "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==", - "dependencies": {} - }, - "pg-cloudflare@1.1.1": { - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", - "dependencies": {} - }, - "pg-connection-string@2.6.4": { - "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==", - "dependencies": {} - }, - "pg-int8@1.0.1": { - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dependencies": {} - }, - "pg-pool@3.6.2_pg@8.12.0": { - "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", - "dependencies": { - "pg": "pg@8.12.0" - } - }, - "pg-protocol@1.6.1": { - "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==", - "dependencies": {} - }, - "pg-types@2.2.0": { - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": { - "pg-int8": "pg-int8@1.0.1", - "postgres-array": "postgres-array@2.0.0", - "postgres-bytea": "postgres-bytea@1.0.0", - "postgres-date": "postgres-date@1.0.7", - "postgres-interval": "postgres-interval@1.2.0" - } - }, - "pg@8.12.0": { - "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", - "dependencies": { - "pg-cloudflare": "pg-cloudflare@1.1.1", - "pg-connection-string": "pg-connection-string@2.6.4", - "pg-pool": "pg-pool@3.6.2_pg@8.12.0", - "pg-protocol": "pg-protocol@1.6.1", - "pg-types": "pg-types@2.2.0", - "pgpass": "pgpass@1.0.5" - } - }, - "pgpass@1.0.5": { - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": { - "split2": "split2@4.2.0" - } - }, - "postgres-array@2.0.0": { - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "dependencies": {} - }, - "postgres-bytea@1.0.0": { - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "dependencies": {} - }, - "postgres-date@1.0.7": { - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "dependencies": {} - }, - "postgres-interval@1.2.0": { - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": { - "xtend": "xtend@4.0.2" - } - }, - "quick-lru@6.1.2": { - "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", - "dependencies": {} - }, - "regenerator-runtime@0.14.1": { - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dependencies": {} - }, - "seedrandom@3.0.5": { - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "dependencies": {} - }, - "split2@4.2.0": { - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "dependencies": {} - }, - "tiny-emitter@2.1.0": { - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dependencies": {} - }, - "type-fest@4.26.1": { - "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", - "dependencies": {} - }, - "typed-function@4.2.1": { - "integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==", - "dependencies": {} - }, - "validator@13.12.0": { - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "dependencies": {} - }, - "xtend@4.0.2": { - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dependencies": {} - }, - "zod-validation-error@3.1.0_zod@3.23.3": { - "integrity": "sha512-zujS6HqJjMZCsvjfbnRs7WI3PXN39ovTcY1n8a+KTm4kOH0ZXYsNiJkH1odZf4xZKMkBDL7M2rmQ913FCS1p9w==", - "dependencies": { - "zod": "zod@3.23.3" - } - }, - "zod-validation-error@3.2.0_zod@3.23.3": { - "integrity": "sha512-cYlPR6zuyrgmu2wRTdumEAJGuwI7eHVHGT+VyneAQxmRAKtGRL1/7pjz4wfLhz4J05f5qoSZc3rGacswgyTjjw==", - "dependencies": { - "zod": "zod@3.23.3" - } - }, - "zod-validation-error@3.3.0_zod@3.23.3": { - "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", - "dependencies": { - "zod": "zod@3.23.3" - } - }, - "zod@3.23.3": { - "integrity": "sha512-tPvq1B/2Yu/dh2uAIH2/BhUlUeLIUvAjr6dpL/75I0pCYefHgjhXk1o1Kob3kTU8C7yU1j396jFHlsVWFi9ogg==", - "dependencies": {} - }, - "zod@3.23.8": { - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dependencies": {} - } + "version": "4", + "specifiers": { + "jsr:@david/dax@0.40.1": "0.40.1", + "jsr:@david/dax@0.41.0": "0.41.0", + "jsr:@david/which@0.3": "0.3.0", + "jsr:@david/which@~0.4.1": "0.4.1", + "jsr:@ghjk/dax@0.40.2-alpha-ghjk": "0.40.2-alpha-ghjk", + "jsr:@std/assert@0.221": "0.221.0", + "jsr:@std/bytes@0.221": "0.221.0", + "jsr:@std/fmt@0.221": "0.221.0", + "jsr:@std/fs@0.221.0": "0.221.0", + "jsr:@std/io@0.221": "0.221.0", + "jsr:@std/io@0.221.0": "0.221.0", + "jsr:@std/path@0.221": "0.221.0", + "jsr:@std/path@0.221.0": "0.221.0", + "jsr:@std/streams@0.221.0": "0.221.0", + "npm:@livekit/rtc-node@0.11.1": "0.11.1", + "npm:@noble/hashes@1.4.0": "1.4.0", + "npm:@types/node@*": "18.16.19", + "npm:livekit-server-sdk@2.7.2": "2.7.2", + "npm:lodash@*": "4.17.21", + "npm:mathjs@11.11.1": "11.11.1", + "npm:multiformats@13.1.0": "13.1.0", + "npm:pg@*": "8.12.0", + "npm:validator@*": "13.12.0", + "npm:zod-validation-error@*": "3.1.0_zod@3.23.3", + "npm:zod-validation-error@3.2.0": "3.2.0_zod@3.23.3", + "npm:zod-validation-error@3.3.0": "3.3.0_zod@3.23.3", + "npm:zod-validation-error@3.4.0": "3.4.0_zod@3.23.8", + "npm:zod@3.23.8": "3.23.8" + }, + "jsr": { + "@david/dax@0.40.1": { + "integrity": "0c71d32a0484d3904f586417995f8ec26d45144f0eba95d3e5bb03b640b6df59", + "dependencies": [ + "jsr:@david/which@0.3", + "jsr:@std/fmt", + "jsr:@std/fs", + "jsr:@std/io@0.221.0", + "jsr:@std/path@0.221.0", + "jsr:@std/streams" + ] + }, + "@david/dax@0.41.0": { + "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8", + "dependencies": [ + "jsr:@david/which@~0.4.1", + "jsr:@std/fmt", + "jsr:@std/fs", + "jsr:@std/io@0.221.0", + "jsr:@std/path@0.221.0", + "jsr:@std/streams" + ] + }, + "@david/which@0.3.0": { + "integrity": "6bdb62c40ac90edcf328e854fa8103a8db21e7c326089cbe3c3a1cf7887d3204" + }, + "@david/which@0.4.1": { + "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" + }, + "@ghjk/dax@0.40.2-alpha-ghjk": { + "integrity": "87bc93e9947779cb2f3922fe277e21ea8c716de804b2627f80ba9e7bc3d0d019", + "dependencies": [ + "jsr:@david/which@0.3", + "jsr:@std/fmt", + "jsr:@std/fs", + "jsr:@std/io@0.221.0", + "jsr:@std/path@0.221.0", + "jsr:@std/streams" + ] + }, + "@std/assert@0.221.0": { + "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" + }, + "@std/bytes@0.221.0": { + "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" + }, + "@std/fmt@0.221.0": { + "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" + }, + "@std/fs@0.221.0": { + "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/path@0.221" + ] + }, + "@std/io@0.221.0": { + "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/bytes" + ] + }, + "@std/path@0.221.0": { + "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", + "dependencies": [ + "jsr:@std/assert" + ] + }, + "@std/streams@0.221.0": { + "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61", + "dependencies": [ + "jsr:@std/io@0.221" + ] + } + }, + "npm": { + "@babel/runtime@7.24.7": { + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "dependencies": [ + "regenerator-runtime" + ] + }, + "@bufbuild/protobuf@1.10.0": { + "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==" + }, + "@bufbuild/protobuf@2.2.2": { + "integrity": "sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==" + }, + "@livekit/mutex@1.1.0": { + "integrity": "sha512-XRLG+z/0uoyDioupjUiskjI06Y51U/IXVPJn7qJ+R3J75XX01irYVBM9MpxeJahpVoe9QhU4moIEolX+HO9U9g==" + }, + "@livekit/protocol@1.27.1": { + "integrity": "sha512-ISEp7uWdV82mtCR1eyHFTzdRZTVbe2+ZztjmjiMPzR/KPrI1Ma/u5kLh87NNuY3Rn8wv1VlEvGHHsFjQ+dKVUw==", + "dependencies": [ + "@bufbuild/protobuf@1.10.0" + ] + }, + "@livekit/rtc-node-darwin-arm64@0.11.1": { + "integrity": "sha512-M+Ui87H06ae19GGI7r937dS6hI84MBBTQAkkNlL7qd+pvdCAk25u0FYa8r4SOElKJ0VR3AbzeDoXTihLgpvjMg==" + }, + "@livekit/rtc-node-darwin-x64@0.11.1": { + "integrity": "sha512-7G92fyuK2p+jdTH2cUJTNeAmtknTGsXuy0xbI727V7VzQvHFDXULCExRlgwn4t9TxvNlIjUpiltiQ6RCSai6zw==" + }, + "@livekit/rtc-node-linux-arm64-gnu@0.11.1": { + "integrity": "sha512-vqZN9+87Pvxit7auYVW69M+GvUPnf+EwipIJ92GgCJA3Ir1Tcceu5ud5/Ic+0FzSoV0cotVVlQNm74F0tQvyCg==" + }, + "@livekit/rtc-node-linux-x64-gnu@0.11.1": { + "integrity": "sha512-smHZUMfgILQh6/eoauYNe/VlKwQCp4/4jWxiIADHY+mtDtVSvQ9zB6y4GP8FrpohRwFWesKCUpvPBypU0Icrng==" + }, + "@livekit/rtc-node-win32-x64-msvc@0.11.1": { + "integrity": "sha512-bTWVtb+UiRPFjiuhrqq40gt5vs5mMPTa1e+kd2jGQPTOlKZPLArQ0WgFcep2TAy1zmcpOgfeM1XRPVFhZl7G1A==" + }, + "@livekit/rtc-node@0.11.1": { + "integrity": "sha512-EFw+giPll12fcXATZpN2zKkE3umYJAdHvfjW+Yu0aBjwfxbUBXu8rz6le2CzDNvGmRwR888DSZXFZfYikwZgiw==", + "dependencies": [ + "@bufbuild/protobuf@2.2.2", + "@livekit/mutex", + "@livekit/rtc-node-darwin-arm64", + "@livekit/rtc-node-darwin-x64", + "@livekit/rtc-node-linux-arm64-gnu", + "@livekit/rtc-node-linux-x64-gnu", + "@livekit/rtc-node-win32-x64-msvc", + "@livekit/typed-emitter" + ] + }, + "@livekit/typed-emitter@3.0.0": { + "integrity": "sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg==" + }, + "@noble/hashes@1.4.0": { + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" + }, + "@types/node@18.16.19": { + "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" + }, + "camelcase-keys@9.1.3": { + "integrity": "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==", + "dependencies": [ + "camelcase", + "map-obj", + "quick-lru", + "type-fest" + ] + }, + "camelcase@8.0.0": { + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" + }, + "complex.js@2.1.1": { + "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==" + }, + "decimal.js@10.4.3": { + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "escape-latex@1.2.0": { + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, + "fraction.js@4.3.4": { + "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==" + }, + "javascript-natural-sort@0.7.1": { + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, + "jose@5.9.6": { + "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==" + }, + "livekit-server-sdk@2.7.2": { + "integrity": "sha512-qDNRXeo+WMnY5nKSug7KHJ9er9JIuKi+r7H9ZaSBbmbaOt62i0b4BrHBMFSMr8pAuWzuSxihCFa29q5QvFc5fw==", + "dependencies": [ + "@livekit/protocol", + "camelcase-keys", + "jose" + ] + }, + "lodash@4.17.21": { + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "map-obj@5.0.0": { + "integrity": "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==" + }, + "mathjs@11.11.1": { + "integrity": "sha512-uWrwMrhU31TCqHKmm1yFz0C352njGUVr/I1UnpMOxI/VBTTbCktx/mREUXx5Vyg11xrFdg/F3wnMM7Ql/csVsQ==", + "dependencies": [ + "@babel/runtime", + "complex.js", + "decimal.js", + "escape-latex", + "fraction.js", + "javascript-natural-sort", + "seedrandom", + "tiny-emitter", + "typed-function" + ] + }, + "multiformats@13.1.0": { + "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==" + }, + "pg-cloudflare@1.1.1": { + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==" + }, + "pg-connection-string@2.6.4": { + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" + }, + "pg-int8@1.0.1": { + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool@3.6.2_pg@8.12.0": { + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", + "dependencies": [ + "pg" + ] + }, + "pg-protocol@1.6.1": { + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" + }, + "pg-types@2.2.0": { + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": [ + "pg-int8", + "postgres-array", + "postgres-bytea", + "postgres-date", + "postgres-interval" + ] + }, + "pg@8.12.0": { + "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", + "dependencies": [ + "pg-cloudflare", + "pg-connection-string", + "pg-pool", + "pg-protocol", + "pg-types", + "pgpass" + ] + }, + "pgpass@1.0.5": { + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": [ + "split2" + ] + }, + "postgres-array@2.0.0": { + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea@1.0.0": { + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" + }, + "postgres-date@1.0.7": { + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval@1.2.0": { + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": [ + "xtend" + ] + }, + "quick-lru@6.1.2": { + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==" + }, + "regenerator-runtime@0.14.1": { + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "seedrandom@3.0.5": { + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, + "split2@4.2.0": { + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, + "tiny-emitter@2.1.0": { + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "type-fest@4.26.1": { + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==" + }, + "typed-function@4.2.1": { + "integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==" + }, + "validator@13.12.0": { + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==" + }, + "xtend@4.0.2": { + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "zod-validation-error@3.1.0_zod@3.23.3": { + "integrity": "sha512-zujS6HqJjMZCsvjfbnRs7WI3PXN39ovTcY1n8a+KTm4kOH0ZXYsNiJkH1odZf4xZKMkBDL7M2rmQ913FCS1p9w==", + "dependencies": [ + "zod@3.23.3" + ] + }, + "zod-validation-error@3.2.0_zod@3.23.3": { + "integrity": "sha512-cYlPR6zuyrgmu2wRTdumEAJGuwI7eHVHGT+VyneAQxmRAKtGRL1/7pjz4wfLhz4J05f5qoSZc3rGacswgyTjjw==", + "dependencies": [ + "zod@3.23.3" + ] + }, + "zod-validation-error@3.3.0_zod@3.23.3": { + "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", + "dependencies": [ + "zod@3.23.3" + ] + }, + "zod-validation-error@3.4.0_zod@3.23.8": { + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dependencies": [ + "zod@3.23.8" + ] + }, + "zod@3.23.3": { + "integrity": "sha512-tPvq1B/2Yu/dh2uAIH2/BhUlUeLIUvAjr6dpL/75I0pCYefHgjhXk1o1Kob3kTU8C7yU1j396jFHlsVWFi9ogg==" + }, + "zod@3.23.8": { + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" } }, "remote": { diff --git a/deps/common.ts b/deps/common.ts index d81d085..8843e4b 100644 --- a/deps/common.ts +++ b/deps/common.ts @@ -10,7 +10,7 @@ export * as std_fmt_colors from "https://deno.land/std@0.213.0/fmt/colors.ts"; export * as std_url from "https://deno.land/std@0.213.0/url/mod.ts"; export * as std_path from "https://deno.land/std@0.213.0/path/mod.ts"; export * as std_fs from "https://deno.land/std@0.213.0/fs/mod.ts"; -export * as zod_val_err from "npm:zod-validation-error@3.3.0"; +export * as zod_val_err from "npm:zod-validation-error@3.4.0"; // avoid using the following directly and go through the // wrappers in ./utils/mod.ts diff --git a/files/deno/mod2.ts b/files/deno/bindings.ts similarity index 95% rename from files/deno/mod2.ts rename to files/deno/bindings.ts index ccb1da5..8bf47f1 100644 --- a/files/deno/mod2.ts +++ b/files/deno/bindings.ts @@ -9,6 +9,7 @@ // NOTE: only import types import { shimDenoNamespace } from "../../utils/worker.ts"; import { zod } from "../../deps/common.ts"; +import { Ghjk } from "../../src/ghjk/js/runtime.js"; const serializeArgs = zod.object({ uri: zod.string(), diff --git a/ghjk.ts b/ghjk.ts index 9cf3a48..3b0c45f 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -14,6 +14,10 @@ config({ allowedBuildDeps: [ports.cpy_bs({ version: "3.12.7" })], }); +env("main").vars({ + RUST_LOG: "trace,deno=info,denort=trace,swc_ecma_transforms_base=info", +}); + env("_rust") .install( ports.protoc(), diff --git a/host/mod.ts b/host/mod.ts index 811ed0d..651a9b8 100644 --- a/host/mod.ts +++ b/host/mod.ts @@ -268,9 +268,8 @@ async function commandsFromConfig(hcx: HostCtx, gcx: GhjkCtx) { `no lock entry found for module specified by lockfile config: ${man.id}`, ); } - const instance: ModuleBase = new mod.ctor(); + const instance: ModuleBase = new mod.ctor(gcx); lockEntries[man.id] = await instance.loadLockEntry( - gcx, entry as Json, ); } @@ -313,22 +312,21 @@ async function commandsFromConfig(hcx: HostCtx, gcx: GhjkCtx) { }; // command name to [cmd, source module id] const subCommands = {} as Record; - const instances = [] as [string, ModuleBase, unknown][]; + const instances = [] as [string, ModuleBase][]; for (const man of configExt.config.modules) { const mod = std_modules.map[man.id]; if (!mod) { throw new Error(`unrecognized module specified by ghjk.ts: ${man.id}`); } - const instance: ModuleBase = new mod.ctor(); - const pMan = await instance.processManifest( - gcx, + const instance: ModuleBase = new mod.ctor(gcx); + await instance.loadConfig( man, configExt.config.blackboard, lockEntries[man.id], ); - instances.push([man.id, instance, pMan] as const); - for (const [cmdName, cmd] of Object.entries(instance.commands(gcx, pMan))) { + instances.push([man.id, instance] as const); + for (const [cmdName, cmd] of Object.entries(instance.commands())) { const conflict = subCommands[cmdName]; if (conflict) { throw new Error( @@ -368,8 +366,8 @@ async function commandsFromConfig(hcx: HostCtx, gcx: GhjkCtx) { await Array.fromAsync( instances.map( async ( - [id, instance, pMan], - ) => [id, await instance.genLockEntry(gcx, pMan)], + [id, instance], + ) => [id, await instance.genLockEntry()], ), ), ); diff --git a/modules/envs/mod.ts b/modules/envs/mod.ts index 516173b..d15d706 100644 --- a/modules/envs/mod.ts +++ b/modules/envs/mod.ts @@ -33,9 +33,8 @@ const lockValidator = zod.object({ type EnvsLockEnt = zod.infer; -export class EnvsModule extends ModuleBase { - processManifest( - gcx: GhjkCtx, +export class EnvsModule extends ModuleBase { + loadConfig( manifest: ModuleManifest, _bb: Blackboard, _lockEnt: EnvsLockEnt | undefined, @@ -52,20 +51,18 @@ export class EnvsModule extends ModuleBase { const setEnv = Deno.env.get("GHJK_ENV"); const activeEnv = setEnv && setEnv != "" ? setEnv : config.defaultEnv; - const envsCtx = getEnvsCtx(gcx); - envsCtx.activeEnv = activeEnv; - envsCtx.config = config; + const ecx = getEnvsCtx(this.gcx); + ecx.activeEnv = activeEnv; + ecx.config = config; for (const [name, key] of Object.entries(config.envsNamed)) { - envsCtx.keyToName[key] = [name, ...(envsCtx.keyToName[key] ?? [])]; + ecx.keyToName[key] = [name, ...(ecx.keyToName[key] ?? [])]; } - - return Promise.resolve(envsCtx); } - commands( - gcx: GhjkCtx, - ecx: EnvsCtx, - ) { + commands() { + const gcx = this.gcx; + const ecx = getEnvsCtx(this.gcx); + function envKeyArgs( args: { taskKeyMaybe?: string; @@ -215,10 +212,7 @@ Cooks and activates an environment. }; } - loadLockEntry( - _gcx: GhjkCtx, - raw: Json, - ) { + loadLockEntry(raw: Json) { const entry = lockValidator.parse(raw); if (entry.version != "0") { @@ -227,10 +221,7 @@ Cooks and activates an environment. return entry; } - genLockEntry( - _gcx: GhjkCtx, - _tcx: EnvsCtx, - ) { + genLockEntry() { return { version: "0", }; diff --git a/modules/mod.ts b/modules/mod.ts index daa35fa..9ec8165 100644 --- a/modules/mod.ts +++ b/modules/mod.ts @@ -3,27 +3,20 @@ import { Blackboard } from "../host/types.ts"; import type { Json } from "../utils/mod.ts"; import type { GhjkCtx, ModuleManifest } from "./types.ts"; -export abstract class ModuleBase { +export abstract class ModuleBase { + constructor(protected gcx: GhjkCtx) {} /* init( _gcx: GhjkCtx, ): Promise | void {} */ - abstract processManifest( - gcx: GhjkCtx, + abstract loadConfig( manifest: ModuleManifest, bb: Blackboard, lockEnt: LockEnt | undefined, - ): Promise | Ctx; + ): Promise | void; // returns undefined if previous lock entry is no longer valid abstract loadLockEntry( - gcx: GhjkCtx, raw: Json, ): Promise | LockEnt | undefined; - abstract genLockEntry( - gcx: GhjkCtx, - mcx: Ctx, - ): Promise | Json; - abstract commands( - gcx: GhjkCtx, - mcx: Ctx, - ): Record>; + abstract genLockEntry(): Promise | Json; + abstract commands(): Record>; } diff --git a/modules/ports/mod.ts b/modules/ports/mod.ts index 1dcad40..9211346 100644 --- a/modules/ports/mod.ts +++ b/modules/ports/mod.ts @@ -49,9 +49,8 @@ const lockValidator = zod.object({ }); type PortsLockEnt = zod.infer; -export class PortsModule extends ModuleBase { - processManifest( - gcx: GhjkCtx, +export class PortsModule extends ModuleBase { + loadConfig( manifest: ModuleManifest, bb: Blackboard, _lockEnt: PortsLockEnt | undefined, @@ -67,7 +66,8 @@ export class PortsModule extends ModuleBase { validators.portsModuleConfigHashed.safeParse(manifest.config), ); - const pcx: PortsCtx = getPortsCtx(gcx); + const gcx = this.gcx; + const pcx = getPortsCtx(gcx); // pre-process the install sets found in the config for (const [id, hashedSet] of Object.entries(hashedModConf.sets)) { @@ -108,13 +108,12 @@ export class PortsModule extends ModuleBase { installSetProvisionTy, installSetReducer(gcx) as ProvisionReducer, ); - return pcx; } - commands( - gcx: GhjkCtx, - pcx: PortsCtx, - ) { + commands() { + const gcx = this.gcx; + const pcx = getPortsCtx(gcx); + return { ports: new cliffy_cmd.Command() .alias("p") @@ -268,16 +267,13 @@ export class PortsModule extends ModuleBase { ), }; } - loadLockEntry( - gcx: GhjkCtx, - raw: Json, - ) { + loadLockEntry(raw: Json) { const entry = lockValidator.parse(raw); if (entry.version != "0") { throw new Error(`unexepected version tag deserializing lockEntry`); } - const memoStore = getResolutionMemo(gcx); + const memoStore = getResolutionMemo(this.gcx); for (const [hash, config] of Object.entries(entry.configResolutions)) { logger().debug( "restoring resolution from lockfile", @@ -290,11 +286,8 @@ export class PortsModule extends ModuleBase { return entry; } - async genLockEntry( - gcx: GhjkCtx, - _pcx: PortsCtx, - ) { - const memo = getResolutionMemo(gcx); + async genLockEntry() { + const memo = getResolutionMemo(this.gcx); const configResolutions = Object.fromEntries( await Array.fromAsync( [...memo.entries()].map(async ([key, prom]) => [key, await prom]), diff --git a/modules/tasks/mod.ts b/modules/tasks/mod.ts index 222bda7..7bdb2a2 100644 --- a/modules/tasks/mod.ts +++ b/modules/tasks/mod.ts @@ -5,7 +5,7 @@ import { Json, unwrapZodRes } from "../../utils/mod.ts"; import validators from "./types.ts"; import type { TasksModuleConfigX } from "./types.ts"; -import { type GhjkCtx, type ModuleManifest } from "../types.ts"; +import { type ModuleManifest } from "../types.ts"; import { ModuleBase } from "../mod.ts"; import { buildTaskGraph, execTask, type TaskGraph } from "./exec.ts"; @@ -21,9 +21,8 @@ const lockValidator = zod.object({ }); type TasksLockEnt = zod.infer; -export class TasksModule extends ModuleBase { - processManifest( - gcx: GhjkCtx, +export class TasksModule extends ModuleBase { + loadConfig( manifest: ModuleManifest, bb: Blackboard, _lockEnt: TasksLockEnt | undefined, @@ -40,19 +39,17 @@ export class TasksModule extends ModuleBase { validators.tasksModuleConfig.safeParse(manifest.config), ); - const taskGraph = buildTaskGraph(gcx, config); + const taskGraph = buildTaskGraph(this.gcx, config); - const tasksCtx = getTasksCtx(gcx); - tasksCtx.config = config; - tasksCtx.taskGraph = taskGraph; - - return tasksCtx; + const tcx = getTasksCtx(this.gcx); + tcx.config = config; + tcx.taskGraph = taskGraph; } - commands( - gcx: GhjkCtx, - tcx: TasksCtx, - ) { + commands() { + const gcx = this.gcx; + const tcx = getTasksCtx(this.gcx); + const namedSet = new Set(tcx.config.tasksNamed); const commands = Object.keys(tcx.config.tasks) .sort() @@ -96,10 +93,7 @@ The named tasks in your ghjkfile will be listed here.`); }; } - loadLockEntry( - _gcx: GhjkCtx, - raw: Json, - ) { + loadLockEntry(raw: Json) { const entry = lockValidator.parse(raw); if (entry.version != "0") { @@ -108,10 +102,7 @@ The named tasks in your ghjkfile will be listed here.`); return entry; } - genLockEntry( - _gcx: GhjkCtx, - _tcx: TasksCtx, - ) { + genLockEntry() { return { version: "0", }; diff --git a/src/deno_systems/bindings.ts b/src/deno_systems/bindings.ts new file mode 100644 index 0000000..bbfd0e3 --- /dev/null +++ b/src/deno_systems/bindings.ts @@ -0,0 +1,126 @@ +// import "../../src/ghjk/js/mock.sfx.ts"; +import { zod } from "../../deps/common.ts"; +import { $, Json, unwrapZodRes } from "../../utils/mod.ts"; +import type { GhjkCtx, ModuleManifest } from "../../modules/types.ts"; +import type { ModuleBase } from "../../modules/mod.ts"; +import type { Blackboard } from "../../host/types.ts"; +import { Ghjk } from "../ghjk/js/runtime.js"; + +const prepareArgs = zod.object({ + uri: zod.string(), + gcx: zod.object({ + ghjkfile_path: zod.string().optional(), + ghjk_dir_path: zod.string(), + share_dir_path: zod.string(), + }), +}); + +const denoSystemsRoot = zod.object({ + systems: zod.record(zod.function()), +}); + +type DenoSystemCtor = (gcx: GhjkCtx) => ModuleBase; + +export type DenoSystemsRoot = { + systems: Record; +}; + +type ManifestDesc = { + id: string; + ctor_cb_key: string; +}; +type InstanceDesc = { + load_lock_entry_cb_key: string; + gen_lock_entry_cb_key: string; + load_config_cb_key: string; +}; + +async function prepareSystems(args: zod.infer) { + const gcx = { + ghjkDir: $.path(args.gcx.ghjk_dir_path), + ghjkShareDir: $.path(args.gcx.share_dir_path), + ghjkfilePath: args.gcx.ghjkfile_path + ? $.path(args.gcx.ghjkfile_path) + : undefined, + blackboard: new Map(), + } satisfies GhjkCtx; + + const { default: mod } = await import(args.uri); + const { systems } = unwrapZodRes( + denoSystemsRoot.safeParse(mod), + ) as DenoSystemsRoot; + + const manifests = [] as ManifestDesc[]; + + for (const [id, ctorFn] of Object.entries(systems)) { + manifests.push({ + id, + ctor_cb_key: Ghjk.callbacks.set( + `sys_ctor_${id}_${crypto.randomUUID()}`, + () => { + const instance = ctorFn(gcx); + return instanceBinding(gcx, id, instance); + }, + ), + }); + } + await Ghjk.hostcall("register_systems", manifests); +} + +function instanceBinding( + gcx: GhjkCtx, + sys_id: string, + instance: ModuleBase, +) { + const instanceId = crypto.randomUUID(); + type State = { + stateKey: string; + }; + return { + load_config_cb_key: Ghjk.callbacks.set( + `sys_load_config_${instanceId}`, + async (args: Json) => { + const { config, bb, state: stateRaw } = args as { + config: ModuleManifest; + bb: Blackboard; + state?: State; + }; + const state = stateRaw?.stateKey + ? gcx.blackboard.get(stateRaw?.stateKey) + : undefined; + await instance.loadConfig({ id: sys_id, config }, bb, state); + return null; + }, + ), + load_lock_entry_cb_key: Ghjk.callbacks.set( + `sys_load_lock_entry_${instanceId}`, + async (args: Json) => { + const { raw } = args as any; + const state = await instance.loadLockEntry(raw); + const stateKey = `sys_state_${instanceId}`; + gcx.blackboard.set(stateKey, state); + return { + stateKey, + } satisfies State; + }, + ), + gen_lock_entry_cb_key: Ghjk.callbacks.set( + `sys_gen_lock_entry_${instanceId}`, + () => { + return instance.genLockEntry(); + }, + ), + } satisfies InstanceDesc; +} + +// start an interval to prevent the event loop exiting +// after loading systems +setInterval(() => {/* beat */}, 1000); +// FIXME: better means of exit detection, keep alive as long +// as callbacks are registered? +// globalThis.onbeforeunload = (evt) => { +// evt.preventDefault(); +// }; + +const args = prepareArgs.parse(Ghjk.blackboard.get("args")); +await prepareSystems(args); diff --git a/src/deno_systems/mod.ts b/src/deno_systems/mod.ts new file mode 100644 index 0000000..ddfcea4 --- /dev/null +++ b/src/deno_systems/mod.ts @@ -0,0 +1,10 @@ +import { map } from "../../modules/std.ts"; +import type { DenoSystemsRoot } from "./bindings.ts"; + +export default { + systems: Object.fromEntries( + Object.entries(map).map( + ([id, sys]) => [id, (gcx) => new sys.ctor(gcx)], + ), + ), +} satisfies DenoSystemsRoot; diff --git a/src/denort/lib.rs b/src/denort/lib.rs index 4769097..e7ab513 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -1,7 +1,9 @@ -#![allow(dead_code, clippy::let_and_return)] +#![allow(clippy::let_and_return)] pub use deno; +pub mod promises; + #[allow(unused)] mod interlude { pub use std::future::Future; @@ -9,11 +11,16 @@ mod interlude { pub use std::sync::Arc; pub use color_eyre::eyre; + pub use deno::deno_runtime::{ + self, + deno_core::{self, v8}, + }; pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; - pub use tracing::{debug, error, info, trace, warn}; + pub use tracing::{debug, error, info, trace, warn, Instrument}; pub use tracing_unwrap::*; } use crate::interlude::*; + use deno::{ deno_runtime::{ deno_core::{futures::FutureExt, unsync::JoinHandle, ModuleSpecifier}, @@ -22,6 +29,7 @@ use deno::{ }, *, }; +use std::sync::atomic::AtomicBool; #[rustfmt::skip] use deno_runtime::deno_core as deno_core; // necessary for re-exported macros to work @@ -42,6 +50,9 @@ pub fn init() { }; } +// thread tag used for basic sanity checks +pub const WORKER_THREAD_NAME: &str = "denort-worker-thread"; + /// This starts a new thread and uses it to run all the tasks /// that'll need to touch deno internals. Deno is single threaded. /// @@ -52,79 +63,112 @@ pub async fn worker( ) -> Res { let cx = WorkerContext::from_config(flags, custom_extensions_cb).await?; - let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); + let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); let rt = tokio::runtime::Handle::current(); + let term_signal = AtomicBool::new(false); + let term_signal = Arc::new(term_signal); + + let global_term_signal = term_signal.clone(); let join_handle = new_thread_builder() + .name(WORKER_THREAD_NAME.into()) .spawn(move || { let local = tokio::task::LocalSet::new(); - local.spawn_local(async move { - while let Some(req) = rx.recv().await { - match req { - DenoWorkerReq::PrepareModule { - response_channel, - main_module, - permissions, - mode, - stdio, - custom_extensions_cb, - } => { - let mut module_cx = match cx - .prepare_module( - main_module, - &permissions, - mode, - stdio, - custom_extensions_cb, - ) - .await - { - Ok(val) => val, - Err(err) => { - response_channel - .send(Err(err)) - .expect_or_log("channel error"); - continue; - } - }; - - let (module_tx, mut module_rx) = - tokio::sync::mpsc::unbounded_channel::(); - tokio::task::spawn_local(async move { - while let Some(req) = module_rx.recv().await { - match req { - ModuleWorkerReq::Run { response_channel } => { - response_channel - .send(module_cx.run().await) - .expect_or_log("channel error") - } - ModuleWorkerReq::GetLoadedModules { response_channel } => { - response_channel - .send(module_cx.get_loaded_modules()) - .expect_or_log("channel error") - } - } - } - }); - - response_channel - .send(Ok(ModuleWorkerHandle { sender: module_tx })) - .expect_or_log("channel error"); + local.spawn_local( + async move { + debug!("starting deno worker"); + while let Some(msg) = rx.recv().await { + debug!(?msg, "deno worker msg"); + match msg { + DenoWorkerMsg::PrepareModule { + response_channel, + inner, + } => { + response_channel + .send( + module_worker(&cx, global_term_signal.clone(), inner).await, + ) + .expect_or_log("channel error"); + } } } + debug!("deno worker done"); } - }); + .instrument(tracing::debug_span!("deno-worker")), + ); rt.block_on(local); }) .unwrap(); - let join_handle = Arc::new(join_handle); + let join_handle = Arc::new(std::sync::Mutex::new(Some(join_handle))); Ok(DenoWorkerHandle { sender: tx, + term_signal, join_handle, }) } +async fn module_worker( + cx: &WorkerContext, + global_term_signal: Arc, + msg: PrepareModuleMsg, +) -> Res { + let mut module_cx = cx + .prepare_module( + msg.main_module, + &msg.permissions, + msg.mode, + msg.stdio, + msg.custom_extensions_cb, + ) + .await?; + + let (module_tx, mut module_rx) = tokio::sync::mpsc::channel::(1); + tokio::task::spawn_local( + async move { + debug!("starting module worker"); + while let Some(msg) = module_rx.recv().await { + debug!(?msg, "module worker msg"); + match msg { + ModuleWorkerReq::Run { response_channel } => response_channel + .send( + module_cx + .run(&global_term_signal) + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::DriveTillExit { + term_signal, + response_channel, + } => response_channel + .send( + module_cx + .drive_till_exit(&global_term_signal, &term_signal) + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::Execute { response_channel } => response_channel + .send( + module_cx + .execute_main_module() + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::GetLoadedModules { response_channel } => response_channel + .send(module_cx.get_loaded_modules()) + .expect_or_log("channel error"), + } + } + debug!("module worker done"); + } + .instrument(tracing::debug_span!("deno-module-worker")), + ); + Ok(ModuleWorkerHandle { sender: module_tx }) +} + #[derive(educe::Educe)] #[educe(Debug)] struct WorkerContext { @@ -187,7 +231,7 @@ impl WorkerContext { let permissions = deno_permissions::Permissions::from_options(desc_parser.as_ref(), permissions)?; let permissions = deno_permissions::PermissionsContainer::new(desc_parser, permissions); - let worker = self + let mut worker = self .worker_factory .create_custom_worker( mode, @@ -198,30 +242,72 @@ impl WorkerContext { ) .await .map_err(|err| ferr!(Box::new(err)))?; + let maybe_coverage_collector = worker + .maybe_setup_coverage_collector() + .await + .map_err(|err| ferr!(Box::new(err)))?; + + // TODO: hot module support, expose shared worker contet from deno/cli/worker + // let maybe_hmr_runner = worker + // .maybe_setup_hmr_runner() + // .await + // .map_err(|err| ferr!(Box::new(err)))?; + + let worker = worker.into_main_worker(); Ok(ModuleWorkerContext { main_module, worker, graph: self.graph.clone(), + maybe_coverage_collector, + // maybe_hmr_runner, }) } } -enum DenoWorkerReq { +#[derive(educe::Educe)] +#[educe(Debug)] +struct PrepareModuleMsg { + main_module: ModuleSpecifier, + permissions: deno_permissions::PermissionsOptions, + #[educe(Debug(ignore))] + mode: deno_runtime::WorkerExecutionMode, + #[educe(Debug(ignore))] + stdio: deno_runtime::deno_io::Stdio, + #[educe(Debug(ignore))] + custom_extensions_cb: Option>, +} + +#[derive(educe::Educe)] +#[educe(Debug)] +enum DenoWorkerMsg { PrepareModule { + #[educe(Debug(ignore))] response_channel: tokio::sync::oneshot::Sender>, - main_module: ModuleSpecifier, - permissions: deno_permissions::PermissionsOptions, - mode: deno_runtime::WorkerExecutionMode, - stdio: deno_runtime::deno_io::Stdio, - custom_extensions_cb: Option>, + inner: PrepareModuleMsg, }, } #[derive(Clone, Debug)] pub struct DenoWorkerHandle { - sender: tokio::sync::mpsc::UnboundedSender, - join_handle: Arc>, + sender: tokio::sync::mpsc::UnboundedSender, + join_handle: Arc>>>, + term_signal: Arc, +} + +impl DenoWorkerHandle { + pub fn terminate(self) { + self.term_signal + .store(true, std::sync::atomic::Ordering::Relaxed); + let join_handle = { + let mut opt = self.join_handle.lock().expect_or_log("mutex error"); + opt.take() + }; + let Some(join_handle) = join_handle else { + return; + }; + join_handle.join().expect_or_log("join error") + } } impl DenoWorkerHandle { @@ -235,13 +321,15 @@ impl DenoWorkerHandle { ) -> Res { let (tx, rx) = tokio::sync::oneshot::channel(); self.sender - .send(DenoWorkerReq::PrepareModule { + .send(DenoWorkerMsg::PrepareModule { response_channel: tx, - main_module, - permissions, - mode, - stdio, - custom_extensions_cb, + inner: PrepareModuleMsg { + main_module, + permissions, + mode, + stdio, + custom_extensions_cb, + }, }) .expect_or_log("channel error"); rx.await.expect_or_log("channel error") @@ -253,9 +341,12 @@ impl DenoWorkerHandle { struct ModuleWorkerContext { main_module: deno_core::ModuleSpecifier, #[educe(Debug(ignore))] - worker: deno::worker::CliMainWorker, + worker: deno_runtime::worker::MainWorker, #[educe(Debug(ignore))] graph: Arc, + #[educe(Debug(ignore))] + maybe_coverage_collector: Option>, + // maybe_hmr_runner: Option>, } impl ModuleWorkerContext { @@ -276,43 +367,205 @@ impl ModuleWorkerContext { .collect() } - async fn run(&mut self) -> Res { - self.worker.run().await.map_err(|err| ferr!(Box::new(err))) + async fn run(&mut self, global_term_signal: &AtomicBool) -> anyhow::Result { + debug!("main_module {}", self.main_module); + self.execute_main_module().await?; + self.drive_till_exit(global_term_signal, &AtomicBool::new(false)) + .await + } + + async fn drive_till_exit( + &mut self, + global_term_signal: &AtomicBool, + term_signal: &AtomicBool, + ) -> anyhow::Result { + self.worker.dispatch_load_event()?; + loop { + /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { + let watcher_communicator = + self.shared.maybe_file_watcher_communicator.clone().unwrap(); + + let hmr_future = hmr_runner.run().boxed_local(); + let event_loop_future = self.worker.run_event_loop(false).boxed_local(); + + let result; + tokio::select! { + hmr_result = hmr_future => { + result = hmr_result; + }, + event_loop_result = event_loop_future => { + result = event_loop_result; + } + } + if let Err(e) = result { + watcher_communicator.change_restart_mode(WatcherRestartMode::Automatic); + return Err(e); + } + } else { + self.worker + .run_event_loop(self.maybe_coverage_collector.is_none()) + .await?; + } */ + self.worker + .run_event_loop(self.maybe_coverage_collector.is_none()) + .await?; + + if term_signal.load(std::sync::atomic::Ordering::Relaxed) { + trace!("worker term signal lit, shutting down event loop"); + break; + } + + if global_term_signal.load(std::sync::atomic::Ordering::Relaxed) { + trace!("globalterm signal lit, shutting down event loop"); + break; + } + + let web_continue = self.worker.dispatch_beforeunload_event()?; + if !web_continue { + let node_continue = self.worker.dispatch_process_beforeexit_event()?; + if !node_continue { + trace!("beforeunload and beforeexit success, shutting down loop"); + break; + } + } + } + self.worker.dispatch_unload_event()?; + self.worker.dispatch_process_exit_event()?; + if let Some(coverage_collector) = self.maybe_coverage_collector.as_mut() { + self.worker + .js_runtime + .with_event_loop_future( + coverage_collector.stop_collecting().boxed_local(), + deno_core::PollEventLoopOptions::default(), + ) + .await?; + } + /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { + self.worker + .js_runtime + .with_event_loop_future( + hmr_runner.stop().boxed_local(), + deno_core::PollEventLoopOptions::default(), + ) + .await?; + } */ + Ok(self.worker.exit_code()) + //.map_err(|err| ferr!(Box::new(err))) + } + + async fn execute_main_module(&mut self) -> anyhow::Result<()> { + let id = self.worker.preload_main_module(&self.main_module).await?; + self.worker.evaluate_module(id).await } } +#[derive(educe::Educe)] +#[educe(Debug)] enum ModuleWorkerReq { Run { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, + DriveTillExit { + #[educe(Debug(ignore))] + term_signal: Arc, + #[educe(Debug(ignore))] response_channel: tokio::sync::oneshot::Sender>, }, + Execute { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, GetLoadedModules { + #[educe(Debug(ignore))] response_channel: tokio::sync::oneshot::Sender>, }, } #[derive(Clone, Debug)] pub struct ModuleWorkerHandle { - sender: tokio::sync::mpsc::UnboundedSender, + sender: tokio::sync::mpsc::Sender, +} + +#[derive(Clone, Debug)] +pub struct FinishedWorkerHandle { + sender: tokio::sync::mpsc::Sender, } + impl ModuleWorkerHandle { - pub async fn get_loaded_modules(&mut self) -> Vec { + /// Load and execute the main module + /// and drive the main loop until the program + /// exits. + pub async fn run(self) -> Res<(i32, FinishedWorkerHandle)> { let (tx, rx) = tokio::sync::oneshot::channel(); self.sender - .send(ModuleWorkerReq::GetLoadedModules { + .send(ModuleWorkerReq::Run { response_channel: tx, }) + .await + .expect_or_log("channel error"); + Ok(( + rx.await.expect_or_log("channel error")?, + FinishedWorkerHandle { + sender: self.sender, + }, + )) + } + + /// Load and execute the main module + /// but doesn't progress the main event + /// loop. + pub async fn execute(&mut self) -> Res<()> { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::Execute { + response_channel: tx, + }) + .await .expect_or_log("channel error"); - // FIXME: can use sync oneshot here rx.await.expect_or_log("channel error") } - pub async fn run(&mut self) -> Res { + /// Drive the event loop until exit and return + /// result in returned channel. + /// Expects that [`execute`] was called first on the worker. + pub async fn drive_till_exit( + self, + ) -> Res<( + tokio::sync::oneshot::Receiver>, + Arc, + FinishedWorkerHandle, + )> { + let term_signal = AtomicBool::new(false); + let term_signal = Arc::new(term_signal); let (tx, rx) = tokio::sync::oneshot::channel(); self.sender - .send(ModuleWorkerReq::Run { + .send(ModuleWorkerReq::DriveTillExit { + term_signal: term_signal.clone(), + response_channel: tx, + }) + .await + .expect_or_log("channel error"); + Ok(( + rx, + term_signal, + FinishedWorkerHandle { + sender: self.sender, + }, + )) + } +} + +impl FinishedWorkerHandle { + pub async fn get_loaded_modules(&mut self) -> Vec { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::GetLoadedModules { response_channel: tx, }) + .await .expect_or_log("channel error"); + // FIXME: can use sync oneshot here? rx.await.expect_or_log("channel error") } } diff --git a/src/denort/promises.rs b/src/denort/promises.rs new file mode 100644 index 0000000..7692575 --- /dev/null +++ b/src/denort/promises.rs @@ -0,0 +1,70 @@ +use crate::interlude::*; + +// Lifted from deno_core 0.318.0 +/* +MIT License + +Copyright 2018-2024 the Deno authors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +/// Wrap a promise with `then` handlers allowing us to watch the resolution progress from a Rust closure. +/// This has a side-effect of preventing unhandled rejection handlers from triggering. If that is +/// desired, the final handler may choose to rethrow the exception. +pub fn watch_promise<'s, F>( + scope: &mut v8::HandleScope<'s>, + promise: v8::Local<'s, v8::Promise>, + f: F, +) -> Option> +where + F: FnOnce( + &mut v8::HandleScope, + v8::ReturnValue, + Result, v8::Local>, + ) + 'static, +{ + let external = v8::External::new(scope, Box::into_raw(Box::new(Some(f))) as _); + + fn get_handler(external: v8::Local) -> F { + unsafe { Box::>::from_raw(external.value() as _) } + .take() + .unwrap() + } + let on_fulfilled = v8::Function::builder( + |scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, rv: v8::ReturnValue| { + let data = v8::Local::::try_from(args.data()).unwrap(); + let f = get_handler::(data); + f(scope, rv, Ok(args.get(0))); + }, + ) + .data(external.into()) + .build(scope); + let on_rejected = v8::Function::builder( + |scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, rv: v8::ReturnValue| { + let data = v8::Local::::try_from(args.data()).unwrap(); + let f = get_handler::(data); + f(scope, rv, Err(args.get(0))); + }, + ) + .data(external.into()) + .build(scope); + // function builders will return None if the runtime is shutting down + let (Some(on_fulfilled), Some(on_rejected)) = (on_fulfilled, on_rejected) else { + _ = get_handler::(external); + return None; + }; + + // then2 will return None if the runtime is shutting down + let Some(promise) = promise.then2(scope, on_fulfilled, on_rejected) else { + _ = get_handler::(external); + return None; + }; + + Some(promise) +} diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index 89bb4b7..5335c17 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -39,6 +39,8 @@ tracing-error = "0.2" tracing-unwrap.workspace = true color-eyre.workspace = true +anyhow.workspace = true + tracing.workspace = true tracing-subscriber.workspace = true tracing-appender = "0.2" @@ -61,6 +63,7 @@ data-encoding = "2.6.0" sha2 = "0.10.8" pathdiff = "0.2.2" directories = "5.0.1" +async-trait = "0.1.83" [build-dependencies] shadow-rs.workspace = true diff --git a/src/ghjk/deno.rs b/src/ghjk/deno.rs deleted file mode 100644 index c8506f4..0000000 --- a/src/ghjk/deno.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::interlude::*; - -#[rustfmt::skip] -use deno_core as deno_core; // necessary for re-exported macros to work - -pub fn extensions(config: ExtConfig) -> Arc { - // let atom = std::sync::atomic::AtomicBool::new(false); - Arc::new(move || { - // if atom.load(std::sync::atomic::Ordering::SeqCst) { - // return vec![]; - // } - // atom.store(true, std::sync::atomic::Ordering::SeqCst); - vec![ghjk_deno_ext::init_ops_and_esm(config.clone())] - }) -} - -// This is used to populate the deno_core::OpState with dependencies -// used by the different ops -#[derive(Clone)] -pub struct ExtConfig { - pub blackboard: Arc>, -} - -impl ExtConfig { - pub fn new(blackboard: Arc>) -> Self { - Self { blackboard } - } - - fn inject(self, state: &mut deno_core::OpState) { - state.put(ExtContext { - blackboard: self.blackboard.clone(), - }); - } -} - -deno_core::extension!( - ghjk_deno_ext, - ops = [op_get_blackboard, op_set_blackboard], - options = { config: ExtConfig }, - state = |state, opt| { - opt.config.inject(state); - }, - customizer = |ext: &mut deno_core::Extension| { - customizer(ext); - }, - docs = "Kitchen sink extension for all ghjk needs.", -); - -fn customizer(ext: &mut deno_core::Extension) { - ext.esm_files - .to_mut() - .push(deno_core::ExtensionFileSource::new( - "ext:ghjk_deno_ext/00_runtime.js", - deno_core::ascii_str_include!("deno/00_runtime.js"), - )); - ext.esm_entry_point = Some("ext:ghjk_deno_ext/00_runtime.js"); -} - -struct ExtContext { - blackboard: Arc>, -} - -#[deno_core::op2] -#[serde] -pub fn op_get_blackboard( - #[state] ctx: &ExtContext, - #[string] key: &str, -) -> Option { - ctx.blackboard.get(key).map(|val| val.clone()) -} - -#[deno_core::op2] -#[serde] -pub fn op_set_blackboard( - #[state] ctx: &ExtContext, - #[string] key: String, - #[serde] val: serde_json::Value, -) -> Option { - ctx.blackboard - .insert(key.into(), val) - .map(|val| val.clone()) -} diff --git a/src/ghjk/ext.rs b/src/ghjk/ext.rs new file mode 100644 index 0000000..c515700 --- /dev/null +++ b/src/ghjk/ext.rs @@ -0,0 +1,125 @@ +use std::{cell::RefCell, rc::Rc}; + +use crate::interlude::*; + +use deno_core::OpState; +#[rustfmt::skip] +use deno_core as deno_core; // necessary for re-exported macros to work + +mod callbacks; +pub use callbacks::CallbacksHandle; + +/// This extension assumes that deno was launched on top of a tokio::LocalSet +pub fn extensions(config: ExtConfig) -> Arc { + // let atom = std::sync::atomic::AtomicBool::new(false); + Arc::new(move || { + // if atom.load(std::sync::atomic::Ordering::SeqCst) { + // return vec![]; + // } + // atom.store(true, std::sync::atomic::Ordering::SeqCst); + vec![ghjk_deno_ext::init_ops_and_esm(config.clone())] + }) +} +// This is used to populate the deno_core::OpState with dependencies +// used by the different ops +#[derive(Clone, Default)] +pub struct ExtConfig { + pub blackboard: Arc>, + callbacks_rx: Arc>, + pub hostcalls: Hostcalls, +} + +impl ExtConfig { + pub fn new() -> Self { + Self::default() + } + + pub fn callbacks_handle(&mut self) -> callbacks::CallbacksHandle { + let (line, handle) = callbacks::CallbackLine::new(); + self.callbacks_rx = Arc::new(std::sync::Mutex::new(line)); + + handle + } + + fn inject(self, state: &mut deno_core::OpState) { + let ctx = ExtContext { + config: self, + callbacks: default(), + }; + callbacks::worker(ctx.clone()); + state.put(ctx); + } +} + +deno_core::extension!( + ghjk_deno_ext, + ops = [op_blackboard_get, op_blackboard_set, callbacks::op_callbacks_set, op_hostcall], + options = { config: ExtConfig }, + state = |state, opt| { + opt.config.inject(state); + }, + customizer = customizer, + docs = "Kitchen sink extension for all ghjk needs.", +); + +fn customizer(ext: &mut deno_core::Extension) { + ext.esm_files + .to_mut() + .push(deno_core::ExtensionFileSource::new( + "ext:ghjk_deno_ext/00_runtime.js", + deno_core::ascii_str_include!("js/00_runtime.js"), + )); + ext.esm_entry_point = Some("ext:ghjk_deno_ext/00_runtime.js"); +} + +#[derive(Clone)] +struct ExtContext { + callbacks: callbacks::Callbacks, + config: ExtConfig, +} + +#[deno_core::op2] +#[serde] +pub fn op_blackboard_get( + #[state] ctx: &ExtContext, + #[string] key: &str, +) -> Option { + ctx.config.blackboard.get(key).map(|val| val.clone()) +} + +#[deno_core::op2] +#[serde] +pub fn op_blackboard_set( + #[state] ctx: &ExtContext, + #[string] key: String, + #[serde] val: serde_json::Value, +) -> Option { + ctx.config.blackboard.insert(key.into(), val) +} + +#[derive(Clone, Default)] +pub struct Hostcalls { + pub funcs: Arc>, +} + +pub type HostcallFn = Box< + dyn Fn(serde_json::Value) -> BoxFuture<'static, Res> + 'static + Send + Sync, +>; + +#[deno_core::op2(async)] +#[serde] +pub async fn op_hostcall( + state: Rc>, + #[string] name: String, + #[serde] args: serde_json::Value, +) -> anyhow::Result { + let ctx = { + let state = state.borrow(); + let ctx = state.borrow::(); + ctx.clone() + }; + let Some(func) = ctx.config.hostcalls.funcs.get(&name[..]) else { + anyhow::bail!("no hostcall found under {name}"); + }; + func(args).await.map_err(|err| anyhow::anyhow!(err)) +} diff --git a/src/ghjk/ext/callbacks.rs b/src/ghjk/ext/callbacks.rs new file mode 100644 index 0000000..2f63aa3 --- /dev/null +++ b/src/ghjk/ext/callbacks.rs @@ -0,0 +1,293 @@ +use std::{cell::RefCell, rc::Rc}; + +use crate::interlude::*; + +use deno_core::serde_v8; +use deno_core::v8; +use deno_core::OpState; +#[rustfmt::skip] +use deno_core as deno_core; // necessary for re-exported macros to work +use tokio::sync::{mpsc, oneshot}; + +use super::ExtContext; + +#[derive(Debug, thiserror::Error)] +pub enum CallbackError { + #[error("no callback found under {key}")] + NotFound { key: String }, + #[error("callback protocol error {0:?}")] + ProtocolError(eyre::Report), + #[error("error executing callback {0:?}")] + JsError(eyre::Report), + #[error("v8 error {0:?}")] + V8Error(eyre::Report), +} + +/// Line used by the callback_worker to receive +/// invocations. +#[derive(Default)] +pub struct CallbackLine { + line: Option>, + was_set: bool, +} + +impl CallbackLine { + pub fn new() -> (Self, CallbacksHandle) { + let (tx, rx) = tokio::sync::mpsc::channel(1); + ( + Self { + was_set: true, + line: Some(rx), + }, + CallbacksHandle { sender: tx }, + ) + } + + fn take(&mut self) -> Option> { + if !self.was_set { + warn!("callback line was not set"); + return None; + } + match self.line.take() { + Some(val) => Some(val), + None => { + panic!("extensions were injected twice") + } + } + } +} + +/// Line used to invoke callbacks registered by js code. +#[derive(Clone)] +pub struct CallbacksHandle { + sender: mpsc::Sender, +} + +impl CallbacksHandle { + pub async fn exec( + &self, + key: CHeapStr, + args: serde_json::Value, + ) -> Result { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(CallbacksMsg::Exec { + response_channel: tx, + key, + args, + }) + .await + .expect_or_log("channel error"); + rx.await.expect_or_log("channel error") + } +} + +/// Internal used to communicate between callback worker +#[derive(educe::Educe)] +#[educe(Debug)] +enum CallbacksMsg { + Exec { + #[educe(Debug(ignore))] + response_channel: oneshot::Sender>, + key: CHeapStr, + #[educe(Debug(ignore))] + args: serde_json::Value, + }, +} + +#[derive(Clone, Default)] +pub struct Callbacks { + store: Arc>, +} + +/// Start a worker task to execute callbacks on. +/// +/// Stored callbacks are not Sync so this expects to be started +/// on the same thread as deno. +pub fn worker(ctx: ExtContext) { + let mut line = { + let mut line = ctx.config.callbacks_rx.lock().expect_or_log("mutex err"); + let Some(line) = line.take() else { + return; + }; + line + }; + assert_eq!( + std::thread::current().name(), + Some(denort::WORKER_THREAD_NAME), + "callback worker must be launched on deno worker started with a LocalSet" + ); + // assumes local set + tokio::task::spawn_local( + async move { + debug!("callback worker starting"); + while let Some(msg) = line.recv().await { + debug!(?msg, "callback worker msg"); + match msg { + CallbacksMsg::Exec { + key: name, + args, + response_channel, + } => response_channel + .send(ctx.exec_callback(name, args).await) + .expect_or_log("channel error"), + } + } + debug!("callback worker done"); + } + .instrument(tracing::debug_span!("callback-worker")), + ); +} + +impl ExtContext { + pub async fn exec_callback( + &self, + key: CHeapStr, + args: serde_json::Value, + ) -> Result { + let Some(cb) = self.callbacks.store.get(&key[..]).map(|cb| cb.clone()) else { + return Err(CallbackError::NotFound { + key: key.to_string(), + }); + }; + + let (tx, rx) = oneshot::channel::>(); + + // we use the sender to spawn work on the v8 thread + let join_handle = tokio::task::spawn_blocking(move || { + cb.async_work_sender.spawn_blocking(move |scope| { + let args = serde_v8::to_v8(scope, args).map_err(|err| { + CallbackError::V8Error(ferr!(err).wrap_err("error serializaing args to v8")) + })?; + + let recv = v8::undefined(scope); + + let res = { + let tc_scope = &mut v8::TryCatch::new(scope); + // FIXME(@yohe): the original pointer was made from a global + // and yet we're transmuting it to a Local here. + // This is observed from the deno codebase + // and I can't explain it + let func = unsafe { + std::mem::transmute::, v8::Local>( + cb.js_fn, + ) + }; + + let res = func + .call(tc_scope, recv.into(), &[args]) + // FIXME: under what circumstances can this be None? + .expect_or_log("got None from callback call"); + if tc_scope.has_caught() { + let exception = tc_scope.exception().unwrap(); + let exception = exception.to_rust_string_lossy(tc_scope); + /* let exception = serde_v8::from_v8(tc_scope, exception).map_err(|err| { + CallbackError::ProtocolError( + ferr!(err).wrap_err("error deserializaing exception from v8"), + ) + })?; */ + return Err(CallbackError::JsError(ferr!( + "callback exception: {exception}" + ))); + } + res + }; + if res.is_promise() { + let promise = v8::Local::::try_from(res).unwrap(); + + denort::promises::watch_promise(scope, promise, move |scope, _rf, res| { + let res = match res { + Ok(val) => serde_v8::from_v8(scope, val).map_err(|err| { + CallbackError::ProtocolError( + ferr!(err) + .wrap_err("error deserializaing promise result from v8"), + ) + }), + Err(err) => Err(CallbackError::JsError(ferr!( + "callback promise rejection: {}", + err.to_rust_string_lossy(scope) + ))), /* Err(err) => match serde_v8::from_v8(scope, err) { + Ok(json) => Err(CallbackError::JsError(json)), + Err(err) => Err(CallbackError::ProtocolError( + ferr!(err) + .wrap_err("error deserializaing promise rejection from v8"), + )), + }, */ + }; + tx.send(res).expect_or_log("channel error") + }); + Ok(None) + } else { + let res = serde_v8::from_v8(scope, res).map_err(|err| { + CallbackError::ProtocolError( + ferr!(err).wrap_err("error deserializaing result from v8"), + ) + })?; + Ok(Some(res)) + } + }) + }); + + let res = match join_handle.await.expect_or_log("tokio error")? { + Some(res) => res, + None => { + debug!("waiting for callback proimse"); + rx.await.expect_or_log("channel error")? + } + }; + + Ok(res) + } +} + +struct Callback { + js_fn: SendPtr, + async_work_sender: deno_core::V8CrossThreadTaskSpawner, +} + +impl Clone for Callback { + fn clone(&self) -> Self { + Self { + js_fn: SendPtr(self.js_fn.0), + async_work_sender: self.async_work_sender.clone(), + } + } +} + +#[derive(Clone, Copy)] +#[repr(transparent)] +struct SendPtr(std::ptr::NonNull); +// SAFETY: we only ever access this value from within the same thread +// as deno +unsafe impl Send for SendPtr {} + +/* impl Callback { + fn drop(self, scope: &mut v8::HandleScope) { + unsafe { + _ = v8::Global::from_raw(scope, self.js_fn.0); + } + } +} */ + +#[deno_core::op2] +pub fn op_callbacks_set( + state: Rc>, + #[string] name: String, + #[global] cb: v8::Global, +) -> anyhow::Result<()> { + let (ctx, async_work_sender) = { + let state = state.borrow(); + let ctx = state.borrow::(); + let sender = state.borrow::(); + + (ctx.clone(), sender.clone()) + }; + ctx.callbacks.store.insert( + name.into(), + Callback { + js_fn: SendPtr(cb.into_raw()), + async_work_sender, + }, + ); + Ok(()) +} diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index df01517..4ded93f 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -1,59 +1,17 @@ use crate::interlude::*; +use crate::systems::*; + mod deno; mod hashfile; use hashfile::*; -#[derive(educe::Educe)] -#[educe(Debug)] -enum ModuleManifest { - Todo, -} - -impl ModuleManifest { - pub fn init(&self) -> ModuleInstance { - ModuleInstance::Todo - } -} -enum ModuleInstance { - Todo, -} - -type ModuleLockEntry = Box; -type ModuleContext = Box; - -impl ModuleInstance { - pub async fn load_lock_entry( - &mut self, - gcx: &GhjkCtx, - raw: serde_json::Value, - ) -> Res { - Ok(Box::new("todo")) - } - - pub async fn gen_lock_entry( - &mut self, - gcx: &GhjkCtx, - mcx: &ModuleContext, - ) -> Res { - Ok(serde_json::json!("todo")) - } - - pub async fn load_config( - &mut self, - gcx: &GhjkCtx, - bb: &ConfigBlackboard, - lock_entry: Option, - ) -> Res { - Ok(Box::new("todo")) - } -} - #[derive(Debug)] pub struct Config { /// Discard serialization cache. pub re_serialize: bool, /// Discard any resolved values in lockfile. + #[allow(unused)] pub re_resolve: bool, /// Force use serialization cache. pub locked: bool, @@ -61,32 +19,33 @@ pub struct Config { pub cwd: PathBuf, } -#[derive(Debug)] +#[derive(educe::Educe)] +#[educe(Debug)] pub struct HostCtx { pub gcx: Arc, - config: Config, - pub modules: HashMap, + pub config: Config, + #[educe(Debug(ignore))] + pub systems: HashMap, pub file_hash_memo: DHashMap, } impl HostCtx { - pub fn new(gcx: Arc, config: Config) -> Self { + pub fn new( + gcx: Arc, + config: Config, + systems: HashMap, + ) -> Self { Self { gcx, config, - modules: [ - ("envs".into(), ModuleManifest::Todo), - ("ports".into(), ModuleManifest::Todo), - ("tasks".into(), ModuleManifest::Todo), - ] - .into_iter() - .collect(), + systems, file_hash_memo: default(), } } } -pub async fn modules_from_ghjkfile(hcx: Arc) -> Res> { +#[tracing::instrument(skip(hcx))] +pub async fn systems_from_ghjkfile(hcx: Arc) -> Res> { let (hashfile_path, lockfile_path) = ( hcx.gcx.ghjk_dir_path.join("hash.json"), hcx.gcx.ghjk_dir_path.join("lock.json"), @@ -155,23 +114,23 @@ pub async fn modules_from_ghjkfile(hcx: Arc) -> Res) -> Res) -> Res, pub config: Arc, hash_obj: HashObj, - mod_instances: IndexMap, + sys_instances: IndexMap, old_lock_obj: Option, lockfile_path: PathBuf, hashfile_path: PathBuf, @@ -251,25 +210,23 @@ pub struct GhjkfileModules { hashfile_written: bool, } -impl GhjkfileModules { +impl GhjkfileSystems { + #[tracing::instrument(skip(self))] pub async fn write_lockfile(&mut self) -> Res<()> { let mut lock_obj = LockObj { version: "0".into(), config: self.config.clone(), - module_entries: default(), + sys_entries: default(), }; - // generate the lock entries after *all* the modules + // generate the lock entries after *all* the systems // are done processing their config to allow // any shared stores to be properly populated // e.g. the resolution memo store - for (mod_id, (mod_inst, mcx)) in &mut self.mod_instances { - let lock_entry = mod_inst - .gen_lock_entry(&self.hcx.gcx, mcx) - .await - .wrap_err_with(|| { - format!("error generating lock entry for module: {:?}", mod_id) - })?; - lock_obj.module_entries.insert(mod_id.clone(), lock_entry); + for (sys_id, sys_inst) in &mut self.sys_instances { + let lock_entry = sys_inst.gen_lock_entry().await.wrap_err_with(|| { + format!("error generating lock entry for system: {:?}", sys_id) + })?; + lock_obj.sys_entries.insert(sys_id.clone(), lock_entry); } if self.old_lock_obj.is_none() @@ -278,12 +235,13 @@ impl GhjkfileModules { if self.hcx.config.locked { warn!("locked flag set, changes to lockfile discarded"); } else { - tokio::fs::write( + debug!(lockfile_path = ?self.lockfile_path, ?lock_obj, "writing lock.json"); + /* tokio::fs::write( &self.lockfile_path, serde_json::to_vec_pretty(&lock_obj).expect_or_log("error jsonifying lockfile"), ) .await - .wrap_err("error writing to lockfile")?; + .wrap_err("error writing to lockfile")?; */ self.old_lock_obj.replace(lock_obj); } } @@ -294,13 +252,14 @@ impl GhjkfileModules { if self.hcx.config.locked { unreachable!("code should have early exited"); } - tokio::fs::write( - &self.lockfile_path, + debug!(hashfile_path = ?self.hashfile_path, hash_obj= ?self.hash_obj, "writing hash.json"); + /* tokio::fs::write( + &self.hashfile_path, serde_json::to_vec_pretty(&self.hash_obj) .expect_or_log("error jsonifying hashfile"), ) .await - .wrap_err("error writing to lockfile")?; + .wrap_err("error writing to lockfile")?; */ self.hashfile_written = true; } Ok(()) @@ -310,7 +269,6 @@ impl GhjkfileModules { async fn serialize_ghjkfile(hcx: &HostCtx, path: &Path) -> Res<(Arc, HashObj)> { let ext = path.extension(); let res = if ext.map(|ext| ext == "ts" || ext == "js") == Some(true) { - debug!("serializing deno ghjkfile"); deno::serialize_deno_ghjkfile(hcx, path).await? } else { eyre::bail!("unrecognized ghjkfile extension: {path:?}") @@ -323,7 +281,9 @@ async fn serialize_ghjkfile(hcx: &HostCtx, path: &Path) -> Res<(Arc Res<(Arc, read_file_paths: Vec, listed_file_paths: Vec, - loaded_modules: Vec, -} - -type ModuleId = CHeapStr; - -#[derive(Debug, Serialize, Deserialize, PartialEq)] -struct ModuleConfig { - pub id: ModuleId, - pub config: serde_json::Value, } -type ConfigBlackboard = serde_json::Map; - #[derive(Debug, Serialize, Deserialize, PartialEq)] pub struct SerializedConfig { - modules: Vec, + modules: Vec, blackboard: ConfigBlackboard, } #[derive(Debug, Serialize, Deserialize, PartialEq)] pub struct LockObj { pub version: String, - pub module_entries: indexmap::IndexMap, + pub sys_entries: indexmap::IndexMap, pub config: Arc, } impl LockObj { /// The lock.json file stores the serialized config and some entries - /// from modules. It's primary purpose is as a memo store to avoid + /// from systems. It's primary purpose is as a memo store to avoid /// re-serialization on each CLI invocation. pub async fn from_file(path: &Path) -> Res { let raw = tokio::fs::read(path) diff --git a/src/ghjk/host/deno.rs b/src/ghjk/host/deno.rs index c78168b..9703c6d 100644 --- a/src/ghjk/host/deno.rs +++ b/src/ghjk/host/deno.rs @@ -11,17 +11,20 @@ struct InternalSerializationResult { listed_file_paths: Vec, } +#[tracing::instrument(skip(hcx))] pub async fn serialize_deno_ghjkfile( hcx: &super::HostCtx, path: &Path, ) -> Res { - let main_module = deno_runtime::deno_core::resolve_path( - hcx.gcx.repo_root.join("./files/deno/mod2.ts"), - &hcx.config.cwd, - ) - .wrap_err("error resolving main module")?; + let main_module = hcx + .gcx + .repo_root + .join("files/deno/bindings.ts") + .wrap_err("repo url error")?; + + let mut ext_conf = crate::ext::ExtConfig::new(); - let blackboard = [ + ext_conf.blackboard = [ // blackboard is used as communication means // with the deno side of the code ( @@ -32,11 +35,12 @@ pub async fn serialize_deno_ghjkfile( ), ] .into_iter() - .collect::>(); + .collect::>() + .into(); - let blackboard = Arc::new(blackboard); + let bb = ext_conf.blackboard.clone(); - let mut worker = hcx + let worker = hcx .gcx .deno .prepare_module( @@ -50,27 +54,38 @@ pub async fn serialize_deno_ghjkfile( }, deno_runtime::WorkerExecutionMode::Run, default(), - Some(crate::deno::extensions(crate::deno::ExtConfig { - blackboard: blackboard.clone(), - })), + Some(crate::ext::extensions(ext_conf)), ) .await?; - let exit_code = worker.run().await?; + let (exit_code, mut worker) = worker.run().await?; if exit_code != 0 { eyre::bail!("non-zero exit code running deno module"); } let loaded_modules = worker.get_loaded_modules().await; - let (_, resp) = blackboard.remove("resp").expect_or_log("resp missing"); + let (_, resp) = bb.remove("resp").expect_or_log("resp missing"); let resp: InternalSerializationResult = serde_json::from_value(resp).expect_or_log("error deserializing resp"); + let mut loaded_modules = loaded_modules + .into_iter() + .filter(|url| url.scheme() == "file") + .map(|url| { + url.to_file_path() + .map_err(|()| ferr!("url to path error: {url}")) + }) + .collect::>>()?; + + let mut read_file_paths = resp.read_file_paths; + read_file_paths.append(&mut loaded_modules); + + debug!("ghjk.ts serialized"); + Ok(super::SerializationResult { config: resp.config, accessed_env_keys: resp.accessed_env_keys, listed_file_paths: resp.listed_file_paths, - read_file_paths: resp.read_file_paths, - loaded_modules, + read_file_paths, }) } diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs index 97d4c8d..7c67d7f 100644 --- a/src/ghjk/host/hashfile.rs +++ b/src/ghjk/host/hashfile.rs @@ -51,7 +51,7 @@ impl HashObj { { if self.read_file_hashes != file_digests( - &hcx, + hcx, self.read_file_hashes .keys() .map(|path| path.as_ref()) @@ -74,10 +74,7 @@ pub fn env_var_digests<'a>( .map(|key| { ( key.to_owned(), - match all.get(key) { - Some(val) => Some(crate::utils::hash_str(val)), - None => None, - }, + all.get(key).map(|val| crate::utils::hash_str(val)), ) }) .collect() @@ -162,7 +159,7 @@ impl From for StatMeta { ts.duration_since(std::time::SystemTime::UNIX_EPOCH) .map_err(|_| ()) }) - .and_then(|dur| Ok(dur.as_secs())) + .map(|dur| dur.as_secs()) .ok() } #[cfg(unix)] diff --git a/src/ghjk/deno/00_runtime.js b/src/ghjk/js/00_runtime.js similarity index 74% rename from src/ghjk/deno/00_runtime.js rename to src/ghjk/js/00_runtime.js index e4ce282..70e342e 100644 --- a/src/ghjk/deno/00_runtime.js +++ b/src/ghjk/js/00_runtime.js @@ -21,14 +21,23 @@ function getOp(name) { return op; } +const op_callbacks_set = getOp("op_callbacks_set"); + /** * @type {import('./runtime.d.ts').GhjkNs} */ const Ghjk = { blackboard: { - get: getOp("op_get_blackboard"), - set: getOp("op_set_blackboard"), + get: getOp("op_blackboard_get"), + set: getOp("op_blackboard_set"), + }, + callbacks: { + set: (key, fn) => { + op_callbacks_set(key, fn); + return key; + }, }, + hostcall: getOp("op_hostcall"), }; globalThis.Ghjk = Ghjk; diff --git a/src/ghjk/js/mock.sfx.ts b/src/ghjk/js/mock.sfx.ts new file mode 100644 index 0000000..76de814 --- /dev/null +++ b/src/ghjk/js/mock.sfx.ts @@ -0,0 +1,20 @@ +//! Import this as a side effect for a mock the Ghjk object. +//! Useful to sanity check code that relies on the Ghjk extension. + +import { Ghjk } from "./runtime.js"; + +const bb = new Map(); +Object.assign(Ghjk, { + callbacks: { + set: (key: string) => key, + }, + hostcall: () => Promise.resolve({}), + blackboard: { + set: (key: string, value: any) => { + const old = bb.get(key); + bb.set(key, value); + return old; + }, + get: (key: string) => bb.get(key), + }, +}); diff --git a/src/ghjk/deno/runtime.d.ts b/src/ghjk/js/runtime.d.ts similarity index 59% rename from src/ghjk/deno/runtime.d.ts rename to src/ghjk/js/runtime.d.ts index 1e2a931..8d4e664 100644 --- a/src/ghjk/deno/runtime.d.ts +++ b/src/ghjk/js/runtime.d.ts @@ -1,5 +1,4 @@ -type JsonLiteral = string | number | boolean | null; - +export type JsonLiteral = string | number | boolean | null; export type JsonObject = { [key: string]: Json }; export type JsonArray = Json[]; export type Json = JsonLiteral | JsonObject | JsonArray; @@ -9,5 +8,9 @@ type GhjkNs = { get: (key: string) => Json | undefined; set: (key: string, value: Json) => Json | undefined; }; + callbacks: { + set: (key: string, fn: (arg: Json) => Json | Promise) => string; + }; + hostcall: (key: string, args: Json) => Promise; }; export const Ghjk: GhjkNs; diff --git a/src/ghjk/deno/runtime.js b/src/ghjk/js/runtime.js similarity index 100% rename from src/ghjk/deno/runtime.js rename to src/ghjk/js/runtime.js diff --git a/src/ghjk/log.rs b/src/ghjk/log.rs new file mode 100644 index 0000000..76ade7e --- /dev/null +++ b/src/ghjk/log.rs @@ -0,0 +1,95 @@ +use crate::interlude::*; + +pub fn init() { + static INIT: std::sync::Once = std::sync::Once::new(); + INIT.call_once(|| { + let eyre_panic_hook = color_eyre::config::HookBuilder::default().display_location_section( + std::env::var("RUST_ERR_LOCATION") + .map(|var| var != "0") + .unwrap_or(true), + ); + + #[cfg(not(debug_assertions))] + let eyre_panic_hook = eyre_panic_hook.panic_section(format!( + r#"Ghjk has panicked. This is a bug, please report this +at https://github.com/metatypedev/ghjk/issues/new. +If you can reliably reproduce this panic, try to include the +following items in your report: +- Reproduction steps +- Output of meta-cli doctor and +- A panic backtrace. Set the following environment variables as shown to enable full backtraces. + - RUST_BACKTRACE=1 + - RUST_LIB_BACKTRACE=full + - RUST_SPANTRACE=1 +Platform: {platform} +Version: {version} +Args: {args:?} +"#, + platform = crate::build::BUILD_TARGET, + // TODO: include commit sha + version = crate::build::PKG_VERSION, + args = std::env::args().collect::>() + )); + + let (eyre_panic_hook, _eyre_hook) = eyre_panic_hook.try_into_hooks().unwrap(); + let eyre_panic_hook = eyre_panic_hook.into_panic_hook(); + + std::panic::set_hook(Box::new(move |panic_info| { + if let Some(msg) = panic_info.payload().downcast_ref::<&str>() { + if msg.contains("A Tokio 1.x context was found, but it is being shutdown.") { + warn!("improper shutdown, make sure to terminate all workers first"); + return; + } + } else if let Some(msg) = panic_info.payload().downcast_ref::() { + if msg.contains("A Tokio 1.x context was found, but it is being shutdown.") { + warn!("improper shutdown, make sure to terminate all workers first"); + return; + } + } + eyre_panic_hook(panic_info); + // - Tokio does not exit the process when a task panics, so we define a custom + // panic hook to implement this behaviour. + // std::process::exit(1); + })); + + // FIXME: for some reason, the tests already have + // an eyre_hook + #[cfg(not(test))] + _eyre_hook.install().unwrap(); + + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "info,actix_server=warn"); + } + #[cfg(not(debug_assertions))] + if std::env::var("RUST_SPANTRACE").is_err() { + std::env::set_var("RUST_SPANTRACE", "0"); + } + + use tracing_subscriber::prelude::*; + + let fmt = tracing_subscriber::fmt::layer() + .without_time() + .with_writer(std::io::stderr) + // .pretty() + // .with_file(true) + // .with_line_number(true) + .with_target(false); + + #[cfg(test)] + let fmt = fmt.with_test_writer(); + + #[cfg(debug_assertions)] + let fmt = fmt.with_target(true); + + let filter = tracing_subscriber::EnvFilter::from_default_env(); + + tracing_subscriber::registry() + // filter on values from RUST_LOG + .with(filter) + // subscriber that emits to stderr + .with(fmt) + // instrument errors with SpanTraces, used by color-eyre + .with(tracing_error::ErrorLayer::default()) + .init(); + }); +} diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index 25f172f..7427988 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -25,14 +25,16 @@ mod interlude { pub use serde_json::json; pub use smallvec::smallvec as svec; pub use smallvec::SmallVec as Svec; - pub use tracing::{debug, error, info, trace, warn}; + pub use tracing::{debug, error, info, trace, warn, Instrument}; pub use tracing_unwrap::*; } mod host; mod cli {} -mod deno; +mod ext; +mod log; +mod systems; mod utils; use crate::interlude::*; @@ -44,7 +46,7 @@ fn main() -> Res<()> { use nix::sys::signal::*; signal(Signal::SIGPIPE, SigHandler::SigDfl)?; } - utils::setup_tracing()?; + log::init(); denort::init(); tokio::runtime::Builder::new_current_thread() @@ -60,78 +62,104 @@ shadow!(build); const DENO_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; async fn cli() -> Res<()> { - debug!(version = build::VERSION, "ghjk CLI"); + debug!(version = build::PKG_VERSION, "ghjk CLI"); let cwd = std::env::current_dir()?; - let ghjk_dir_path = match std::env::var("GHJK_DIR") { - Ok(path) => Some(PathBuf::from(path)), - Err(std::env::VarError::NotUnicode(os_str)) => Some(PathBuf::from(os_str)), - Err(std::env::VarError::NotPresent) => utils::find_entry_recursive(&cwd, ".ghjk").await?, - }; + let config = { + let ghjk_dir_path = match std::env::var("GHJK_DIR") { + Ok(path) => Some(PathBuf::from(path)), + Err(std::env::VarError::NotUnicode(os_str)) => Some(PathBuf::from(os_str)), + Err(std::env::VarError::NotPresent) => { + utils::find_entry_recursive(&cwd, ".ghjk").await? + } + }; - let ghjk_dir_path = if let Some(path) = ghjk_dir_path { - Some(tokio::fs::canonicalize(path).await?) - } else { - None - }; + let ghjk_dir_path = if let Some(path) = ghjk_dir_path { + Some(tokio::fs::canonicalize(path).await?) + } else { + None + }; - let ghjkfile_path = match &ghjk_dir_path { - Some(ghjkfile_path) => { - utils::find_entry_recursive( - ghjkfile_path - .parent() - .expect_or_log("invalid GHJK_DIR path"), - "ghjk.ts", - ) - .await? - } - None => utils::find_entry_recursive(&cwd, "ghjk.ts").await?, - }; + let ghjkfile_path = match &ghjk_dir_path { + Some(ghjkfile_path) => { + utils::find_entry_recursive( + ghjkfile_path + .parent() + .expect_or_log("invalid GHJK_DIR path"), + "ghjk.ts", + ) + .await? + } + None => utils::find_entry_recursive(&cwd, "ghjk.ts").await?, + }; - let ghjkfile_path = if let Some(path) = ghjkfile_path { - Some(tokio::fs::canonicalize(path).await?) - } else { - None - }; + let ghjkfile_path = if let Some(path) = ghjkfile_path { + Some(tokio::fs::canonicalize(path).await?) + } else { + None + }; - if ghjk_dir_path.is_none() && ghjkfile_path.is_none() { - warn!("ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.",); - } + if ghjk_dir_path.is_none() && ghjkfile_path.is_none() { + warn!( + "ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.", + ); + } - let share_dir_path = match std::env::var("GHJK_SHARE_DIR") { - Ok(path) => PathBuf::from(path), - Err(std::env::VarError::NotUnicode(os_str)) => PathBuf::from(os_str), - Err(std::env::VarError::NotPresent) => directories::BaseDirs::new() - .expect_or_log("unable to resolve home dir") - .data_local_dir() - .join("ghjk"), + let share_dir_path = match std::env::var("GHJK_SHARE_DIR") { + Ok(path) => PathBuf::from(path), + Err(std::env::VarError::NotUnicode(os_str)) => PathBuf::from(os_str), + Err(std::env::VarError::NotPresent) => directories::BaseDirs::new() + .expect_or_log("unable to resolve home dir") + .data_local_dir() + .join("ghjk"), + }; + Config { + ghjkfile_path, + ghjk_dir_path, + share_dir_path, + } }; - if let Some(ghjk_dir_path) = ghjk_dir_path { + let deno_cx = denort::worker( + denort::deno::args::Flags { + unstable_config: denort::deno::args::UnstableConfig { + features: DENO_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..default() + }, + ..default() + }, + Some(Arc::new(Vec::new)), + ) + .await?; + + if let Some(ghjk_dir_path) = config.ghjk_dir_path { let gcx = GhjkCtx { ghjk_dir_path, - ghjkfile_path, - share_dir_path, - repo_root: cwd.clone(), - deno: denort::worker( - denort::deno::args::Flags { - unstable_config: denort::deno::args::UnstableConfig { - features: DENO_UNSTABLE_FLAGS - .iter() - .copied() - .map(String::from) - .collect(), - ..default() - }, - ..default() - }, - Some(Arc::new(Vec::new)), - ) - .await?, + ghjkfile_path: config.ghjkfile_path, + share_dir_path: config.share_dir_path, + repo_root: url::Url::from_file_path(&cwd) + .expect_or_log("cwd error") + // repo root url must end in slash due to + // how Url::join works + .join(&format!("{}/", cwd.file_name().unwrap().to_string_lossy())) + .wrap_err("repo url error")?, + deno: deno_cx.clone(), }; let gcx = Arc::new(gcx); + let systems_deno = systems::deno::systems_from_deno( + &gcx, + &gcx.repo_root + .join("src/deno_systems/mod.ts") + .wrap_err("repo url error")?, + ) + .await?; + let hcx = host::HostCtx::new( gcx, host::Config { @@ -141,25 +169,29 @@ async fn cli() -> Res<()> { env_vars: std::env::vars().collect(), cwd, }, + systems_deno, ); let hcx = Arc::new(hcx); - if let Some(modules) = host::modules_from_ghjkfile(hcx).await? { - let conf_json = serde_json::to_string_pretty(&modules.config)?; + if let Some(mut systems) = host::systems_from_ghjkfile(hcx).await? { + let conf_json = serde_json::to_string_pretty(&systems.config)?; info!(%conf_json); + systems.write_lockfile().await?; } else { warn!("no ghjkfile found"); } } + // tokio::task::spawn_blocking(|| deno_cx.terminate()); + Ok(()) } #[derive(Debug)] pub struct GhjkCtx { deno: denort::DenoWorkerHandle, - repo_root: PathBuf, + repo_root: url::Url, ghjkfile_path: Option, ghjk_dir_path: PathBuf, share_dir_path: PathBuf, diff --git a/src/ghjk/systems.rs b/src/ghjk/systems.rs new file mode 100644 index 0000000..0795e70 --- /dev/null +++ b/src/ghjk/systems.rs @@ -0,0 +1,112 @@ +//! Systems (formerly modules) are units of implementation that bundle together +//! related functionality. + +use std::any::Any; + +use crate::interlude::*; + +pub mod deno; + +pub enum SystemManifest { + Deno(deno::DenoSystemManifest), +} + +impl SystemManifest { + pub async fn init(&self) -> Res { + match self { + SystemManifest::Deno(man) => Ok(ErasedSystemInstance::new(Arc::new(man.ctor().await?))), + } + } +} + +#[async_trait::async_trait] +pub trait SystemInstance { + type LockState; + + async fn load_config( + &self, + config: serde_json::Value, + bb: ConfigBlackboard, + state: Option, + ) -> Res<()>; + + async fn load_lock_entry(&self, raw: serde_json::Value) -> Res; + + async fn gen_lock_entry(&self) -> Res; +} + +type BoxAny = Box; + +#[allow(clippy::type_complexity)] +pub struct ErasedSystemInstance { + load_lock_entry_fn: Box BoxFuture<'static, Res>>, + gen_lock_entry_fn: Box BoxFuture<'static, Res>>, + load_config_fn: Box< + dyn Fn(serde_json::Value, ConfigBlackboard, Option) -> BoxFuture<'static, Res<()>>, + >, +} + +impl ErasedSystemInstance { + pub fn new(instance: Arc) -> Self + where + S: SystemInstance + Send + Sync + 'static, + L: std::any::Any + Send + Sync, + { + Self { + load_lock_entry_fn: { + let instance = instance.clone(); + Box::new(move |raw| { + let instance = instance.clone(); + async move { + let res: BoxAny = Box::new(instance.load_lock_entry(raw).await?); + Ok(res) + } + .boxed() + }) + }, + gen_lock_entry_fn: { + let instance = instance.clone(); + Box::new(move || { + let instance = instance.clone(); + async move { instance.gen_lock_entry().await }.boxed() + }) + }, + load_config_fn: Box::new(move |config, bb, state| { + let instance = instance.clone(); + async move { + let state: Option> = + state.map(|st| st.downcast().expect_or_log("downcast error")); + instance.load_config(config, bb, state.map(|bx| *bx)).await + } + .boxed() + }), + } + } + + pub async fn load_config( + &self, + config: serde_json::Value, + bb: ConfigBlackboard, + state: Option, + ) -> Res<()> { + (self.load_config_fn)(config, bb, state).await + } + + pub async fn load_lock_entry(&self, raw: serde_json::Value) -> Res { + (self.load_lock_entry_fn)(raw).await + } + + pub async fn gen_lock_entry(&self) -> Res { + (self.gen_lock_entry_fn)().await + } +} + +pub type SystemId = CHeapStr; + +#[derive(Debug, Serialize, Deserialize, PartialEq)] +pub struct SystemConfig { + pub id: SystemId, + pub config: serde_json::Value, +} + +pub type ConfigBlackboard = Arc>; diff --git a/src/ghjk/systems/deno.rs b/src/ghjk/systems/deno.rs new file mode 100644 index 0000000..15ef2e3 --- /dev/null +++ b/src/ghjk/systems/deno.rs @@ -0,0 +1,256 @@ +//! This module implements support for systems written in typescript +//! running on top of deno. + +use crate::interlude::*; + +use super::{SystemId, SystemInstance, SystemManifest}; + +#[derive(Clone)] +pub struct DenoSystemsContext { + callbacks: crate::ext::CallbacksHandle, + exit_code_channel: Arc>>>, + term_signal: Arc, + #[allow(unused)] + hostcalls: crate::ext::Hostcalls, +} + +impl DenoSystemsContext { + #[allow(unused)] + pub async fn terminate(&mut self) -> Res { + let channel = { + let mut opt = self.exit_code_channel.lock().expect_or_log("mutex error"); + opt.take() + }; + let Some(channel) = channel else { + eyre::bail!("already terminated") + }; + self.term_signal + .store(true, std::sync::atomic::Ordering::Relaxed); + Ok(channel.await.expect_or_log("channel error")) + } +} + +#[tracing::instrument(skip(gcx))] +pub async fn systems_from_deno( + gcx: &GhjkCtx, + source_uri: &url::Url, +) -> Res> { + let main_module = gcx + .repo_root + .join("src/deno_systems/bindings.ts") + .wrap_err("repo url error")?; + + let mut ext_conf = crate::ext::ExtConfig::new(); + + let bb = ext_conf.blackboard.clone(); + bb.insert("args".into(), { + #[derive(Serialize)] + struct GhjkCtxBean<'a> { + ghjkfile_path: Option<&'a Path>, + ghjk_dir_path: &'a Path, + share_dir_path: &'a Path, + } + + #[derive(Serialize)] + struct BindingArgs<'a> { + uri: url::Url, + gcx: GhjkCtxBean<'a>, + } + let GhjkCtx { + deno, + repo_root, + ghjkfile_path, + ghjk_dir_path, + share_dir_path, + } = gcx; + _ = (deno, repo_root); + + serde_json::json!(BindingArgs { + uri: source_uri.clone(), + gcx: GhjkCtxBean { + ghjkfile_path: ghjkfile_path.as_ref().map(|path| path.as_path()), + ghjk_dir_path, + share_dir_path, + }, + }) + }); + let hostcalls = ext_conf.hostcalls.clone(); + + let (manifests_tx, mut manifests_rx) = tokio::sync::mpsc::channel(1); + hostcalls.funcs.insert( + "register_systems".into(), + Box::new(move |args| { + let tx = manifests_tx.clone(); + async move { + tx.send(args).await.expect_or_log("channel error"); + Ok(serde_json::Value::Null) + } + .boxed() + }), + ); + let cb_line = ext_conf.callbacks_handle(); + + let mut worker = gcx + .deno + .prepare_module( + main_module, + deno_runtime::deno_permissions::PermissionsOptions { + allow_env: Some(vec![]), + allow_import: Some(vec![]), + allow_read: Some(vec![]), + allow_net: Some(vec![]), + allow_ffi: Some(vec![]), + allow_run: Some(vec![]), + allow_sys: Some(vec![]), + allow_write: Some(vec![]), + allow_all: true, + prompt: false, + ..default() + }, + deno_runtime::WorkerExecutionMode::Run, + default(), + Some(crate::ext::extensions(ext_conf)), + ) + .await?; + worker.execute().await?; + let (exit_code_channel, term_signal, _) = worker.drive_till_exit().await?; + + let join_exit_code_watcher = tokio::spawn(async { + let exit_code = exit_code_channel + .await + .expect_or_log("channel error") + .wrap_err("error on event loop for deno systems") + .unwrap_or_log(); + if exit_code != 0 { + // TODO: exit signals + error!(%exit_code, "deno systems died with non-zero exit code"); + } else { + info!(%exit_code, "deno systems exit") + } + exit_code + }); + let exit_code_channel = Arc::new(std::sync::Mutex::new(Some(join_exit_code_watcher))); + + let scx = DenoSystemsContext { + callbacks: cb_line, + hostcalls, + term_signal, + exit_code_channel, + }; + let scx = Arc::new(scx); + + let manifests = manifests_rx.recv().await.expect_or_log("channel error"); + let manifests: Vec = + serde_json::from_value(manifests).wrap_err("protocol error")?; + let manifests = manifests + .into_iter() + .map(|desc| { + ( + desc.id.clone(), + SystemManifest::Deno(DenoSystemManifest { + desc, + scx: scx.clone(), + }), + ) + }) + .collect(); + + Ok(manifests) +} + +#[derive(Debug, Deserialize)] +struct ManifestDesc { + id: SystemId, + ctor_cb_key: CHeapStr, +} + +#[derive(educe::Educe)] +#[educe(Debug)] +pub struct DenoSystemManifest { + desc: ManifestDesc, + #[educe(Debug(ignore))] + scx: Arc, +} + +impl DenoSystemManifest { + pub async fn ctor(&self) -> Res { + debug!(id = %self.desc.id, "initializing deno system"); + let desc = self + .scx + .callbacks + .exec(self.desc.ctor_cb_key.clone(), serde_json::Value::Null) + .await?; + + let desc = serde_json::from_value(desc).wrap_err("protocol error")?; + + debug!(id = %self.desc.id, "deno system initialized"); + + Ok(DenoSystemInstance { + desc, + scx: self.scx.clone(), + }) + } +} + +#[derive(Debug, Deserialize)] +/// This is the description sent from the typescript side for a registered manifest. +struct InstanceDesc { + load_lock_entry_cb_key: CHeapStr, + gen_lock_entry_cb_key: CHeapStr, + load_config_cb_key: CHeapStr, +} + +pub struct DenoSystemInstance { + desc: InstanceDesc, + scx: Arc, +} + +#[async_trait::async_trait] +impl SystemInstance for DenoSystemInstance { + type LockState = serde_json::Value; + + async fn load_config( + &self, + config: serde_json::Value, + bb: Arc>, + state: Option, + ) -> Res<()> { + self.scx + .callbacks + .exec( + self.desc.load_config_cb_key.clone(), + serde_json::json!({ + "config": config, + "bb": bb, + "state": state + }), + ) + .await + .wrap_err("callback error")?; + Ok(()) + } + + async fn load_lock_entry(&self, raw: serde_json::Value) -> Res { + self.scx + .callbacks + .exec( + self.desc.load_lock_entry_cb_key.clone(), + serde_json::json!({ + "raw": raw + }), + ) + .await + .wrap_err("callback error") + } + + async fn gen_lock_entry(&self) -> Res { + self.scx + .callbacks + .exec( + self.desc.gen_lock_entry_cb_key.clone(), + serde_json::json!({}), + ) + .await + .wrap_err("callback error") + } +} diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index d71783f..30e1201 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -1,33 +1,6 @@ -use std::io::Write; - use crate::interlude::*; -// Ensure that the `tracing` stack is only initialised once using `once_cell` -// isn't required in cargo-nextest since each test runs in a new process -pub fn _setup_tracing_once() { - use once_cell::sync::Lazy; - static TRACING: Lazy<()> = Lazy::new(|| { - setup_tracing().expect("failed to init tracing"); - }); - Lazy::force(&TRACING); -} - -pub fn setup_tracing() -> eyre::Result<()> { - color_eyre::install()?; - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - - // tracing_log::LogTracer::init()?; - tracing_subscriber::fmt() - .compact() - .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) - .with_timer(tracing_subscriber::fmt::time::uptime()) - .try_init() - .map_err(|err| eyre::eyre!(err))?; - - Ok(()) -} +use std::io::Write; #[inline] pub fn default() -> T { @@ -75,10 +48,13 @@ mod cheapstr { } } - impl From<&str> for CHeapStr { + impl From for CHeapStr + where + T: Into>, + { #[inline(always)] - fn from(string: &str) -> Self { - Self::new(string.to_owned()) + fn from(string: T) -> Self { + Self::new(string) } } @@ -127,14 +103,6 @@ mod cheapstr { } } - impl From for CHeapStr { - fn from(string: String) -> Self { - /* let byte_arc: Arc<[u8]> = string.into_bytes().into(); - let str_arc = unsafe { Arc::from_raw(Arc::into_raw(byte_arc) as *const str) }; */ - Self::new(string) - } - } - impl From for String { fn from(value: CHeapStr) -> String { // FIXME: optmize this @@ -167,10 +135,11 @@ const SHA2_256: u64 = 0x12; pub fn hash_obj(obj: &T) -> String { use sha2::Digest; let mut hash = sha2::Sha256::new(); - json_canon::to_writer(&mut hash, obj).expect("error serializing manifest"); + json_canon::to_writer(&mut hash, obj).expect_or_log("error serializing manifest"); let hash = hash.finalize(); - let hash = multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect("error multihashing"); + let hash = + multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect_or_log("error multihashing"); encode_base32_multibase(hash.digest()) } @@ -181,14 +150,21 @@ pub fn hash_str(string: &str) -> String { .expect_or_log("error writing to hasher"); let hash = hash.finalize(); - let hash = multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect("error multihashing"); + let hash = + multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect_or_log("error multihashing"); encode_base32_multibase(hash.digest()) } pub fn encode_base32_multibase>(source: T) -> String { - format!("b{}", data_encoding::BASE32_NOPAD.encode(source.as_ref())) + format!( + "b{}", + data_encoding::BASE32_NOPAD + .encode(source.as_ref()) + .to_lowercase() + ) } +#[allow(unused)] // Consider z-base32 https://en.wikipedia.org/wiki/Base32#z-base-32 pub fn decode_base32_multibase(source: &str) -> eyre::Result> { match ( @@ -203,6 +179,7 @@ pub fn decode_base32_multibase(source: &str) -> eyre::Result> { } } +#[allow(unused)] pub fn encode_hex_multibase>(source: T) -> String { format!( "f{}", @@ -210,6 +187,7 @@ pub fn encode_hex_multibase>(source: T) -> String { ) } +#[allow(unused)] pub fn decode_hex_multibase(source: &str) -> eyre::Result> { match ( &source[0..1], diff --git a/utils/mod.ts b/utils/mod.ts index 8ec530f..2e77256 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -603,13 +603,12 @@ export function unwrapZodRes( const zodErr = zod_val_err.fromZodError(res.error, { includePath: true, maxIssuesInMessage: 3, + prefix: errMessage, }); - throw new Error(`${errMessage}: ${zodErr}`, { - cause: { - issues: res.error.issues, - ...cause, - }, - }); + zodErr.cause = { + ...cause, + }; + throw zodErr; } return res.data; } From 1091966a94f752a8209b5a91787b5e95f3b2518d Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:56:42 +0300 Subject: [PATCH 09/15] refactor: rewrite in rust (cli) (#108) --- .cargo/config.toml | 7 + .ghjk/deno.lock | 314 +++----- .ghjk/lock.json | 266 +++++-- .github/workflows/nightly.yml | 2 +- .github/workflows/tests.yml | 40 +- .gitignore | 2 + .pre-commit-config.yaml | 1 - Cargo.lock | 1130 +++++++++++++++++++++------- Cargo.toml | 12 +- README.md | 13 +- deno.jsonc | 4 +- deno.lock | 350 +-------- deps/install.ts | 1 + docs/manual.md | 6 +- ghjk.ts | 72 +- host/mod.ts | 625 --------------- install.sh | 180 ++++- install.ts | 22 +- install/bash-preexec.sh | 353 +++++++++ install/ghjk.sh | 55 -- install/hook.fish | 1 + install/hook.sh | 2 +- install/mod.ts | 136 +--- install/utils.ts | 21 +- main.ts | 43 -- modules/envs/mod.ts | 214 +++--- modules/envs/posix.ts | 22 +- modules/mod.ts | 4 +- modules/ports/mod.ts | 321 ++++---- modules/ports/sync.ts | 2 +- modules/ports/worker.ts | 2 + modules/tasks/mod.ts | 86 +-- modules/types.ts | 2 +- rust-toolchain.toml | 6 + scripts/dev.ts | 37 +- src/deno_systems/bindings.ts | 116 ++- src/deno_systems/mod.ts | 2 +- src/deno_systems/types.ts | 145 ++++ src/denort/lib.rs | 606 ++------------- src/denort/promises.rs | 21 +- src/denort/unsync.rs | 280 +++++++ src/denort/worker.rs | 564 ++++++++++++++ src/ghjk/Cargo.toml | 24 +- src/ghjk/cli.rs | 441 +++++++++++ src/ghjk/config.rs | 286 +++++++ src/ghjk/ext.rs | 13 +- src/ghjk/ext/callbacks.rs | 157 ++-- src/ghjk/host.rs | 142 ++-- src/ghjk/host/deno.rs | 1 + src/ghjk/host/hashfile.rs | 138 +++- src/ghjk/js/00_runtime.js | 4 +- src/ghjk/js/runtime.js | 9 +- src/ghjk/log.rs | 25 +- src/ghjk/main.rs | 171 +---- src/ghjk/systems.rs | 53 +- src/ghjk/systems/deno.rs | 138 ++-- src/ghjk/systems/deno/cli.rs | 400 ++++++++++ src/ghjk/utils.rs | 54 +- src/play/Cargo.toml | 22 + src/play/main.rs | 20 + src/xtask/main.rs | 25 +- tests/envHooks.ts | 4 +- tests/envs.ts | 2 + tests/ports.ts | 9 +- tests/reloadHooks.ts | 5 +- tests/test-alpine.Dockerfile | 80 -- tests/test.Dockerfile | 71 -- tests/test.Dockerfile.dockerignore | 4 - tests/todo.ts | 2 + tests/utils.ts | 157 ++-- utils/mod.ts | 25 +- 71 files changed, 5120 insertions(+), 3450 deletions(-) create mode 100644 deps/install.ts delete mode 100644 host/mod.ts create mode 100644 install/bash-preexec.sh delete mode 100644 install/ghjk.sh delete mode 100755 main.ts create mode 100644 rust-toolchain.toml create mode 100644 src/deno_systems/types.ts create mode 100644 src/denort/unsync.rs create mode 100644 src/denort/worker.rs create mode 100644 src/ghjk/cli.rs create mode 100644 src/ghjk/config.rs create mode 100644 src/ghjk/systems/deno/cli.rs create mode 100644 src/play/Cargo.toml create mode 100644 src/play/main.rs delete mode 100644 tests/test-alpine.Dockerfile delete mode 100644 tests/test.Dockerfile delete mode 100644 tests/test.Dockerfile.dockerignore create mode 100644 tests/todo.ts diff --git a/.cargo/config.toml b/.cargo/config.toml index 6c8d827..53a1c12 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,3 +1,10 @@ [alias] xtask = "run --package xtask --" x = "run --package xtask --" + +[build] +rustflags = [ + # for use with tokio-rs/console + "--cfg", + "tokio_unstable" +] diff --git a/.ghjk/deno.lock b/.ghjk/deno.lock index fbcc951..8ec1e4b 100644 --- a/.ghjk/deno.lock +++ b/.ghjk/deno.lock @@ -1,93 +1,95 @@ { - "version": "3", - "packages": { - "specifiers": { - "jsr:@david/dax@0.41.0": "jsr:@david/dax@0.41.0", - "jsr:@david/which@^0.4.1": "jsr:@david/which@0.4.1", - "jsr:@std/assert@^0.221.0": "jsr:@std/assert@0.221.0", - "jsr:@std/bytes@^0.221.0": "jsr:@std/bytes@0.221.0", - "jsr:@std/fmt@^0.221.0": "jsr:@std/fmt@0.221.0", - "jsr:@std/fs@0.221.0": "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0": "jsr:@std/io@0.221.0", - "jsr:@std/io@^0.221.0": "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0": "jsr:@std/path@0.221.0", - "jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0": "jsr:@std/streams@0.221.0", - "npm:@noble/hashes@1.4.0": "npm:@noble/hashes@1.4.0", - "npm:multiformats@13.1.0": "npm:multiformats@13.1.0", - "npm:zod-validation-error@3.3.0": "npm:zod-validation-error@3.3.0_zod@3.23.8", - "npm:zod@3.23.8": "npm:zod@3.23.8" + "version": "4", + "specifiers": { + "jsr:@david/dax@0.41.0": "0.41.0", + "jsr:@david/which@~0.4.1": "0.4.1", + "jsr:@std/assert@0.221": "0.221.0", + "jsr:@std/bytes@0.221": "0.221.0", + "jsr:@std/fmt@0.221": "0.221.0", + "jsr:@std/fs@0.221.0": "0.221.0", + "jsr:@std/io@0.221": "0.221.0", + "jsr:@std/io@0.221.0": "0.221.0", + "jsr:@std/path@0.221": "0.221.0", + "jsr:@std/path@0.221.0": "0.221.0", + "jsr:@std/streams@0.221.0": "0.221.0", + "npm:@noble/hashes@1.4.0": "1.4.0", + "npm:multiformats@13.1.0": "13.1.0", + "npm:zod-validation-error@3.3.0": "3.3.0_zod@3.23.8", + "npm:zod-validation-error@3.4.0": "3.4.0_zod@3.23.8", + "npm:zod@3.23.8": "3.23.8" + }, + "jsr": { + "@david/dax@0.41.0": { + "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8", + "dependencies": [ + "jsr:@david/which", + "jsr:@std/fmt", + "jsr:@std/fs", + "jsr:@std/io@0.221.0", + "jsr:@std/path@0.221.0", + "jsr:@std/streams" + ] + }, + "@david/which@0.4.1": { + "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" + }, + "@std/assert@0.221.0": { + "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" + }, + "@std/bytes@0.221.0": { + "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" + }, + "@std/fmt@0.221.0": { + "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" + }, + "@std/fs@0.221.0": { + "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/path@0.221" + ] + }, + "@std/io@0.221.0": { + "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", + "dependencies": [ + "jsr:@std/assert", + "jsr:@std/bytes" + ] + }, + "@std/path@0.221.0": { + "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", + "dependencies": [ + "jsr:@std/assert" + ] + }, + "@std/streams@0.221.0": { + "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61", + "dependencies": [ + "jsr:@std/io@0.221" + ] + } + }, + "npm": { + "@noble/hashes@1.4.0": { + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" + }, + "multiformats@13.1.0": { + "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==" + }, + "zod-validation-error@3.3.0_zod@3.23.8": { + "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", + "dependencies": [ + "zod" + ] }, - "jsr": { - "@david/dax@0.41.0": { - "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8", - "dependencies": [ - "jsr:@david/which@^0.4.1", - "jsr:@std/fmt@^0.221.0", - "jsr:@std/fs@0.221.0", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams@0.221.0" - ] - }, - "@david/which@0.4.1": { - "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" - }, - "@std/assert@0.221.0": { - "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" - }, - "@std/bytes@0.221.0": { - "integrity": "64a047011cf833890a4a2ab7293ac55a1b4f5a050624ebc6a0159c357de91966" - }, - "@std/fmt@0.221.0": { - "integrity": "379fed69bdd9731110f26b9085aeb740606b20428ce6af31ef6bd45ef8efa62a" - }, - "@std/fs@0.221.0": { - "integrity": "028044450299de8ed5a716ade4e6d524399f035513b85913794f4e81f07da286", - "dependencies": [ - "jsr:@std/assert@^0.221.0", - "jsr:@std/path@^0.221.0" - ] - }, - "@std/io@0.221.0": { - "integrity": "faf7f8700d46ab527fa05cc6167f4b97701a06c413024431c6b4d207caa010da", - "dependencies": [ - "jsr:@std/assert@^0.221.0", - "jsr:@std/bytes@^0.221.0" - ] - }, - "@std/path@0.221.0": { - "integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095", - "dependencies": [ - "jsr:@std/assert@^0.221.0" - ] - }, - "@std/streams@0.221.0": { - "integrity": "47f2f74634b47449277c0ee79fe878da4424b66bd8975c032e3afdca88986e61", - "dependencies": [ - "jsr:@std/io@^0.221.0" - ] - } + "zod-validation-error@3.4.0_zod@3.23.8": { + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dependencies": [ + "zod" + ] }, - "npm": { - "@noble/hashes@1.4.0": { - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dependencies": {} - }, - "multiformats@13.1.0": { - "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==", - "dependencies": {} - }, - "zod-validation-error@3.3.0_zod@3.23.8": { - "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", - "dependencies": { - "zod": "zod@3.23.8" - } - }, - "zod@3.23.8": { - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dependencies": {} - } + "zod@3.23.8": { + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" } }, "remote": { @@ -394,145 +396,8 @@ "https://deno.land/x/foras@v2.1.4/wasm/pkg/foras.wasm.js": "2df8522df7243b0f05b1d188e220629cd5d2c92080a5f1407e15396fc35bebb3", "https://deno.land/x/json_hash@0.2.0/canon.ts": "ce7c07abd871cd7f0eb1280ad9f58f6382f02f84a217898ce977cf35ad315877", "https://deno.land/x/jszip@0.11.0/mod.ts": "5661ddc18e9ac9c07e3c5d2483bc912a7022b6af0d784bb7b05035973e640ba1", - "https://deno.land/x/zod@v3.23.8/ZodError.ts": "528da200fbe995157b9ae91498b103c4ef482217a5c086249507ac850bd78f52", - "https://deno.land/x/zod@v3.23.8/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", - "https://deno.land/x/zod@v3.23.8/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", - "https://deno.land/x/zod@v3.23.8/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", - "https://deno.land/x/zod@v3.23.8/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", - "https://deno.land/x/zod@v3.23.8/helpers/parseUtil.ts": "c14814d167cc286972b6e094df88d7d982572a08424b7cd50f862036b6fcaa77", - "https://deno.land/x/zod@v3.23.8/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7", - "https://deno.land/x/zod@v3.23.8/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", - "https://deno.land/x/zod@v3.23.8/helpers/util.ts": "30c273131661ca5dc973f2cfb196fa23caf3a43e224cdde7a683b72e101a31fc", - "https://deno.land/x/zod@v3.23.8/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268", - "https://deno.land/x/zod@v3.23.8/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c", - "https://deno.land/x/zod@v3.23.8/mod.ts": "ec6e2b1255c1a350b80188f97bd0a6bac45801bb46fc48f50b9763aa66046039", - "https://deno.land/x/zod@v3.23.8/types.ts": "1b172c90782b1eaa837100ebb6abd726d79d6c1ec336350c8e851e0fd706bf5c", "https://esm.sh/jszip@3.7.1": "f3872a819b015715edb05f81d973b5cd05d3d213d8eb28293ca5471fe7a71773", "https://esm.sh/v135/jszip@3.7.1/denonext/jszip.mjs": "d31d7f9e0de9c6db3c07ca93f7301b756273d4dccb41b600461978fc313504c9", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/deps/cli.ts": "aac025f9372ad413b9c2663dc7f61affd597820d9448f010a510d541df3b56ea", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/deps/common.ts": "f775710b66a9099b98651cd3831906466e9b83ef98f2e5c080fd59ee801c28d4", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/deps/ports.ts": "3c60d1f7ab626ffdd81b37f4e83a780910936480da8fe24f4ccceaefa207d339", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/files/deno/mod.ts": "1b8204c3df18b908408b2148b48af788e669d0debbeb8ba119418ab1ddf1ab8f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/files/deno/worker.ts": "8ded400d70a0bd40e281ceb1ffcdc82578443caf9c481b9eee77166472784282", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/host/mod.ts": "cc25d1f82e54e6a27eef4571145c3f34c4c8ad9148b3aa48bd3b53d1e078d95d", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/host/types.ts": "f450d9b9c0eced2650262d02455aa6f794de0edd6b052aade256882148e5697f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/install/mod.ts": "aa54eb3e119f28d33e61645c89669da292ee00376068ead8f45be2807e7a9989", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/install/utils.ts": "d4634d4fc0e963f540402b4ca7eb5dcba340eaa0d8fceb43af57d722ad267115", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/main.ts": "ecd5e83be2d8f351058ad44424cad1f36dd2e3d76f6e8409afc47682a9eff01a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/envs/inter.ts": "84805fa208754a08f185dca7a5236de3760bbc1d0df96af86ea5fd7778f827a2", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/envs/mod.ts": "5f37b9f155808f8d6d51e1f16f58c07914d8c7d8070bc5c2fb5076ab748798a7", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/envs/posix.ts": "09e410e3fea9c303a5148ff2a22697474320442b9fea0bd3fc932d6828fe820f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/envs/reducer.ts": "50517084caaf73ce6618141ee4d97795060a0d3169651da7abd7251a3204465a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/envs/types.ts": "ab9715cf02e9d73f553ae757db347863be23e1e9daf94d18aab716fc27b3dbc1", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/mod.ts": "fc1cb9176c6557b44ae9c6536fa51c6c4f80ac01fc476d15b0a217e70cb0d176", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/ambient.ts": "823ec8d98702a60e6bfcdbeb64b69dc9f5039e73a1f10e87cd51210c1aaf52d5", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/base.ts": "8ef8a8de372420bddcd63a1b363937f43d898059e99478a58621e8432bcd5891", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/db.ts": "a309d1058f66079a481141c3f1733d928b9af8a37b7ce911b1228f70fd24df0f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/ghrel.ts": "ebbc30a5c31244131d937eadca73fbc099c9e7bdf0ad4f668766d4388ede143c", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/inter.ts": "b3999e73d73d7f928a8de86e5e2261fe6b1450ceedfb54f24537bf0803532ed0", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/mod.ts": "78db7040e724f84c95b1a0fdeaf0cfc53382482e8905cd352189756b953556cc", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/reducers.ts": "d04e813652101f67f946242df68429ed5540e499fbdb7776b8be5703f16754c8", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/sync.ts": "a7a297f6b098360d56af168692f3cff96f8ceeb5189e5baa249e094f8d9c42ef", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/types.ts": "f4dbd1a3f4b7f539b3a85418617d25adbf710b54144161880d48f6c4ec032eee", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/types/platform.ts": "0ecffeda71919293f9ffdb6c564ddea4f23bc85c4e640b08ea78225d34387fdc", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/utils.ts": "6b14b331cce66bd46e7aec51f02424327d819150f16d3f72a6b0aaf7aee43c09", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/ports/worker.ts": "6b76ba1efb2e47a82582fc48bcc6264fe153a166beffccde1a9a3a185024c337", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/std.ts": "419d6b04680f73f7b252257ab287d68c1571cee4347301c53278e2b53df21c4a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/tasks/deno.ts": "2b9f33253ac1257eb79a4981cd221509aa9ecf8a3c36d7bd8be1cd6c1150100b", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/tasks/exec.ts": "6adcfe13f8d2da5d65331fd1601d4f950d9fc6f164bc9592204e5b08c23c5c30", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/tasks/inter.ts": "63e8f2860f7e3b4d95b6f61ca56aeb8567e4f265aa9c22cace6c8075edd6210f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/tasks/mod.ts": "334b18d7c110cc05483be96353e342425c0033b7410c271a8a47d2b18308c73e", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/tasks/types.ts": "072a34bd0749428bad4d612cc86abe463d4d4f74dc56cf0a48a1f41650e2399b", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/modules/types.ts": "c0f212b686a2721d076e9aeb127596c7cbc939758e2cc32fd1d165a8fb320a87", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/port.ts": "c039a010dee7dfd978478cf4c5e2256c643135e10f33c30a09f8db9915e9d89d", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/setup_logger.ts": "f8a206bda0595497d6f4718032d4a959000b32ef3346d4b507777eec6a169458", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/utils/logger.ts": "fcbafb35ae4b812412b9b301ce6d06b8b9798f94ebebe3f92677e25e4b19af3c", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/utils/mod.ts": "25bfdd222d6afec5b3f0a7e647e3d9b12abed6d222b49a4b2e95c6bbe266f533", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/utils/unarchive.ts": "f6d0e9e75f470eeef5aecd0089169f4350fc30ebfdc05466bb7b30042294d6d3", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/utils/url.ts": "e1ada6fd30fc796b8918c88456ea1b5bbd87a07d0a0538b092b91fd2bb9b7623", - "https://raw.githubusercontent.com/metatypedev/ghjk/0.2.0/utils/worker.ts": "ac4caf72a36d2e4af4f4e92f2e0a95f9fc2324b568640f24c7c2ff6dc0c11d62", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/deps/cli.ts": "22fdbfe7f39dc2caa9dd056a57a57051deec6b2a7ba9381e20e2ce7ab6af07e1", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/deps/common.ts": "5d676e006bb1485056935c263a967eee9fcfc1517249d1ca05a7645dca5e2e68", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/deps/ports.ts": "3c60d1f7ab626ffdd81b37f4e83a780910936480da8fe24f4ccceaefa207d339", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/files/deno/mod.ts": "1b8204c3df18b908408b2148b48af788e669d0debbeb8ba119418ab1ddf1ab8f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/files/deno/worker.ts": "71f3cee9dba3c2bd59c85d2909eac325da556a9917ed6ea01222f6c217638dd9", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/host/mod.ts": "faea10bf051dc22443e0bb3cadb74599d2ef5e4543f065a75777bb57b818c022", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/host/types.ts": "359ceb8a800c5acd9ef4778e40ccfe039fd7724c06205ae3998398641a9b2370", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/install/mod.ts": "f78083efd15e82c8cc302dd801565f39c947497cfaa039fde1023f7e0d5ab368", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/install/utils.ts": "d4634d4fc0e963f540402b4ca7eb5dcba340eaa0d8fceb43af57d722ad267115", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/main.ts": "fb82696926c97ea6749151275cafce049c35c2d500188661ac8b1d205a3b9939", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/envs/mod.ts": "33ddee364795c1f22028e74071063fe85211949682bb94f1ca38396314cbd01e", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/envs/posix.ts": "3193141953de1bfe2d73549e651711f4e1a1d05f5fcc7655ab74160b25be09d0", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/envs/reducer.ts": "853347377f4b265792da2ece78dfde7602c2555341bbd9f8dfd7ac5fd7d989ad", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/envs/types.ts": "a03173fe013a41163471446f41c636bd23acc6e4956ea910e12cb203dc449a9e", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/mod.ts": "fc1cb9176c6557b44ae9c6536fa51c6c4f80ac01fc476d15b0a217e70cb0d176", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/ambient.ts": "823ec8d98702a60e6bfcdbeb64b69dc9f5039e73a1f10e87cd51210c1aaf52d5", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/base.ts": "8ef8a8de372420bddcd63a1b363937f43d898059e99478a58621e8432bcd5891", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/db.ts": "a309d1058f66079a481141c3f1733d928b9af8a37b7ce911b1228f70fd24df0f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/ghrel.ts": "a1bf0e244080b8b2a62093f536bb7eff0b5a9c596f7eef9f516c11a80aad0be1", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/inter.ts": "62ddc0dede33b059dbd84d18411d0b0acceb145ff96b076401a96c980ae9bfc0", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/mod.ts": "6d4b907ad70a9946299bc5931c976fad1cb1b405466cf4cc8d2acb7d0ba3310c", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/reducers.ts": "eaabbc2cf5d16a55cff5b3f95180f3e1ddb09b1a755776da2931f8817f28a0df", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/sync.ts": "6bbaca38024fd1f6c6ba5811abe65052d2061527539f1893f768ace40016ab5f", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/types.ts": "1adbe5a901f765de106db6513eb770356eed156c435e94d51b7432dce401530e", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/types/platform.ts": "0ecffeda71919293f9ffdb6c564ddea4f23bc85c4e640b08ea78225d34387fdc", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/utils.ts": "6b14b331cce66bd46e7aec51f02424327d819150f16d3f72a6b0aaf7aee43c09", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/ports/worker.ts": "6b76ba1efb2e47a82582fc48bcc6264fe153a166beffccde1a9a3a185024c337", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/std.ts": "419d6b04680f73f7b252257ab287d68c1571cee4347301c53278e2b53df21c4a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/tasks/deno.ts": "15d5bb6379f3add73cb0d8aa4b578998d87bcfaa939518166c30a7f906ea5750", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/tasks/exec.ts": "cc5db628d85a84b6193f59d7f5d98868f22a59f038716dc3d4fc5ac70494d625", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/tasks/mod.ts": "71a16751895ce8bb687c565602938773ac276ccb62d28a793db0b1715438ee9a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/tasks/types.ts": "0bf2cf9ac1f5735dc95ac348175866abf602bd90d01c9275c708f767baa976c1", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/types.ts": "53de8906ea0149871e35c937f3e52dee1a615907971fa8ec3f322f4dfe6d40f3", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/modules/utils.ts": "b5866a52cd4e0e1c0dc8ccb56c7281aeff2e2bf5e16866b77eda36e0529e312a", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/port.ts": "c039a010dee7dfd978478cf4c5e2256c643135e10f33c30a09f8db9915e9d89d", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/setup_logger.ts": "f8a206bda0595497d6f4718032d4a959000b32ef3346d4b507777eec6a169458", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/utils/logger.ts": "fcbafb35ae4b812412b9b301ce6d06b8b9798f94ebebe3f92677e25e4b19af3c", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/utils/mod.ts": "d4d0c0198168f63bd084872bf7dfb40925301ecb65fd0501520db942f6c0c961", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/utils/unarchive.ts": "f6d0e9e75f470eeef5aecd0089169f4350fc30ebfdc05466bb7b30042294d6d3", - "https://raw.githubusercontent.com/metatypedev/ghjk/0c5f78/utils/url.ts": "e1ada6fd30fc796b8918c88456ea1b5bbd87a07d0a0538b092b91fd2bb9b7623", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/deps/cli.ts": "aac025f9372ad413b9c2663dc7f61affd597820d9448f010a510d541df3b56ea", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/deps/common.ts": "f775710b66a9099b98651cd3831906466e9b83ef98f2e5c080fd59ee801c28d4", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/deps/ports.ts": "3c60d1f7ab626ffdd81b37f4e83a780910936480da8fe24f4ccceaefa207d339", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/files/deno/mod.ts": "1b8204c3df18b908408b2148b48af788e669d0debbeb8ba119418ab1ddf1ab8f", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/files/deno/worker.ts": "8ded400d70a0bd40e281ceb1ffcdc82578443caf9c481b9eee77166472784282", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/host/mod.ts": "604e2729145c16226af91e6880e3eca30ea060688fb4941ab39d9489109dd62c", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/host/types.ts": "f450d9b9c0eced2650262d02455aa6f794de0edd6b052aade256882148e5697f", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/install/mod.ts": "f78083efd15e82c8cc302dd801565f39c947497cfaa039fde1023f7e0d5ab368", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/install/utils.ts": "d4634d4fc0e963f540402b4ca7eb5dcba340eaa0d8fceb43af57d722ad267115", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/main.ts": "21ea4582db19e163f4dd68ccdb19578c3c48e48dd23c094d8f8f88ab785e34e5", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/envs/inter.ts": "84805fa208754a08f185dca7a5236de3760bbc1d0df96af86ea5fd7778f827a2", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/envs/mod.ts": "b9483be6dbd4c282d1c5b134864b2ff0f53d8bfb25dba6c96e591c84ccf25e01", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/envs/posix.ts": "09e410e3fea9c303a5148ff2a22697474320442b9fea0bd3fc932d6828fe820f", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/envs/reducer.ts": "853347377f4b265792da2ece78dfde7602c2555341bbd9f8dfd7ac5fd7d989ad", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/envs/types.ts": "ab9715cf02e9d73f553ae757db347863be23e1e9daf94d18aab716fc27b3dbc1", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/mod.ts": "fc1cb9176c6557b44ae9c6536fa51c6c4f80ac01fc476d15b0a217e70cb0d176", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/ambient.ts": "823ec8d98702a60e6bfcdbeb64b69dc9f5039e73a1f10e87cd51210c1aaf52d5", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/base.ts": "8ef8a8de372420bddcd63a1b363937f43d898059e99478a58621e8432bcd5891", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/db.ts": "a309d1058f66079a481141c3f1733d928b9af8a37b7ce911b1228f70fd24df0f", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/ghrel.ts": "a1bf0e244080b8b2a62093f536bb7eff0b5a9c596f7eef9f516c11a80aad0be1", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/inter.ts": "b3999e73d73d7f928a8de86e5e2261fe6b1450ceedfb54f24537bf0803532ed0", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/mod.ts": "2b5d4773d64641cdc0aacf09ece6c40d094feb090280647c68f33bbfa8dceee7", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/reducers.ts": "eaabbc2cf5d16a55cff5b3f95180f3e1ddb09b1a755776da2931f8817f28a0df", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/sync.ts": "a7a297f6b098360d56af168692f3cff96f8ceeb5189e5baa249e094f8d9c42ef", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/types.ts": "f4dbd1a3f4b7f539b3a85418617d25adbf710b54144161880d48f6c4ec032eee", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/types/platform.ts": "0ecffeda71919293f9ffdb6c564ddea4f23bc85c4e640b08ea78225d34387fdc", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/utils.ts": "6b14b331cce66bd46e7aec51f02424327d819150f16d3f72a6b0aaf7aee43c09", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/ports/worker.ts": "6b76ba1efb2e47a82582fc48bcc6264fe153a166beffccde1a9a3a185024c337", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/std.ts": "419d6b04680f73f7b252257ab287d68c1571cee4347301c53278e2b53df21c4a", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/tasks/deno.ts": "2b9f33253ac1257eb79a4981cd221509aa9ecf8a3c36d7bd8be1cd6c1150100b", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/tasks/exec.ts": "eaf6b2f9639185fa76f560276e0d28d262a6c78d2bdc0d579e7683e062d7b542", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/tasks/inter.ts": "63e8f2860f7e3b4d95b6f61ca56aeb8567e4f265aa9c22cace6c8075edd6210f", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/tasks/mod.ts": "438f1cbb5e96470f380b6954bb18ad7693ed33bb99314137ff7080d82d026615", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/tasks/types.ts": "072a34bd0749428bad4d612cc86abe463d4d4f74dc56cf0a48a1f41650e2399b", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/modules/types.ts": "c0f212b686a2721d076e9aeb127596c7cbc939758e2cc32fd1d165a8fb320a87", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/port.ts": "c039a010dee7dfd978478cf4c5e2256c643135e10f33c30a09f8db9915e9d89d", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/setup_logger.ts": "f8a206bda0595497d6f4718032d4a959000b32ef3346d4b507777eec6a169458", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/utils/logger.ts": "fcbafb35ae4b812412b9b301ce6d06b8b9798f94ebebe3f92677e25e4b19af3c", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/utils/mod.ts": "fe8b14465fbcbf3a952af48083a17304c294f296591752dff3ca141386c2d46b", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/utils/unarchive.ts": "f6d0e9e75f470eeef5aecd0089169f4350fc30ebfdc05466bb7b30042294d6d3", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/utils/url.ts": "e1ada6fd30fc796b8918c88456ea1b5bbd87a07d0a0538b092b91fd2bb9b7623", - "https://raw.githubusercontent.com/metatypedev/ghjk/5bb0d24/utils/worker.ts": "ac4caf72a36d2e4af4f4e92f2e0a95f9fc2324b568640f24c7c2ff6dc0c11d62", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/deps/cli.ts": "aac025f9372ad413b9c2663dc7f61affd597820d9448f010a510d541df3b56ea", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/deps/common.ts": "f775710b66a9099b98651cd3831906466e9b83ef98f2e5c080fd59ee801c28d4", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/deps/ports.ts": "3c60d1f7ab626ffdd81b37f4e83a780910936480da8fe24f4ccceaefa207d339", @@ -570,6 +435,7 @@ "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/modules/types.ts": "c0f212b686a2721d076e9aeb127596c7cbc939758e2cc32fd1d165a8fb320a87", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/port.ts": "c039a010dee7dfd978478cf4c5e2256c643135e10f33c30a09f8db9915e9d89d", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/ports/act.ts": "2ce6b8fddf61db12ba69b7cad6985237a2962ca79853edbddee5bfb49c47d1ab", + "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/ports/deno_ghrel.ts": "eca02a93ceb62ad9fb7f395361d32da0d5657aba5f7856c8ae0109135da0e070", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/setup_logger.ts": "f8a206bda0595497d6f4718032d4a959000b32ef3346d4b507777eec6a169458", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/utils/logger.ts": "fcbafb35ae4b812412b9b301ce6d06b8b9798f94ebebe3f92677e25e4b19af3c", "https://raw.githubusercontent.com/metatypedev/ghjk/v0.2.1/utils/mod.ts": "25901b5a03625353cc0d9c024daca806eb2513b153faede5ecad73b428542721", diff --git a/.ghjk/lock.json b/.ghjk/lock.json index 410bbd9..7411cce 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -1,7 +1,6 @@ { "version": "0", - "platform": "x86_64-linux", - "moduleEntries": { + "sys_entries": { "ports": { "version": "0", "configResolutions": { @@ -15,7 +14,7 @@ "version": "4.0.1", "buildDepConfigs": { "cpy_bs_ghrel": { - "version": "3.12.7", + "version": "3.13.1", "buildDepConfigs": { "tar_aa": { "version": "1.35", @@ -39,7 +38,7 @@ "specifiedVersion": false }, "bciqh4dfyevkzzvmnhuz7lcfqttkg5neg4ewhoxzofyuicavgk6pb7ia": { - "version": "3.12.7", + "version": "3.13.1", "buildDepConfigs": { "tar_aa": { "version": "1.35", @@ -73,7 +72,7 @@ "version": "3.9.0.0", "buildDepConfigs": { "cpy_bs_ghrel": { - "version": "3.12.7", + "version": "3.13.1", "buildDepConfigs": { "tar_aa": { "version": "1.35", @@ -118,7 +117,7 @@ "version": "3.31.0.1", "buildDepConfigs": { "cpy_bs_ghrel": { - "version": "3.12.7", + "version": "3.13.1", "buildDepConfigs": { "tar_aa": { "version": "1.35", @@ -248,6 +247,74 @@ "rust-src" ], "specifiedVersion": true + }, + "bciqeosxosr6ur7pu7gny33gy7dqubmxbcs4775xazb4zvaxavkd5rha": { + "version": "0.1.13", + "buildDepConfigs": { + "cargo_binstall_ghrel": { + "version": "v1.10.17", + "buildDepConfigs": {}, + "portRef": "cargo_binstall_ghrel@0.1.0", + "specifiedVersion": false + }, + "rust_rustup": { + "version": "1.83.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "minimal", + "specifiedVersion": false + } + }, + "portRef": "cargobi_cratesio@0.1.0", + "crateName": "tokio-console", + "specifiedVersion": false + }, + "bciqeal5okt5zj763vhgsmf3afr5thrkqaitv6pb3wwegcwyb74gdyjq": { + "version": "v1.10.17", + "buildDepConfigs": {}, + "portRef": "cargo_binstall_ghrel@0.1.0", + "specifiedVersion": false + }, + "bciqeub366wrduva4y3rxegdjkhlebwsud56e5orgcpbkdrbhuxmvuxa": { + "version": "1.83.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.0", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "minimal", + "specifiedVersion": false + }, + "bciqe7g5m4v5jkg3ubqhogjjntsduyrwxcirqcp6tc3jmjr5af7ojq6a": { + "version": "v2.1.2", + "buildDepConfigs": {}, + "portRef": "deno_ghrel@0.1.0", + "specifiedVersion": true } } }, @@ -269,9 +336,9 @@ "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", - "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq" + "bciqelae2kzmf7umbo62flzq2mnlhnc4ilbfmn4va2fzrqwx7w7zusji" ], - "allowedBuildDeps": "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq" + "allowedBuildDeps": "bciqdg64uhkvlkqyc7nli33cja3aolbcdr75qepnrhj5ojlifsvxqzgq" }, "ghjkEnvProvInstSet____rust": { "installs": [ @@ -281,12 +348,13 @@ "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", - "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq" + "bciqelae2kzmf7umbo62flzq2mnlhnc4ilbfmn4va2fzrqwx7w7zusji" ], - "allowedBuildDeps": "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq" + "allowedBuildDeps": "bciqdg64uhkvlkqyc7nli33cja3aolbcdr75qepnrhj5ojlifsvxqzgq" }, "ghjkEnvProvInstSet___dev": { "installs": [ + "bciqlfx3mm5hi37g75snjknph6fkniixjhnvyyfxeua7f5z4h7nnqtna", "bciqlmoqot4jk2lb2b34pldr5iiwsfm3biuipzesjkkwmc2n2o6nlw4q", "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", @@ -294,9 +362,13 @@ "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", - "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq" + "bciqelae2kzmf7umbo62flzq2mnlhnc4ilbfmn4va2fzrqwx7w7zusji" ], - "allowedBuildDeps": "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq" + "allowedBuildDeps": "bciqdg64uhkvlkqyc7nli33cja3aolbcdr75qepnrhj5ojlifsvxqzgq" + }, + "ghjkEnvProvInstSet_______task_env_cache-v8": { + "installs": [], + "allowedBuildDeps": "bciqeie3punk3gz4kcfdk2fxx5bsj5fh3j7bb7z36qmimayhwdsvp7cq" } } } @@ -308,13 +380,13 @@ "lock-sed": { "ty": "denoFile@v1", "key": "lock-sed", - "envKey": "bciqlneazfye2nq2cb4jsgigjqisrzm25gdkyitmotyl3qmq5nf3nb7y" + "envKey": "bciqocjamyeiuh6llwcdqg4q4ceantuzpbm5bmnlz7pkqz4r2ca7w2eq" }, "cache-v8": { "ty": "denoFile@v1", "key": "cache-v8", "desc": "Install the V8 builds to a local cache.", - "envKey": "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny" + "envKey": "bciqngtgh6vxbmug3jgfhtc6t2o7d4375gzfwxca2hmq2mhwbe4tajvq" } }, "tasksNamed": [ @@ -327,13 +399,21 @@ "id": "envs", "config": { "envs": { - "bciqazjf2gsxfy4wt2gd6qsou4pciedy7dyhdch5l7gsmoq62boo2s7a": { + "bciqngtgh6vxbmug3jgfhtc6t2o7d4375gzfwxca2hmq2mhwbe4tajvq": { + "provides": [ + { + "ty": "ghjk.ports.InstallSetRef", + "setId": "ghjkEnvProvInstSet_______task_env_cache-v8" + } + ] + }, + "bciqfnku2tswsz4gapwhys5ox5uiyzcb5r7bmuwzljjeziljcu7efroi": { "desc": "the default default environment.", "provides": [ { "ty": "posix.envVar", "key": "RUST_LOG", - "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + "val": "info,deno::npm=info,deno::file_fetcher=info,swc_ecma_transforms_base=info,swc_common=info,h2=info,rustls=info,mio=info,hyper_util=info" }, { "ty": "ghjk.ports.InstallSetRef", @@ -341,12 +421,12 @@ } ] }, - "bciqlneazfye2nq2cb4jsgigjqisrzm25gdkyitmotyl3qmq5nf3nb7y": { + "bciqocjamyeiuh6llwcdqg4q4ceantuzpbm5bmnlz7pkqz4r2ca7w2eq": { "provides": [ { "ty": "posix.envVar", "key": "RUST_LOG", - "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + "val": "info,deno::npm=info,deno::file_fetcher=info,swc_ecma_transforms_base=info,swc_common=info,h2=info,rustls=info,mio=info,hyper_util=info" }, { "ty": "ghjk.ports.InstallSetRef", @@ -354,12 +434,12 @@ } ] }, - "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny": { + "bciqex5g2cetqvfipwhu6fb3mmyke3y6jvrscjrykf2zl7wfwupiqhca": { "provides": [ { "ty": "posix.envVar", "key": "RUST_LOG", - "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + "val": "info,deno::npm=info,deno::file_fetcher=info,swc_ecma_transforms_base=info,swc_common=info,h2=info,rustls=info,mio=info,hyper_util=info" }, { "ty": "ghjk.ports.InstallSetRef", @@ -367,17 +447,17 @@ } ] }, - "bciqe26fbb6fkfbou7w3rf3t2uqw4neldvakclhcecktgtpcuxwnzgja": { + "bciqnerbswitlqt27ado74puxt3faxea6jaxe4wvytnzwjpupig25kky": { "provides": [ { "ty": "posix.envVar", "key": "RUST_LOG", - "val": "trace,deno=info,denort=trace,swc_ecma_transforms_base=info" + "val": "info,deno::npm=info,deno::file_fetcher=info,swc_ecma_transforms_base=info,swc_common=info,h2=info,rustls=info,mio=info,hyper_util=info" }, { "ty": "posix.envVar", "key": "RUSTY_V8_MIRROR", - "val": "/home/asdf/repos/ecma/ghjk/.dev/rusty_v8" + "val": "/home/yohe/ghjk/.dev/rusty_v8" }, { "ty": "ghjk.ports.InstallSetRef", @@ -388,9 +468,9 @@ }, "defaultEnv": "dev", "envsNamed": { - "main": "bciqazjf2gsxfy4wt2gd6qsou4pciedy7dyhdch5l7gsmoq62boo2s7a", - "_rust": "bciqe5yq32fnpsioc326yny37wl3jszc6sgq3imo6544ez7iswpu3yny", - "dev": "bciqe26fbb6fkfbou7w3rf3t2uqw4neldvakclhcecktgtpcuxwnzgja" + "main": "bciqfnku2tswsz4gapwhys5ox5uiyzcb5r7bmuwzljjeziljcu7efroi", + "_rust": "bciqex5g2cetqvfipwhu6fb3mmyke3y6jvrscjrykf2zl7wfwupiqhca", + "dev": "bciqnerbswitlqt27ado74puxt3faxea6jaxe4wvytnzwjpupig25kky" } } } @@ -480,8 +560,8 @@ }, "packageName": "vale" }, - "bciqpy7sxlin5fqcbsl7vildckib5p65mei4qxya2fsbgvi2pqt3jimq": { - "version": "2.0.6", + "bciqelae2kzmf7umbo62flzq2mnlhnc4ilbfmn4va2fzrqwx7w7zusji": { + "version": "2.1.2", "port": { "ty": "denoWorker@v1", "name": "deno_ghrel", @@ -497,7 +577,7 @@ "moduleSpecifier": "file:///ports/deno_ghrel.ts" } }, - "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq": { + "bciqdfarczmlu3r5dkvcdoultfbnuvn6saao55h4fbb3jg72kv6mkr3y": { "manifest": { "ty": "denoWorker@v1", "name": "cpy_bs_ghrel", @@ -521,10 +601,51 @@ "moduleSpecifier": "file:///ports/cpy_bs.ts" }, "defaultInst": { - "version": "3.12.7", + "version": "3.13.1", "portRef": "cpy_bs_ghrel@0.1.0" } }, + "bciqgze4knhjfbiypt5axkjslfsduq6tbwszbiuy5zsgpacrm5h6cg4a": { + "manifest": { + "ty": "denoWorker@v1", + "name": "rust_rustup", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin", + "x86_64-windows", + "aarch64-windows", + "x86_64-freebsd", + "aarch64-freebsd", + "x86_64-netbsd", + "aarch64-netbsd", + "x86_64-aix", + "aarch64-aix", + "x86_64-solaris", + "aarch64-solaris", + "x86_64-illumos", + "aarch64-illumos", + "x86_64-android", + "aarch64-android" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "rustup_rustlang" + } + ], + "moduleSpecifier": "file:///ports/rust.ts" + }, + "defaultInst": { + "version": "1.82.0", + "portRef": "rust_rustup@0.1.0", + "profile": "default", + "components": [ + "rust-src" + ] + } + }, "bciqb6ua63xodzwxngnbjq35hfikiwzb3dclbqkc7e6xgjdt5jin4pia": { "manifest": { "ty": "ambientAccess@v1", @@ -727,43 +848,6 @@ "portRef": "node_org@0.1.0" } }, - "bciqhjmjvlo4aqvwxjkrmoiledobmhkfe7iovqe3wndxiw2aootwn4lq": { - "manifest": { - "ty": "denoWorker@v1", - "name": "rust_rustup", - "platforms": [ - "x86_64-linux", - "aarch64-linux", - "x86_64-darwin", - "aarch64-darwin", - "x86_64-windows", - "aarch64-windows", - "x86_64-freebsd", - "aarch64-freebsd", - "x86_64-netbsd", - "aarch64-netbsd", - "x86_64-aix", - "aarch64-aix", - "x86_64-solaris", - "aarch64-solaris", - "x86_64-illumos", - "aarch64-illumos", - "x86_64-android", - "aarch64-android" - ], - "version": "0.1.0", - "buildDeps": [ - { - "name": "rustup_rustlang" - } - ], - "moduleSpecifier": "file:///ports/rust.ts" - }, - "defaultInst": { - "portRef": "rust_rustup@0.1.0", - "profile": "minimal" - } - }, "bciqoxx4uhfhw77sux6kzqhy6bvxhxkk4cqigrxdrmggillzkfjgjnli": { "manifest": { "ty": "denoWorker@v1", @@ -793,8 +877,9 @@ "portRef": "asdf_plugin_git@0.1.0" } }, - "bciqoo3t36t4pphdox5wa5ugn34wkar7rwkqgb5l55lwnxbuabcc3nyq": { - "cpy_bs_ghrel": "bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq", + "bciqdg64uhkvlkqyc7nli33cja3aolbcdr75qepnrhj5ojlifsvxqzgq": { + "cpy_bs_ghrel": "bciqdfarczmlu3r5dkvcdoultfbnuvn6saao55h4fbb3jg72kv6mkr3y", + "rust_rustup": "bciqgze4knhjfbiypt5axkjslfsduq6tbwszbiuy5zsgpacrm5h6cg4a", "tar_aa": "bciqb6ua63xodzwxngnbjq35hfikiwzb3dclbqkc7e6xgjdt5jin4pia", "git_aa": "bciqfl5s36w335ducrb6f6gwb3vuwup7vzqwwg67pq42xtkngsnxqobi", "curl_aa": "bciqcfe7qyxmokpn6pgtaj35r5qg74jkehuu6cvyrtcsnegvwlm64oqy", @@ -803,7 +888,6 @@ "rustup_rustlang": "bciqk4ivbyqvpxwcaj5reufmveqldiizo6xmqiqq7njtaczgappydoka", "cargo_binstall_ghrel": "bciqpgt5wsiw4y7qzovqbt2yrdgq5mvhhjpcg6cxzt4w4taudyen44ca", "node_org": "bciqboouqnp54fnumgxvl7uay2k6ho4vhlbibvgoyyt5yt3rkwqaohzi", - "rust_rustup": "bciqhjmjvlo4aqvwxjkrmoiledobmhkfe7iovqe3wndxiw2aootwn4lq", "asdf_plugin_git": "bciqoxx4uhfhw77sux6kzqhy6bvxhxkk4cqigrxdrmggillzkfjgjnli" }, "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa": { @@ -892,6 +976,43 @@ "rust-src" ] }, + "bciqlfx3mm5hi37g75snjknph6fkniixjhnvyyfxeua7f5z4h7nnqtna": { + "port": { + "ty": "denoWorker@v1", + "name": "cargobi_cratesio", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin", + "x86_64-windows", + "aarch64-windows", + "x86_64-freebsd", + "aarch64-freebsd", + "x86_64-netbsd", + "aarch64-netbsd", + "x86_64-aix", + "aarch64-aix", + "x86_64-solaris", + "aarch64-solaris", + "x86_64-illumos", + "aarch64-illumos", + "x86_64-android", + "aarch64-android" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "cargo_binstall_ghrel" + }, + { + "name": "rust_rustup" + } + ], + "moduleSpecifier": "file:///ports/cargobi.ts" + }, + "crateName": "tokio-console" + }, "bciqlmoqot4jk2lb2b34pldr5iiwsfm3biuipzesjkkwmc2n2o6nlw4q": { "version": "v2.4.0", "port": { @@ -910,7 +1031,8 @@ "moduleSpecifier": "file:///ports/mold.ts" }, "replaceLd": true - } + }, + "bciqeie3punk3gz4kcfdk2fxx5bsj5fh3j7bb7z36qmimayhwdsvp7cq": {} } } -} +} \ No newline at end of file diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2466d31..0380726 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: env: - DENO_VERSION: "2.0.6" + DENO_VERSION: "2.1.2" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GHJK_LOG_PANIC_LEVEL: error DENO_DIR: .deno-dir diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6f33085..51aed6c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,3 +1,5 @@ +name: test suite +run-name: test suite for ${{ github.event.pull_request.title || github.ref }} on: push: branches: @@ -8,14 +10,16 @@ on: - synchronize - ready_for_review +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: - DENO_VERSION: "2.0.6" + DENO_VERSION: "2.1.2" GHJK_LOG: debug GHJK_LOG_PANIC_LEVEL: error DENO_DIR: .deno-dir GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # removing the images after every test is unncessary - DOCKER_NO_RMI: 1 jobs: changes: @@ -26,9 +30,11 @@ jobs: - uses: actions/checkout@v4 test-pre-commit: + timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: dsherret/rust-toolchain-file@v1 - uses: denoland/setup-deno@v1 with: deno-version: ${{ env.DENO_VERSION }} @@ -36,12 +42,13 @@ jobs: # pre commit runs ghjk. We'll always see changes # to lock.json since GITHUB_TOKEN is different # in the CI - - run: deno run --unstable -A main.ts print config + - run: deno task self envs cook -t lock-sed - uses: pre-commit/action@v3.0.1 env: SKIP: ghjk-resolve test-e2e: + timeout-minutes: 60 runs-on: "${{ matrix.os }}" strategy: fail-fast: false @@ -49,22 +56,16 @@ jobs: include: - os: ubuntu-latest platform: linux/x86_64 - e2eType: "local" - os: custom-arm platform: linux/aarch64 - e2eType: "local" - os: macos-latest platform: darwin/x86_64 - e2eType: "local" - os: macos-14 platform: darwin/aarch64 - e2eType: "local" # - os: windows-latest - # e2eType: "local" - env: - GHJK_TEST_E2E_TYPE: ${{ matrix.e2eType }} steps: - uses: actions/checkout@v4 + - uses: dsherret/rust-toolchain-file@v1 - uses: denoland/setup-deno@v1 with: deno-version: ${{ env.DENO_VERSION }} @@ -73,24 +74,23 @@ jobs: with: path: ${{ env.DENO_DIR }} key: deno-${{ hashFiles('**/deno.lock') }} - - if: "${{ matrix.e2eType == 'docker' }}" - uses: docker/setup-buildx-action@v3 - if: "${{ matrix.os == 'ubuntu-latest' || matrix.os == 'custom-arm' }}" + # need coreutils on max for the `timeout` command + # need cmake to build the rust deps run: | - # we need coreutils on max for the `timeout` command sudo apt update - sudo apt install -y --no-install-recommends fish zsh + sudo apt install -y --no-install-recommends fish zsh cmake - if: "${{ matrix.os == 'macos-latest' || matrix.os == 'macos-14' }}" - # we need coreutils on max for the `timeout` command - run: brew install fish zsh coreutils - - env: - DOCKER_PLATFORM: ${{ matrix.platform }} - run: deno task test + # need cmake to build the rust deps + # need coreutils on max for the `timeout` command + run: brew install fish zsh coreutils cmake + - run: deno task test test-action: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: dsherret/rust-toolchain-file@v1 - uses: metatypedev/setup-ghjk@318209a9d215f70716a4ac89dbeb9653a2deb8bc with: installer-url: ./install.ts diff --git a/.gitignore b/.gitignore index ffa470c..269d8a0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ deno.land jsr.io esm.sh +src/play/*.rs + # Added by cargo /target diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f92f43a..a0766cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -70,7 +70,6 @@ repos: rev: v1.0 hooks: - id: fmt - exclude: tests/metagen/typegraphs/sample/rs/client.rs - id: clippy args: - "--locked" diff --git a/Cargo.lock b/Cargo.lock index 421172d..622add8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,6 +354,59 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "axum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" + [[package]] name = "backtrace" version = "0.3.71" @@ -438,25 +491,22 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.5" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.10.5", - "lazy_static", - "lazycell", + "itertools 0.13.0", "log", - "prettyplease 0.2.25", + "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn 2.0.87", - "which 4.4.2", ] [[package]] @@ -534,6 +584,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "boxed_error" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d4f95e880cfd28c4ca5a006cf7f6af52b4bcb7b5866f573b2faa126fb7affb" +dependencies = [ + "quote", + "syn 2.0.87", +] + [[package]] name = "brotli" version = "6.0.0" @@ -836,9 +896,9 @@ checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "comrak" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c93ab3577cca16b4a1d80a88c2e0cd8b6e969e51696f0bbb0d1dcb0157109832" +checksum = "d8c32ff8b21372fab0e9ecc4e42536055702dc5faa418362bffd1544f9d12637" dependencies = [ "caseless", "derive_builder", @@ -851,6 +911,72 @@ dependencies = [ "unicode_categories", ] +[[package]] +name = "config" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" +dependencies = [ + "async-trait", + "json5", + "nom 7.1.3", + "pathdiff", + "serde", + "serde_json", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "console-api" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8030735ecb0d128428b64cd379809817e620a40e5001c54465b99ec5feec2857" +dependencies = [ + "futures-core", + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6539aa9c6a4cd31f4b1c040f860a1eac9aa80e7df6b05d506a6e7179936d6a01" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures-task", + "hdrhistogram", + "humantime", + "hyper-util", + "prost", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "console_static_text" version = "0.8.1" @@ -1188,8 +1314,8 @@ dependencies = [ [[package]] name = "deno" -version = "2.0.6" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "2.1.2" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "anstream", "async-trait", @@ -1220,6 +1346,7 @@ dependencies = [ "deno_runtime", "deno_semver", "deno_task_shell", + "deno_telemetry", "deno_terminal 0.2.0", "deno_tower_lsp", "dissimilar", @@ -1240,7 +1367,7 @@ dependencies = [ "http-body-util", "hyper-util", "import_map", - "indexmap", + "indexmap 2.6.0", "jsonc-parser", "junction", "lazy-regex", @@ -1276,6 +1403,7 @@ dependencies = [ "sha2", "shell-escape", "spki", + "sqlformat", "strsim", "tar", "tempfile", @@ -1354,8 +1482,8 @@ dependencies = [ [[package]] name = "deno_broadcast_channel" -version = "0.171.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.174.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-trait", "deno_core", @@ -1366,8 +1494,8 @@ dependencies = [ [[package]] name = "deno_cache" -version = "0.109.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.112.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-trait", "deno_core", @@ -1387,7 +1515,7 @@ dependencies = [ "base32", "deno_media_type", "deno_path_util", - "indexmap", + "indexmap 2.6.0", "log", "once_cell", "parking_lot", @@ -1400,8 +1528,8 @@ dependencies = [ [[package]] name = "deno_canvas" -version = "0.46.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.49.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_webgpu", @@ -1412,9 +1540,9 @@ dependencies = [ [[package]] name = "deno_config" -version = "0.38.2" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966825073480a6ac7e01977a3879d13edc8d6ea2d65ea164b37156a5fb206e9a" +checksum = "38fb809500238be2b10eee42944a47b3ac38974e1edbb47f73afcfca7df143bf" dependencies = [ "anyhow", "deno_package_json", @@ -1423,7 +1551,7 @@ dependencies = [ "glob", "ignore", "import_map", - "indexmap", + "indexmap 2.6.0", "jsonc-parser", "log", "percent-encoding", @@ -1436,19 +1564,20 @@ dependencies = [ [[package]] name = "deno_console" -version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.180.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", ] [[package]] name = "deno_core" -version = "0.318.0" +version = "0.323.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cae2393219ff9278123f7b24799cdfab37c7d6561b69ca06ced115cac92111" +checksum = "a781bcfe1b5211b8497f45bf5b3dba73036b8d5d1533c1f05d26ccf0afb25a78" dependencies = [ "anyhow", + "az", "bincode", "bit-set", "bit-vec", @@ -1458,6 +1587,7 @@ dependencies = [ "deno_ops", "deno_unsync", "futures", + "indexmap 2.6.0", "libc", "memoffset", "parking_lot", @@ -1472,18 +1602,19 @@ dependencies = [ "tokio", "url", "v8", + "wasm_dep_analyzer", ] [[package]] name = "deno_core_icudata" -version = "0.0.73" +version = "0.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13951ea98c0a4c372f162d669193b4c9d991512de9f2381dd161027f34b26b1" +checksum = "fe4dccb6147bb3f3ba0c7a48e993bfeb999d2c2e47a81badee80e2b370c8d695" [[package]] name = "deno_cron" -version = "0.57.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.60.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "anyhow", "async-trait", @@ -1496,8 +1627,8 @@ dependencies = [ [[package]] name = "deno_crypto" -version = "0.191.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.194.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "aes", "aes-gcm", @@ -1534,33 +1665,37 @@ dependencies = [ [[package]] name = "deno_doc" -version = "0.156.0" +version = "0.161.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2585b98d6ad76dae30bf2d7b6d71b8363cae041158b8780d14a2f4fe17590a61" +checksum = "32d994915f85e873865fc341e592080a487b0a987d06177016b2d93fd62162f8" dependencies = [ "anyhow", "cfg-if", "comrak", "deno_ast", "deno_graph", - "futures", + "deno_path_util", "handlebars", "html-escape", "import_map", - "indexmap", + "indexmap 2.6.0", "itoa", + "js-sys", "lazy_static", + "percent-encoding", "regex", "serde", + "serde-wasm-bindgen", "serde_json", - "syntect", "termcolor", + "url", + "wasm-bindgen", ] [[package]] name = "deno_fetch" -version = "0.201.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.204.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "base64 0.21.7", "bytes", @@ -1570,6 +1705,7 @@ dependencies = [ "deno_tls", "dyn-clone", "error_reporter", + "hickory-resolver", "http 1.1.0", "http-body-util", "hyper 1.5.0", @@ -1592,8 +1728,8 @@ dependencies = [ [[package]] name = "deno_ffi" -version = "0.164.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.167.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_permissions", @@ -1613,11 +1749,12 @@ dependencies = [ [[package]] name = "deno_fs" -version = "0.87.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.90.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-trait", "base32", + "boxed_error", "deno_core", "deno_io", "deno_path_util", @@ -1636,9 +1773,9 @@ dependencies = [ [[package]] name = "deno_graph" -version = "0.84.1" +version = "0.86.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd4f4a14aa069087be41c2998077b0453f0191747898f96e6343f700abfc2c18" +checksum = "4c3f4be49dad28e794ff4eeb2daaf7956c97f8557097ef6f9c3ff1292e0a5c28" dependencies = [ "anyhow", "async-trait", @@ -1649,7 +1786,7 @@ dependencies = [ "encoding_rs", "futures", "import_map", - "indexmap", + "indexmap 2.6.0", "log", "monch", "once_cell", @@ -1661,12 +1798,13 @@ dependencies = [ "thiserror", "twox-hash", "url", + "wasm_dep_analyzer", ] [[package]] name = "deno_http" -version = "0.175.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.178.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-compression", "async-trait", @@ -1702,8 +1840,8 @@ dependencies = [ [[package]] name = "deno_io" -version = "0.87.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.90.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-trait", "deno_core", @@ -1724,12 +1862,13 @@ dependencies = [ [[package]] name = "deno_kv" -version = "0.85.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.88.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "anyhow", "async-trait", "base64 0.21.7", + "boxed_error", "bytes", "chrono", "deno_core", @@ -1745,7 +1884,7 @@ dependencies = [ "http-body-util", "log", "num-bigint", - "prost 0.11.9", + "prost", "prost-build", "rand", "rusqlite", @@ -1797,8 +1936,8 @@ dependencies = [ [[package]] name = "deno_napi" -version = "0.108.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.111.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_permissions", @@ -1825,8 +1964,8 @@ dependencies = [ [[package]] name = "deno_net" -version = "0.169.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.172.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_permissions", @@ -1843,14 +1982,15 @@ dependencies = [ [[package]] name = "deno_node" -version = "0.114.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.117.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "aead-gcm-stream", "aes", "async-trait", "base64 0.21.7", "blake2", + "boxed_error", "brotli", "bytes", "cbc", @@ -1882,8 +2022,8 @@ dependencies = [ "http-body-util", "hyper 1.5.0", "hyper-util", - "idna 0.3.0", - "indexmap", + "idna 1.0.3", + "indexmap 2.6.0", "ipnetwork", "k256", "lazy-regex", @@ -1923,6 +2063,7 @@ dependencies = [ "stable_deref_trait", "thiserror", "tokio", + "tokio-eld", "url", "webpki-root-certs", "winapi", @@ -1953,13 +2094,14 @@ dependencies = [ [[package]] name = "deno_ops" -version = "0.194.0" +version = "0.199.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f760b492bd638c1dc3e992d11672c259fbe9a233162099a8347591c9e22d0391" +checksum = "a24a1f3e22029a57d3094b32070b8328eac793920b5a022027d360f085e6b245" dependencies = [ "proc-macro-rules", "proc-macro2", "quote", + "stringcase", "strum", "strum_macros", "syn 2.0.87", @@ -1973,7 +2115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cbc4c4d3eb0960b58e8f43f9fc2d3f620fcac9a03cd85203e08db5b04e83c1f" dependencies = [ "deno_semver", - "indexmap", + "indexmap 2.6.0", "serde", "serde_json", "thiserror", @@ -1993,8 +2135,8 @@ dependencies = [ [[package]] name = "deno_permissions" -version = "0.37.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.40.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_path_util", @@ -2012,11 +2154,14 @@ dependencies = [ [[package]] name = "deno_resolver" -version = "0.9.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.12.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "anyhow", "base32", + "boxed_error", + "dashmap", + "deno_config", "deno_media_type", "deno_package_json", "deno_path_util", @@ -2028,8 +2173,8 @@ dependencies = [ [[package]] name = "deno_runtime" -version = "0.186.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.189.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "color-print", "deno_ast", @@ -2051,6 +2196,7 @@ dependencies = [ "deno_node", "deno_path_util", "deno_permissions", + "deno_telemetry", "deno_terminal 0.2.0", "deno_tls", "deno_url", @@ -2124,6 +2270,28 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "deno_telemetry" +version = "0.2.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" +dependencies = [ + "async-trait", + "deno_core", + "http-body-util", + "hyper 1.5.0", + "hyper-util", + "log", + "once_cell", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "pin-project", + "serde", + "tokio", +] + [[package]] name = "deno_terminal" version = "0.1.1" @@ -2146,8 +2314,8 @@ dependencies = [ [[package]] name = "deno_tls" -version = "0.164.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.167.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_native_certs", @@ -2196,8 +2364,8 @@ dependencies = [ [[package]] name = "deno_url" -version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.180.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "thiserror", @@ -2206,8 +2374,8 @@ dependencies = [ [[package]] name = "deno_web" -version = "0.208.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.211.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "async-trait", "base64-simd 0.8.0", @@ -2225,8 +2393,8 @@ dependencies = [ [[package]] name = "deno_webgpu" -version = "0.144.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.147.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "raw-window-handle", @@ -2239,16 +2407,16 @@ dependencies = [ [[package]] name = "deno_webidl" -version = "0.177.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.180.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", ] [[package]] name = "deno_websocket" -version = "0.182.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.185.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "bytes", "deno_core", @@ -2270,8 +2438,8 @@ dependencies = [ [[package]] name = "deno_webstorage" -version = "0.172.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.175.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "deno_core", "deno_web", @@ -2300,7 +2468,7 @@ dependencies = [ "chrono", "futures", "num-bigint", - "prost 0.13.3", + "prost", "serde", "uuid", ] @@ -2320,7 +2488,7 @@ dependencies = [ "futures", "http 1.1.0", "log", - "prost 0.13.3", + "prost", "rand", "serde", "serde_json", @@ -2357,7 +2525,7 @@ dependencies = [ [[package]] name = "denort" -version = "0.3.0" +version = "0.3.0-rc.1" dependencies = [ "anyhow", "color-eyre", @@ -2477,6 +2645,19 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + [[package]] name = "diatomic-waker" version = "0.2.3" @@ -2601,7 +2782,7 @@ dependencies = [ "anyhow", "bumpalo", "hashbrown 0.14.5", - "indexmap", + "indexmap 2.6.0", "rustc-hash", "serde", "unicode-width", @@ -2807,7 +2988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48cede2bb1b07dd598d269f973792c43e0cd92686d3b452bd6e01d7a8eb01211" dependencies = [ "debug-ignore", - "indexmap", + "indexmap 2.6.0", "log", "thiserror", "zerocopy", @@ -2855,6 +3036,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -3416,24 +3603,29 @@ dependencies = [ [[package]] name = "ghjk" -version = "0.3.0" +version = "0.3.0-rc.1" dependencies = [ "ahash", "anyhow", "async-trait", - "bitflags 2.6.0", + "bitflags 1.3.2", "clap", + "clap_complete", "color-eyre", + "config", + "console", + "console-subscriber", "dashmap", "data-encoding", "deno_core", "denort", + "dialoguer", "directories", "educe", "futures", "futures-concurrency", - "indexmap", - "itertools 0.13.0", + "indexmap 2.6.0", + "itertools 0.10.5", "json-canon", "multihash", "nix 0.29.0", @@ -3610,7 +3802,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -3629,7 +3821,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -3662,6 +3854,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.5" @@ -3687,6 +3885,20 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "base64 0.21.7", + "byteorder", + "crossbeam-channel", + "flate2", + "nom 7.1.3", + "num-traits", +] + [[package]] name = "heck" version = "0.4.1" @@ -3961,6 +4173,19 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper 1.5.0", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.7" @@ -4005,91 +4230,230 @@ dependencies = [ ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] [[package]] -name = "idna" -version = "0.3.0" +name = "icu_locid" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "idna" -version = "0.4.0" +name = "icu_locid_transform" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "if_chain" -version = "1.0.2" +name = "icu_locid_transform_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" [[package]] -name = "ignore" -version = "0.4.20" +name = "icu_normalizer" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", ] [[package]] -name = "image" -version = "0.24.9" +name = "icu_normalizer_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-traits", - "png", -] +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] -name = "import_map" -version = "0.20.1" +name = "icu_properties" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a787decc56f38d65d16d32687265045d6d6a4531b4a0e1b649def3590354e" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ - "indexmap", - "log", - "percent-encoding", - "serde", - "serde_json", - "thiserror", - "url", + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", ] [[package]] -name = "indenter" -version = "0.3.3" +name = "icu_properties_data" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] -name = "indexmap" -version = "2.6.0" +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "ignore" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +dependencies = [ + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + +[[package]] +name = "import_map" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a787decc56f38d65d16d32687265045d6d6a4531b4a0e1b649def3590354e" +dependencies = [ + "indexmap 2.6.0", + "log", + "percent-encoding", + "serde", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ @@ -4277,6 +4641,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "jsonc-parser" version = "0.26.2" @@ -4296,6 +4671,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "jupyter-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd71aa17c4fa65e6d7536ab2728881a41f8feb2ee5841c2240516c3c3d65d8b3" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "thiserror", + "uuid", +] + [[package]] name = "k256" version = "0.13.3" @@ -4388,12 +4776,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.155" @@ -4516,6 +4898,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "litrs" version = "0.4.1" @@ -4600,9 +4988,9 @@ dependencies = [ [[package]] name = "markup_fmt" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebae65c91eab3d42231232bf48107f351e5a8d511454927218c53aeb68bbdb6f" +checksum = "f303c36143671ac6c54112eb5aa95649b169dae783fdb6ead2c0e88b408c425c" dependencies = [ "aho-corasick", "css_dataset", @@ -4626,6 +5014,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "md-5" version = "0.10.6" @@ -4757,7 +5151,7 @@ dependencies = [ "bitflags 2.6.0", "codespan-reporting", "hexf-parse", - "indexmap", + "indexmap 2.6.0", "log", "num-traits", "rustc-hash", @@ -4770,8 +5164,8 @@ dependencies = [ [[package]] name = "napi_sym" -version = "0.107.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.110.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "quote", "serde", @@ -4838,11 +5232,12 @@ dependencies = [ [[package]] name = "node_resolver" -version = "0.16.0" -source = "git+https://github.com/metatypedev/deno?branch=v2.0.6-embeddable#5bf5dcaa89967e67e5a156de02b512bf06dc3fbd" +version = "0.19.0" +source = "git+https://github.com/metatypedev/deno?branch=v2.1.2-embeddable#56aa322605a14bb3911b75376846c8624e4f4104" dependencies = [ "anyhow", "async-trait", + "boxed_error", "deno_media_type", "deno_package_json", "deno_path_util", @@ -5048,28 +5443,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "onig" -version = "6.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" -dependencies = [ - "bitflags 1.3.2", - "libc", - "once_cell", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "opaque-debug" version = "0.3.1" @@ -5093,6 +5466,92 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "opentelemetry" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a8a7f5f6ba7c1b286c2fbca0454eaba116f63bbe69ed250b642d36fbb04d80" +dependencies = [ + "async-trait", + "bytes", + "http 1.1.0", + "opentelemetry", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" +dependencies = [ + "async-trait", + "futures-core", + "http 1.1.0", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost", + "serde_json", + "thiserror", + "tokio", + "tonic", + "tracing", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" +dependencies = [ + "hex", + "opentelemetry", + "opentelemetry_sdk", + "prost", + "serde", + "tonic", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc1b6902ff63b32ef6c489e8048c5e253e2e4a803ea3ea7e783914536eb15c52" + +[[package]] +name = "opentelemetry_sdk" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" +dependencies = [ + "async-trait", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "opentelemetry", + "percent-encoding", + "rand", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -5336,7 +5795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap", + "indexmap 2.6.0", ] [[package]] @@ -5457,6 +5916,22 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "play" +version = "0.3.0-rc.1" +dependencies = [ + "clap", + "color-eyre", + "data-encoding", + "futures-concurrency", + "once_cell", + "sha2", + "tokio", + "tracing", + "tracing-subscriber", + "tracing-unwrap", +] + [[package]] name = "png" version = "0.17.13" @@ -5505,16 +5980,6 @@ dependencies = [ "yaml_parser", ] -[[package]] -name = "prettyplease" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" -dependencies = [ - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "prettyplease" version = "0.2.25" @@ -5596,16 +6061,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive 0.11.9", -] - [[package]] name = "prost" version = "0.13.3" @@ -5613,42 +6068,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.13.3", + "prost-derive", ] [[package]] name = "prost-build" -version = "0.11.9" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", - "lazy_static", + "heck 0.5.0", + "itertools 0.13.0", "log", "multimap", + "once_cell", "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", + "prettyplease", + "prost", "prost-types", "regex", - "syn 1.0.109", + "syn 2.0.87", "tempfile", - "which 4.4.2", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", ] [[package]] @@ -5666,11 +6107,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.9" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ - "prost 0.11.9", + "prost", ] [[package]] @@ -5726,7 +6167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1a341ae463320e9f8f34adda49c8a85d81d4e8f34cce4397fb0350481552224" dependencies = [ "chrono", - "indexmap", + "indexmap 2.6.0", "quick-xml", "strip-ansi-escapes", "thiserror", @@ -5744,9 +6185,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -6045,9 +6486,9 @@ dependencies = [ [[package]] name = "runtimelib" -version = "0.14.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3d817764e3971867351e6103955b17d808f5330e9ef63aaaaab55bf8c664c1" +checksum = "fe23ba9967355bbb1be2fb9a8e51bd239ffdf9c791fad5a9b765122ee2bde2e4" dependencies = [ "anyhow", "base64 0.22.1", @@ -6057,6 +6498,7 @@ dependencies = [ "dirs", "futures", "glob", + "jupyter-serde", "rand", "ring", "serde", @@ -6395,6 +6837,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bytes" version = "0.11.15" @@ -6421,7 +6874,7 @@ version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ - "indexmap", + "indexmap 2.6.0", "itoa", "memchr", "ryu", @@ -6441,9 +6894,9 @@ dependencies = [ [[package]] name = "serde_v8" -version = "0.227.0" +version = "0.232.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a8294c2223c53bed343be8b80564ece4dc0d03b643b06fa86c4ccc0e064eda0" +checksum = "5c9feae92f7293fcc1a32a86be1a399859c0637e55dad8991d5258c43f7ff4d2" dependencies = [ "num-bigint", "serde", @@ -6528,6 +6981,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shellexpand" version = "3.1.0" @@ -6745,6 +7204,18 @@ dependencies = [ "der", ] +[[package]] +name = "sqlformat" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c38684453189293372e6fffa3bed1015d20488ce4cc09a23de050fd7411e46" +dependencies = [ + "nom 7.1.3", + "once_cell", + "regex", + "unicode_categories", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -6782,6 +7253,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "stringcase" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04028eeb851ed08af6aba5caa29f2d59a13ed168cee4d6bd753aeefcf1d636b0" + [[package]] name = "strip-ansi-escapes" version = "0.2.0" @@ -6858,7 +7335,7 @@ checksum = "c77c112c218a09635d99a45802a81b4f341d6c28c81076aa2c29ba3bcd9151a9" dependencies = [ "anyhow", "crc", - "indexmap", + "indexmap 2.6.0", "is-macro", "once_cell", "parking_lot", @@ -6928,7 +7405,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4740e53eaf68b101203c1df0937d5161a29f3c13bceed0836ddfe245b72dd000" dependencies = [ "anyhow", - "indexmap", + "indexmap 2.6.0", "serde", "serde_json", "swc_cached", @@ -7040,7 +7517,7 @@ checksum = "65f21494e75d0bd8ef42010b47cabab9caaed8f2207570e809f6f4eb51a710d1" dependencies = [ "better_scoped_tls", "bitflags 2.6.0", - "indexmap", + "indexmap 2.6.0", "once_cell", "phf", "rustc-hash", @@ -7088,7 +7565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98d8447ea20ef76958a8240feef95743702485a84331e6df5bdbe7e383c87838" dependencies = [ "dashmap", - "indexmap", + "indexmap 2.6.0", "once_cell", "petgraph", "rustc-hash", @@ -7133,7 +7610,7 @@ checksum = "76c76d8b9792ce51401d38da0fa62158d61f6d80d16d68fe5b03ce4bf5fba383" dependencies = [ "base64 0.21.7", "dashmap", - "indexmap", + "indexmap 2.6.0", "once_cell", "serde", "sha1", @@ -7173,7 +7650,7 @@ version = "0.134.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029eec7dd485923a75b5a45befd04510288870250270292fc2c1b3a9e7547408" dependencies = [ - "indexmap", + "indexmap 2.6.0", "num_cpus", "once_cell", "rustc-hash", @@ -7218,7 +7695,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357e2c97bb51431d65080f25b436bc4e2fc1a7f64a643bc21a8353e478dc799f" dependencies = [ - "indexmap", + "indexmap 2.6.0", "petgraph", "rustc-hash", "swc_common", @@ -7293,6 +7770,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + [[package]] name = "synstructure" version = "0.12.6" @@ -7316,26 +7799,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "syntect" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" -dependencies = [ - "bincode", - "bitflags 1.3.2", - "flate2", - "fnv", - "once_cell", - "onig", - "regex-syntax 0.8.5", - "serde", - "serde_derive", - "serde_json", - "thiserror", - "walkdir", -] - [[package]] name = "tap" version = "1.0.1" @@ -7471,6 +7934,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.1" @@ -7502,9 +7975,20 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", + "tracing", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-eld" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9166030f05d6bc5642bdb8f8c2be31eb3c02cd465d662bcdc2df82d4aa41a584" +dependencies = [ + "hdrhistogram", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.3.0" @@ -7553,9 +8037,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -7588,6 +8072,36 @@ dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.5.0", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "socket2", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -7596,11 +8110,16 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "indexmap 1.9.3", "pin-project", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -7944,12 +8463,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 1.0.3", "percent-encoding", "serde", ] @@ -7972,12 +8491,24 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -7997,9 +8528,9 @@ dependencies = [ [[package]] name = "v8" -version = "0.106.0" +version = "130.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a381badc47c6f15acb5fe0b5b40234162349ed9d4e4fd7c83a7f5547c0fc69c5" +checksum = "c23b5c2caff00209b03a716609b275acae94b02dd3b63c4648e7232a84a8402f" dependencies = [ "bindgen", "bitflags 2.6.0", @@ -8020,7 +8551,7 @@ checksum = "97599c400fc79925922b58303e98fcb8fa88f573379a08ddb652e72cbd2e70f6" dependencies = [ "bitflags 2.6.0", "encoding_rs", - "indexmap", + "indexmap 2.6.0", "num-bigint", "serde", "thiserror", @@ -8176,6 +8707,15 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasm_dep_analyzer" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f270206a91783fd90625c8bb0d8fbd459d0b1d1bf209b656f713f01ae7c04b8" +dependencies = [ + "thiserror", +] + [[package]] name = "web-sys" version = "0.3.69" @@ -8216,7 +8756,7 @@ dependencies = [ "cfg_aliases 0.1.1", "codespan-reporting", "document-features", - "indexmap", + "indexmap 2.6.0", "log", "naga", "once_cell", @@ -8550,6 +9090,18 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "wtf8" version = "0.1.0" @@ -8613,7 +9165,7 @@ checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" [[package]] name = "xtask" -version = "0.3.0" +version = "0.3.0-rc.1" dependencies = [ "clap", "color-eyre", @@ -8722,9 +9274,9 @@ dependencies = [ [[package]] name = "zeromq" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0560d00172817b7f7c2265060783519c475702ae290b154115ca75e976d4d0" +checksum = "6a4528179201f6eecf211961a7d3276faa61554c82651ecc66387f68fc3004bd" dependencies = [ "async-trait", "asynchronous-codec", @@ -8747,6 +9299,28 @@ dependencies = [ "uuid", ] +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "zip" version = "2.2.0" @@ -8758,7 +9332,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap", + "indexmap 2.6.0", "memchr", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 2372000..c3eefa3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,15 +4,15 @@ exclude = ["src/deno_systems"] resolver = "2" [workspace.package] -version = "0.3.0" +version = "0.3.0-rc.1" edition = "2021" [workspace.dependencies] denort = { path = "src/denort" } -deno = { git = "https://github.com/metatypedev/deno", branch = "v2.0.6-embeddable" } +deno = { git = "https://github.com/metatypedev/deno", branch = "v2.1.2-embeddable" } # needed to get deno_core::op2 working -# must track version used by deno -deno_core = "=0.318.0" +# WARN: must track version used by deno +deno_core = "=0.323.0" educe = "0.6" @@ -28,8 +28,10 @@ tracing-unwrap = "1.0" once_cell = "1" -# version must match on clap in `deno` +# WARN: version must match on clap in `deno` clap = "=4.5" +clap_complete = "=4.5.24" + shadow-rs = "0.36.0" diff --git a/README.md b/README.md index 809c7aa..c5f884f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ghjk -ghjk /gk/ is a programmable runtime manager and an attempt at a successor for [asdf](https://github.com/asdf-vm/asdf). +ghjk /gk/ is a set of tools for managing developer environments and an attempt at a successor for [asdf](https://github.com/asdf-vm/asdf). > ghjk is part of the > [Metatype ecosystem](https://github.com/metatypedev/metatype). Consider @@ -46,7 +46,7 @@ Before anything, make sure the following programs are available on the system. Install the ghjk cli using the installer scripts like so: ```bash -curl -fsSL https://raw.github.com/metatypedev/ghjk/v0.3.0/install.sh | bash +curl -fsSL https://raw.github.com/metatypedev/ghjk/v0.3.0-rc.1/install.sh | bash ``` Use the following command to create a starter `ghjk.ts` in your project directory: @@ -61,9 +61,9 @@ Ghjk is primarily configured through constructs called "environments" or "envs" They serve as recipes for making (mostly) reproducible posix shells. ```ts -import { file } from "https://raw.github.com/metatypedev/ghjk/v0.3.0/mod.ts"; +import { file } from "https://raw.github.com/metatypedev/ghjk/v0.3.0-rc.1/mod.ts"; // ports are small programs that install sowtware to your envs -import * as ports from "https://raw.github.com/metatypedev/ghjk/v0.3.0/ports/mod.ts"; +import * as ports from "https://raw.github.com/metatypedev/ghjk/v0.3.0-rc.1/ports/mod.ts"; const ghjk = file({}); @@ -151,7 +151,6 @@ Run the tests in the repository through the deno task: ```bash $ deno task test +# this supports filtering +$ deno task test --filter envHooks ``` - -Most tests are isolated from each other using containers. -Set `$GHJK_TEST_E2E_TYPE` to `local` to use the local test runner. diff --git a/deno.jsonc b/deno.jsonc index fdbc2ba..ce5a3f9 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -1,7 +1,7 @@ { "tasks": { - "test": "cargo x test tests/*", - "self": "deno run -A --unstable-kv --unstable-worker-options main.ts ", + "test": "cargo build -p ghjk && deno test --unstable-worker-options --unstable-kv -A tests/*", + "self": "cargo run -p ghjk", "cache": "deno cache deps/*", "check": "deno run -A ./scripts/check.ts", "dev": "deno run -A ./scripts/dev.ts" diff --git a/deno.lock b/deno.lock index 6d7581e..840393d 100644 --- a/deno.lock +++ b/deno.lock @@ -1,11 +1,8 @@ { "version": "4", "specifiers": { - "jsr:@david/dax@0.40.1": "0.40.1", "jsr:@david/dax@0.41.0": "0.41.0", - "jsr:@david/which@0.3": "0.3.0", "jsr:@david/which@~0.4.1": "0.4.1", - "jsr:@ghjk/dax@0.40.2-alpha-ghjk": "0.40.2-alpha-ghjk", "jsr:@std/assert@0.221": "0.221.0", "jsr:@std/bytes@0.221": "0.221.0", "jsr:@std/fmt@0.221": "0.221.0", @@ -15,37 +12,17 @@ "jsr:@std/path@0.221": "0.221.0", "jsr:@std/path@0.221.0": "0.221.0", "jsr:@std/streams@0.221.0": "0.221.0", - "npm:@livekit/rtc-node@0.11.1": "0.11.1", "npm:@noble/hashes@1.4.0": "1.4.0", - "npm:@types/node@*": "18.16.19", - "npm:livekit-server-sdk@2.7.2": "2.7.2", - "npm:lodash@*": "4.17.21", - "npm:mathjs@11.11.1": "11.11.1", + "npm:@types/node@*": "22.5.4", "npm:multiformats@13.1.0": "13.1.0", - "npm:pg@*": "8.12.0", - "npm:validator@*": "13.12.0", - "npm:zod-validation-error@*": "3.1.0_zod@3.23.3", - "npm:zod-validation-error@3.2.0": "3.2.0_zod@3.23.3", - "npm:zod-validation-error@3.3.0": "3.3.0_zod@3.23.3", "npm:zod-validation-error@3.4.0": "3.4.0_zod@3.23.8", "npm:zod@3.23.8": "3.23.8" }, "jsr": { - "@david/dax@0.40.1": { - "integrity": "0c71d32a0484d3904f586417995f8ec26d45144f0eba95d3e5bb03b640b6df59", - "dependencies": [ - "jsr:@david/which@0.3", - "jsr:@std/fmt", - "jsr:@std/fs", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams" - ] - }, "@david/dax@0.41.0": { "integrity": "9e1ecf66a0415962cc8ad3ba4e3fa93ce0f1a1cc797dd95c36fdfb6977dc7fc8", "dependencies": [ - "jsr:@david/which@~0.4.1", + "jsr:@david/which", "jsr:@std/fmt", "jsr:@std/fs", "jsr:@std/io@0.221.0", @@ -53,23 +30,9 @@ "jsr:@std/streams" ] }, - "@david/which@0.3.0": { - "integrity": "6bdb62c40ac90edcf328e854fa8103a8db21e7c326089cbe3c3a1cf7887d3204" - }, "@david/which@0.4.1": { "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" }, - "@ghjk/dax@0.40.2-alpha-ghjk": { - "integrity": "87bc93e9947779cb2f3922fe277e21ea8c716de804b2627f80ba9e7bc3d0d019", - "dependencies": [ - "jsr:@david/which@0.3", - "jsr:@std/fmt", - "jsr:@std/fs", - "jsr:@std/io@0.221.0", - "jsr:@std/path@0.221.0", - "jsr:@std/streams" - ] - }, "@std/assert@0.221.0": { "integrity": "a5f1aa6e7909dbea271754fd4ab3f4e687aeff4873b4cef9a320af813adb489a" }, @@ -107,239 +70,27 @@ } }, "npm": { - "@babel/runtime@7.24.7": { - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", - "dependencies": [ - "regenerator-runtime" - ] - }, - "@bufbuild/protobuf@1.10.0": { - "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==" - }, - "@bufbuild/protobuf@2.2.2": { - "integrity": "sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==" - }, - "@livekit/mutex@1.1.0": { - "integrity": "sha512-XRLG+z/0uoyDioupjUiskjI06Y51U/IXVPJn7qJ+R3J75XX01irYVBM9MpxeJahpVoe9QhU4moIEolX+HO9U9g==" - }, - "@livekit/protocol@1.27.1": { - "integrity": "sha512-ISEp7uWdV82mtCR1eyHFTzdRZTVbe2+ZztjmjiMPzR/KPrI1Ma/u5kLh87NNuY3Rn8wv1VlEvGHHsFjQ+dKVUw==", - "dependencies": [ - "@bufbuild/protobuf@1.10.0" - ] - }, - "@livekit/rtc-node-darwin-arm64@0.11.1": { - "integrity": "sha512-M+Ui87H06ae19GGI7r937dS6hI84MBBTQAkkNlL7qd+pvdCAk25u0FYa8r4SOElKJ0VR3AbzeDoXTihLgpvjMg==" - }, - "@livekit/rtc-node-darwin-x64@0.11.1": { - "integrity": "sha512-7G92fyuK2p+jdTH2cUJTNeAmtknTGsXuy0xbI727V7VzQvHFDXULCExRlgwn4t9TxvNlIjUpiltiQ6RCSai6zw==" - }, - "@livekit/rtc-node-linux-arm64-gnu@0.11.1": { - "integrity": "sha512-vqZN9+87Pvxit7auYVW69M+GvUPnf+EwipIJ92GgCJA3Ir1Tcceu5ud5/Ic+0FzSoV0cotVVlQNm74F0tQvyCg==" - }, - "@livekit/rtc-node-linux-x64-gnu@0.11.1": { - "integrity": "sha512-smHZUMfgILQh6/eoauYNe/VlKwQCp4/4jWxiIADHY+mtDtVSvQ9zB6y4GP8FrpohRwFWesKCUpvPBypU0Icrng==" - }, - "@livekit/rtc-node-win32-x64-msvc@0.11.1": { - "integrity": "sha512-bTWVtb+UiRPFjiuhrqq40gt5vs5mMPTa1e+kd2jGQPTOlKZPLArQ0WgFcep2TAy1zmcpOgfeM1XRPVFhZl7G1A==" - }, - "@livekit/rtc-node@0.11.1": { - "integrity": "sha512-EFw+giPll12fcXATZpN2zKkE3umYJAdHvfjW+Yu0aBjwfxbUBXu8rz6le2CzDNvGmRwR888DSZXFZfYikwZgiw==", - "dependencies": [ - "@bufbuild/protobuf@2.2.2", - "@livekit/mutex", - "@livekit/rtc-node-darwin-arm64", - "@livekit/rtc-node-darwin-x64", - "@livekit/rtc-node-linux-arm64-gnu", - "@livekit/rtc-node-linux-x64-gnu", - "@livekit/rtc-node-win32-x64-msvc", - "@livekit/typed-emitter" - ] - }, - "@livekit/typed-emitter@3.0.0": { - "integrity": "sha512-9bl0k4MgBPZu3Qu3R3xy12rmbW17e3bE9yf4YY85gJIQ3ezLEj/uzpKHWBsLaDoL5Mozz8QCgggwIBudYQWeQg==" - }, "@noble/hashes@1.4.0": { "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" }, - "@types/node@18.16.19": { - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" - }, - "camelcase-keys@9.1.3": { - "integrity": "sha512-Rircqi9ch8AnZscQcsA1C47NFdaO3wukpmIRzYcDOrmvgt78hM/sj5pZhZNec2NM12uk5vTwRHZ4anGcrC4ZTg==", - "dependencies": [ - "camelcase", - "map-obj", - "quick-lru", - "type-fest" - ] - }, - "camelcase@8.0.0": { - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==" - }, - "complex.js@2.1.1": { - "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==" - }, - "decimal.js@10.4.3": { - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" - }, - "escape-latex@1.2.0": { - "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" - }, - "fraction.js@4.3.4": { - "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==" - }, - "javascript-natural-sort@0.7.1": { - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" - }, - "jose@5.9.6": { - "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==" - }, - "livekit-server-sdk@2.7.2": { - "integrity": "sha512-qDNRXeo+WMnY5nKSug7KHJ9er9JIuKi+r7H9ZaSBbmbaOt62i0b4BrHBMFSMr8pAuWzuSxihCFa29q5QvFc5fw==", + "@types/node@22.5.4": { + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", "dependencies": [ - "@livekit/protocol", - "camelcase-keys", - "jose" - ] - }, - "lodash@4.17.21": { - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "map-obj@5.0.0": { - "integrity": "sha512-2L3MIgJynYrZ3TYMriLDLWocz15okFakV6J12HXvMXDHui2x/zgChzg1u9mFFGbbGWE+GsLpQByt4POb9Or+uA==" - }, - "mathjs@11.11.1": { - "integrity": "sha512-uWrwMrhU31TCqHKmm1yFz0C352njGUVr/I1UnpMOxI/VBTTbCktx/mREUXx5Vyg11xrFdg/F3wnMM7Ql/csVsQ==", - "dependencies": [ - "@babel/runtime", - "complex.js", - "decimal.js", - "escape-latex", - "fraction.js", - "javascript-natural-sort", - "seedrandom", - "tiny-emitter", - "typed-function" + "undici-types" ] }, "multiformats@13.1.0": { "integrity": "sha512-HzdtdBwxsIkzpeXzhQ5mAhhuxcHbjEHH+JQoxt7hG/2HGFjjwyolLo7hbaexcnhoEuV4e0TNJ8kkpMjiEYY4VQ==" }, - "pg-cloudflare@1.1.1": { - "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==" - }, - "pg-connection-string@2.6.4": { - "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==" - }, - "pg-int8@1.0.1": { - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-pool@3.6.2_pg@8.12.0": { - "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", - "dependencies": [ - "pg" - ] - }, - "pg-protocol@1.6.1": { - "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==" - }, - "pg-types@2.2.0": { - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "dependencies": [ - "pg-int8", - "postgres-array", - "postgres-bytea", - "postgres-date", - "postgres-interval" - ] - }, - "pg@8.12.0": { - "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", - "dependencies": [ - "pg-cloudflare", - "pg-connection-string", - "pg-pool", - "pg-protocol", - "pg-types", - "pgpass" - ] - }, - "pgpass@1.0.5": { - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "dependencies": [ - "split2" - ] - }, - "postgres-array@2.0.0": { - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea@1.0.0": { - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==" - }, - "postgres-date@1.0.7": { - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" - }, - "postgres-interval@1.2.0": { - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "dependencies": [ - "xtend" - ] - }, - "quick-lru@6.1.2": { - "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==" - }, - "regenerator-runtime@0.14.1": { - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "seedrandom@3.0.5": { - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" - }, - "split2@4.2.0": { - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" - }, - "tiny-emitter@2.1.0": { - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" - }, - "type-fest@4.26.1": { - "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==" - }, - "typed-function@4.2.1": { - "integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==" - }, - "validator@13.12.0": { - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==" - }, - "xtend@4.0.2": { - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "zod-validation-error@3.1.0_zod@3.23.3": { - "integrity": "sha512-zujS6HqJjMZCsvjfbnRs7WI3PXN39ovTcY1n8a+KTm4kOH0ZXYsNiJkH1odZf4xZKMkBDL7M2rmQ913FCS1p9w==", - "dependencies": [ - "zod@3.23.3" - ] - }, - "zod-validation-error@3.2.0_zod@3.23.3": { - "integrity": "sha512-cYlPR6zuyrgmu2wRTdumEAJGuwI7eHVHGT+VyneAQxmRAKtGRL1/7pjz4wfLhz4J05f5qoSZc3rGacswgyTjjw==", - "dependencies": [ - "zod@3.23.3" - ] - }, - "zod-validation-error@3.3.0_zod@3.23.3": { - "integrity": "sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw==", - "dependencies": [ - "zod@3.23.3" - ] + "undici-types@6.19.8": { + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "zod-validation-error@3.4.0_zod@3.23.8": { "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", "dependencies": [ - "zod@3.23.8" + "zod" ] }, - "zod@3.23.3": { - "integrity": "sha512-tPvq1B/2Yu/dh2uAIH2/BhUlUeLIUvAjr6dpL/75I0pCYefHgjhXk1o1Kob3kTU8C7yU1j396jFHlsVWFi9ogg==" - }, "zod@3.23.8": { "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" } @@ -357,12 +108,17 @@ "https://deno.land/std@0.116.0/path/posix.ts": "34349174b9cd121625a2810837a82dd8b986bbaaad5ade690d1de75bbb4555b2", "https://deno.land/std@0.116.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c", "https://deno.land/std@0.116.0/path/win32.ts": "11549e8c6df8307a8efcfa47ad7b2a75da743eac7d4c89c9723a944661c8bd2e", - "https://deno.land/std@0.120.0/_wasm_crypto/crypto.js": "5c283a80e1059d16589b79fa026be5fb0a28424302a99487cadceef8c17f8afa", - "https://deno.land/std@0.120.0/_wasm_crypto/crypto.wasm.js": "0e6df3c18beb1187b442ec7f0a03df4d18b21212172d6b4a50ee4816404771d7", - "https://deno.land/std@0.120.0/_wasm_crypto/mod.ts": "7d02009ef3ddc953c8f90561d213e02fa0a6f3eaed9b8baf0c241c8cbeec1ed3", - "https://deno.land/std@0.120.0/crypto/mod.ts": "5760510eaa0b250f78cce81ce92d83cf8c40e9bb3c3efeedd4ef1a5bb0801ef4", - "https://deno.land/std@0.120.0/encoding/ascii85.ts": "b42b041e9c668afa356dd07ccf69a6b3ee49b9ae080fdf3b03f0ac3981f4d1e6", - "https://deno.land/std@0.120.0/encoding/base64.ts": "0b58bd6477214838bf711eef43eac21e47ba9e5c81b2ce185fe25d9ecab3ebb3", + "https://deno.land/std@0.134.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.134.0/_util/os.ts": "49b92edea1e82ba295ec946de8ffd956ed123e2948d9bd1d3e901b04e4307617", + "https://deno.land/std@0.134.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.134.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.134.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b", + "https://deno.land/std@0.134.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.134.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.134.0/path/mod.ts": "4275129bb766f0e475ecc5246aa35689eeade419d72a48355203f31802640be7", + "https://deno.land/std@0.134.0/path/posix.ts": "663e4a6fe30a145f56aa41a22d95114c4c5582d8b57d2d7c9ed27ad2c47636bb", + "https://deno.land/std@0.134.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.134.0/path/win32.ts": "e7bdf63e8d9982b4d8a01ef5689425c93310ece950e517476e22af10f41a136e", "https://deno.land/std@0.213.0/archive/_common.ts": "85edd5cdd4324833f613c1bc055f8e2f935cc9229c6b3044421268d9959997ef", "https://deno.land/std@0.213.0/archive/untar.ts": "7677c136f2188cd8c33363ccaaee6e77d4ca656cca3e2093d08de8f294d4353d", "https://deno.land/std@0.213.0/assert/_constants.ts": "a271e8ef5a573f1df8e822a6eb9d09df064ad66a4390f21b3e31f820a38e0975", @@ -619,12 +375,6 @@ "https://deno.land/std@0.213.0/url/join.ts": "00c7e9088cafaa24963ce4081119e58b3afe2c58f033701383f359ea02620dd2", "https://deno.land/std@0.213.0/url/mod.ts": "e2621f6a0db6fdbe7fbbd240064095bb203014657e5e1ab81db1c44d80dce6c9", "https://deno.land/std@0.213.0/url/normalize.ts": "6328c75df0fab300f74bc4a1c255062a0db882240e15ab646606d0009e7e40d7", - "https://deno.land/std@0.219.0/assert/assert.ts": "bec068b2fccdd434c138a555b19a2c2393b71dfaada02b7d568a01541e67cdc5", - "https://deno.land/std@0.219.0/assert/assertion_error.ts": "9f689a101ee586c4ce92f52fa7ddd362e86434ffdf1f848e45987dc7689976b8", - "https://deno.land/std@0.219.0/cli/mod.ts": "58f75df8ce43fb8266bdd26ec4465f73176b910316d72eb8e090b6a0549391da", - "https://deno.land/std@0.219.0/cli/parse_args.ts": "475b3edc8105c9acea09b83b100afc383d7bddbba9828da3f0c4adced006607a", - "https://deno.land/std@0.219.0/cli/prompt_secret.ts": "831cfb4efa83bfaf9bfd320ddbfd619e03cd87e81260909f93ca199ebe214ec2", - "https://deno.land/std@0.219.0/cli/spinner.ts": "005395c4e00b1086bfa2ae44e8c9413c1231c4741a08a55aa0d3c9ea267cecb5", "https://deno.land/std@0.221.0/assert/assert.ts": "bec068b2fccdd434c138a555b19a2c2393b71dfaada02b7d568a01541e67cdc5", "https://deno.land/std@0.221.0/assert/assertion_error.ts": "9f689a101ee586c4ce92f52fa7ddd362e86434ffdf1f848e45987dc7689976b8", "https://deno.land/std@0.221.0/console/_data.json": "cf2cc9d039a192b3adbfe64627167c7e6212704c888c25c769fc8f1709e1e1b8", @@ -633,12 +383,6 @@ "https://deno.land/std@0.221.0/fmt/colors.ts": "d239d84620b921ea520125d778947881f62c50e78deef2657073840b8af9559a", "https://deno.land/std@0.221.0/text/closest_string.ts": "8a91ee8b6d69ff96addcb7c251dad53b476ac8be9c756a0ef786abe9e13a93a5", "https://deno.land/std@0.221.0/text/levenshtein_distance.ts": "24be5cc88326bbba83ca7c1ea89259af0050cffda2817ff3a6d240ad6495eae2", - "https://deno.land/std@0.76.0/encoding/base64.ts": "b1d8f99b778981548457ec74bc6273ad785ffd6f61b2233bd5b30925345b565d", - "https://deno.land/std@0.76.0/encoding/hex.ts": "07a03ba41c96060a4ed4ba272e50b9e23f3c5b3839f4b069cdebc24d57434386", - "https://deno.land/std@0.76.0/hash/_wasm/hash.ts": "005f64c4d9343ecbc91e0da9ae5e800f146c20930ad829bbb872c5c06bd89c5f", - "https://deno.land/std@0.76.0/hash/_wasm/wasm.js": "5ac48aa0c3931d7f31dba628be5ab0aa4e786354197eb4d7d0583f9b50be1397", - "https://deno.land/std@0.76.0/hash/hasher.ts": "099c9e2a91b9f106b9f01379705e17e7d9de392ee1ea2b8684a2adfa82ac3bfc", - "https://deno.land/std@0.76.0/hash/mod.ts": "e764a6a9ab2f5519a97f928e17cc13d984e3dd5c7f742ff9c1c8fb3114790f0c", "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_argument_types.ts": "ab269dacea2030f865a07c2a1e953ec437a64419a05bad1f1ddaab3f99752ead", "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_errors.ts": "d78e1b4d69d84b8b476b5f3c0b028e3906d48f21b8f1ca1d36d5abe9ccfe48bc", "https://deno.land/x/cliffy@v1.0.0-rc.4/command/_spread.ts": "0cc6eb70a6df97b5d7d26008822d39f3e8a1232ee0a27f395aa19e68de738245", @@ -704,56 +448,16 @@ "https://deno.land/x/foras@v2.1.4/wasm/pkg/foras.js": "06f8875b456918b9671d52133f64f3047f1c95540feda87fdd4a55ba3d30091d", "https://deno.land/x/foras@v2.1.4/wasm/pkg/foras.wasm.js": "2df8522df7243b0f05b1d188e220629cd5d2c92080a5f1407e15396fc35bebb3", "https://deno.land/x/json_hash@0.2.0/canon.ts": "ce7c07abd871cd7f0eb1280ad9f58f6382f02f84a217898ce977cf35ad315877", - "https://deno.land/x/json_hash@0.2.0/crypto.ts": "8738b601a0cf52c0ff58242707e2d5f7f5ff8f7ca4d51d0282ad3b0bb56548cf", - "https://deno.land/x/json_hash@0.2.0/digest.ts": "95e3d996377eebebb960ad2b6e4fdd70d71543378a651c31de75f1e86b637fc7", - "https://deno.land/x/json_hash@0.2.0/hex.ts": "104154a6408c6b5b36ff35361011aeb3047941bd5a652724f5aebeeb89fcf9a8", - "https://deno.land/x/json_hash@0.2.0/merkle.ts": "cf48004b45fdf0412afd48fea0ba8bb16bf78f717a66a5ff505f6400a88c08cf", - "https://deno.land/x/json_hash@0.2.0/mod.ts": "b0fdd79a540d3fc6aa3e0a9a93fe6735b1a174d9ba2aba103e4a18ee4872acad", "https://deno.land/x/jszip@0.11.0/mod.ts": "5661ddc18e9ac9c07e3c5d2483bc912a7022b6af0d784bb7b05035973e640ba1", "https://deno.land/x/jszip@0.11.0/types.ts": "1528d1279fbb64dd118c371331c641a3a5eff2b594336fb38a7659cf4c53b2d1", - "https://deno.land/x/object_hash@2.0.3.1/index.ts": "74b20a0065dc0066c60510174626db1d18e53ec966edb6f76fa33a67aa0c44e3", - "https://deno.land/x/object_hash@2.0.3.1/mod.ts": "648559bcafb54b930d4b6a283cc2eef20afa54de471371a97c2ccf8116941148", - "https://deno.land/x/object_hash@2.0.3/index.ts": "74b20a0065dc0066c60510174626db1d18e53ec966edb6f76fa33a67aa0c44e3", - "https://deno.land/x/object_hash@2.0.3/mod.ts": "648559bcafb54b930d4b6a283cc2eef20afa54de471371a97c2ccf8116941148", - "https://deno.land/x/zod@v3.22.4/ZodError.ts": "4de18ff525e75a0315f2c12066b77b5c2ae18c7c15ef7df7e165d63536fdf2ea", - "https://deno.land/x/zod@v3.22.4/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", - "https://deno.land/x/zod@v3.22.4/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", - "https://deno.land/x/zod@v3.22.4/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", - "https://deno.land/x/zod@v3.22.4/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", - "https://deno.land/x/zod@v3.22.4/helpers/parseUtil.ts": "f791e6e65a0340d85ad37d26cd7a3ba67126cd9957eac2b7163162155283abb1", - "https://deno.land/x/zod@v3.22.4/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7", - "https://deno.land/x/zod@v3.22.4/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", - "https://deno.land/x/zod@v3.22.4/helpers/util.ts": "8baf19b19b2fca8424380367b90364b32503b6b71780269a6e3e67700bb02774", - "https://deno.land/x/zod@v3.22.4/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268", - "https://deno.land/x/zod@v3.22.4/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c", - "https://deno.land/x/zod@v3.22.4/mod.ts": "64e55237cb4410e17d968cd08975566059f27638ebb0b86048031b987ba251c4", - "https://deno.land/x/zod@v3.22.4/types.ts": "724185522fafe43ee56a52333958764c8c8cd6ad4effa27b42651df873fc151e", - "https://deno.land/x/zod@v3.23.5/ZodError.ts": "528da200fbe995157b9ae91498b103c4ef482217a5c086249507ac850bd78f52", - "https://deno.land/x/zod@v3.23.5/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", - "https://deno.land/x/zod@v3.23.5/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", - "https://deno.land/x/zod@v3.23.5/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", - "https://deno.land/x/zod@v3.23.5/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", - "https://deno.land/x/zod@v3.23.5/helpers/parseUtil.ts": "c14814d167cc286972b6e094df88d7d982572a08424b7cd50f862036b6fcaa77", - "https://deno.land/x/zod@v3.23.5/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7", - "https://deno.land/x/zod@v3.23.5/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", - "https://deno.land/x/zod@v3.23.5/helpers/util.ts": "3301a69867c9e589ac5b3bc4d7a518b5212858cd6a25e8b02d635c9c32ba331c", - "https://deno.land/x/zod@v3.23.5/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268", - "https://deno.land/x/zod@v3.23.5/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c", - "https://deno.land/x/zod@v3.23.5/mod.ts": "ec6e2b1255c1a350b80188f97bd0a6bac45801bb46fc48f50b9763aa66046039", - "https://deno.land/x/zod@v3.23.5/types.ts": "78d3f06eb313ea754fad0ee389d3c0fa55bc01cf708e6ce0ea7fddd41f31eca2", - "https://deno.land/x/zod@v3.23.8/ZodError.ts": "528da200fbe995157b9ae91498b103c4ef482217a5c086249507ac850bd78f52", - "https://deno.land/x/zod@v3.23.8/errors.ts": "5285922d2be9700cc0c70c95e4858952b07ae193aa0224be3cbd5cd5567eabef", - "https://deno.land/x/zod@v3.23.8/external.ts": "a6cfbd61e9e097d5f42f8a7ed6f92f93f51ff927d29c9fbaec04f03cbce130fe", - "https://deno.land/x/zod@v3.23.8/helpers/enumUtil.ts": "54efc393cc9860e687d8b81ff52e980def00fa67377ad0bf8b3104f8a5bf698c", - "https://deno.land/x/zod@v3.23.8/helpers/errorUtil.ts": "7a77328240be7b847af6de9189963bd9f79cab32bbc61502a9db4fe6683e2ea7", - "https://deno.land/x/zod@v3.23.8/helpers/parseUtil.ts": "c14814d167cc286972b6e094df88d7d982572a08424b7cd50f862036b6fcaa77", - "https://deno.land/x/zod@v3.23.8/helpers/partialUtil.ts": "998c2fe79795257d4d1cf10361e74492f3b7d852f61057c7c08ac0a46488b7e7", - "https://deno.land/x/zod@v3.23.8/helpers/typeAliases.ts": "0fda31a063c6736fc3cf9090dd94865c811dfff4f3cb8707b932bf937c6f2c3e", - "https://deno.land/x/zod@v3.23.8/helpers/util.ts": "30c273131661ca5dc973f2cfb196fa23caf3a43e224cdde7a683b72e101a31fc", - "https://deno.land/x/zod@v3.23.8/index.ts": "d27aabd973613985574bc31f39e45cb5d856aa122ef094a9f38a463b8ef1a268", - "https://deno.land/x/zod@v3.23.8/locales/en.ts": "a7a25cd23563ccb5e0eed214d9b31846305ddbcdb9c5c8f508b108943366ab4c", - "https://deno.land/x/zod@v3.23.8/mod.ts": "ec6e2b1255c1a350b80188f97bd0a6bac45801bb46fc48f50b9763aa66046039", - "https://deno.land/x/zod@v3.23.8/types.ts": "1b172c90782b1eaa837100ebb6abd726d79d6c1ec336350c8e851e0fd706bf5c", + "https://deno.land/x/os_paths@v7.2.0/dist/esm/lib/OSPaths.js": "db4f5f05765a1c862e7b1e0f0c293fc752e94e213eabff19f3c03af9b2164f98", + "https://deno.land/x/os_paths@v7.2.0/src/mod.deno.ts": "5e34d7c1a033665276a1a06e3957a52218bf4711a801f38cf92978aacfad5666", + "https://deno.land/x/os_paths@v7.2.0/src/platform-adapters/_base.ts": "ca9adf679709824e070631921932620ab4dc2a39fff9706f95592d1620e34dc6", + "https://deno.land/x/os_paths@v7.2.0/src/platform-adapters/deno.deno.ts": "d184d709522bf2703dc12ff335eb6a10d758a3a5dd4d97524d2aef9d3d448c13", + "https://deno.land/x/xdg_portable@v10.6.0/dist/esm/lib/XDG.js": "4c04a45149d66e4ca29ea914aac137e7b0f0b6a8ef431ffc63fef46bc3747064", + "https://deno.land/x/xdg_portable@v10.6.0/src/mod.deno.ts": "e478cc109794bfc130ec81711f9a20d594e6fad848f796c68b75dbe510683c39", + "https://deno.land/x/xdg_portable@v10.6.0/src/platform-adapters/_base.ts": "c79a7f0e5b1d77e23cbc6c782a02958573338e9dfa644a7aa5a1f7c402ff56ef", + "https://deno.land/x/xdg_portable@v10.6.0/src/platform-adapters/deno.deno.ts": "5f5852dc4588c10ad8fd0450421fa728741838cf5839a209d53323ccc9ed4c00", "https://esm.sh/jszip@3.7.1": "f3872a819b015715edb05f81d973b5cd05d3d213d8eb28293ca5471fe7a71773", "https://esm.sh/v135/jszip@3.7.1/denonext/jszip.mjs": "d31d7f9e0de9c6db3c07ca93f7301b756273d4dccb41b600461978fc313504c9" } diff --git a/deps/install.ts b/deps/install.ts new file mode 100644 index 0000000..ba2dc07 --- /dev/null +++ b/deps/install.ts @@ -0,0 +1 @@ +export { default as xdg } from "https://deno.land/x/xdg_portable@v10.6.0/src/mod.deno.ts"; diff --git a/docs/manual.md b/docs/manual.md index ccedea2..f4dedf3 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -17,7 +17,7 @@ There are installer scripts available in the repo. ```bash # stable -curl -fsSL https://raw.github.com/metatypedev/ghjk/v0.3.0/install.sh | bash +curl -fsSL https://raw.github.com/metatypedev/ghjk/v0.3.0-rc.1/install.sh | bash ``` This will install the CLI and add configuration your shell rc files the necessary hooks ghjk needs to function. @@ -39,7 +39,7 @@ Look through the following snippet to understand the basic structure of a `ghjk. ```ts // import the file function from `mod.ts` using the version of ghjk // one's using. For example -// https://raw.github.com/metatypedev/ghjk/v0.3.0/ +// https://raw.github.com/metatypedev/ghjk/v0.3.0-rc.1/ import { file } from ".../mod.ts"; // import the port for the node program import node from ".../ports/node.ts"; @@ -412,7 +412,7 @@ Namely, it's good practice to: ```dockerfile # sample of how one would install ghjk for use in a Dockerfile -ARG GHJK_VERSION=v0.3.0 +ARG GHJK_VERSION=v0.3.0-rc.1 # /usr/bin is available in $PATH by default making ghjk immediately avail RUN curl -fsSL https://raw.github.com/metatypedev/ghjk/$GHJK_VERSION/install.sh \ | GHJK_INSTALL_EXE_DIR=/usr/bin sh diff --git a/ghjk.ts b/ghjk.ts index 3b0c45f..54b207f 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -8,32 +8,64 @@ import { sedLock } from "./std.ts"; import { downloadFile, DownloadFileArgs } from "./utils/mod.ts"; import { unarchive } from "./utils/unarchive.ts"; +// keep in sync with the deno repo's ./rust-toolchain.toml +const RUST_VERSION = "1.82.0"; + +const installs = { + rust: ports.rust({ + version: RUST_VERSION, + profile: "default", + components: ["rust-src"], + }), +}; + config({ defaultEnv: "dev", enableRuntimes: true, - allowedBuildDeps: [ports.cpy_bs({ version: "3.12.7" })], + allowedBuildDeps: [ports.cpy_bs({ version: "3.13.1" }), installs.rust], }); env("main").vars({ - RUST_LOG: "trace,deno=info,denort=trace,swc_ecma_transforms_base=info", + RUST_LOG: [ + "info", + Object.entries({ + "TRACE": [ + // "denort", + // "deno", + ], + "DEBUG": [ + // "runtime", + // "tokio", + ], + "INFO": [ + "deno::npm", + "deno::file_fetcher", + "swc_ecma_transforms_base", + "swc_common", + "h2", + "rustls", + "mio", + "hyper_util", + ], + }).flatMap(([level, modules]) => + modules.map((module) => `${module}=${level.toLowerCase()}`) + ), + ].join(), }); env("_rust") .install( + // TODO: cmake ports.protoc(), ports.pipi({ packageName: "cmake" })[0], - // keep in sync with deno's reqs - ports.rust({ - version: "1.82.0", - profile: "default", - components: ["rust-src"], - }), + installs.rust, ); const RUSTY_V8_MIRROR = `${import.meta.dirname}/.dev/rusty_v8`; env("dev") .inherit("_rust") + .install(ports.cargobi({ crateName: "tokio-console" })) .vars({ // V8_FORCE_DEBUG: "true", RUSTY_V8_MIRROR, @@ -50,7 +82,7 @@ if (Deno.build.os == "linux" && !Deno.env.has("NO_MOLD")) { // these are just for quick testing install(); -const DENO_VERSION = "2.0.6"; +const DENO_VERSION = "2.1.2"; // these are used for developing ghjk install( @@ -64,7 +96,7 @@ task( "cache-v8", { desc: "Install the V8 builds to a local cache.", - inherit: "_rust", + inherit: false, fn: async ($) => { const tmpDirPath = await Deno.makeTempDir({}); const v8Versions = [ @@ -108,24 +140,20 @@ task( task( "lock-sed", async ($) => { - const GHJK_VERSION = "0.3.0"; + const GHJK_VERSION = "0.3.0-rc.1"; await sedLock( $.path(import.meta.dirname!), { lines: { + "./rust-toolchain.toml": [ + [/^(channel = ").*(")/, RUST_VERSION], + ], "./Cargo.toml": [ [/^(version = ").*(")/, GHJK_VERSION], ], "./.github/workflows/*.yml": [ [/(DENO_VERSION: ").*(")/, DENO_VERSION], ], - "./host/mod.ts": [ - [/(GHJK_VERSION = ").*(")/, GHJK_VERSION], - ], - "./install.sh": [ - [/(GHJK_VERSION="\$\{GHJK_VERSION:-v).*(\}")/, GHJK_VERSION], - [/(DENO_VERSION="\$\{DENO_VERSION:-v).*(\}")/, DENO_VERSION], - ], "./docs/*.md": [ [ /(.*\/metatypedev\/ghjk\/v)[^/]*(\/.*)/, @@ -142,6 +170,13 @@ task( GHJK_VERSION, ], ], + "**/Cargo.toml": [ + [/^(version = ").+(")/, GHJK_VERSION], + [ + /(deno\s*=\s*\{\s*git\s*=\s*"https:\/\/github\.com\/metatypedev\/deno"\s*,\s*branch\s*=\s*"v).+(-embeddable"\s*\})/, + DENO_VERSION, + ], + ], }, ignores: [ // ignore this file to avoid hits on the regexps @@ -162,4 +197,5 @@ task( }, ); }, + { inherits: false }, ); diff --git a/host/mod.ts b/host/mod.ts deleted file mode 100644 index 651a9b8..0000000 --- a/host/mod.ts +++ /dev/null @@ -1,625 +0,0 @@ -import { cliffy_cmd, deep_eql, zod, zod_val_err } from "../deps/cli.ts"; -import logger from "../utils/logger.ts"; -import { - $, - bufferHashAsync, - Json, - objectHash, - Path, - stringHash, -} from "../utils/mod.ts"; -import validators, { SerializedConfig } from "./types.ts"; -import * as std_modules from "../modules/std.ts"; -import * as denoFile from "../files/deno/mod.ts"; -import { task$ } from "../files/mod.ts"; -import type { ModuleBase } from "../modules/mod.ts"; -import { GhjkCtx } from "../modules/types.ts"; -import { serializePlatform } from "../modules/ports/types/platform.ts"; -import { default as initTasks } from "./init/mod.ts"; - -export interface CliArgs { - ghjkShareDir: string; - ghjkfilePath?: string; - ghjkDirPath?: string; - reFlagSet: boolean; - lockedFlagSet: boolean; -} - -type HostCtx = { - fileHashMemoStore: Map>; - curEnvVars: Record; - reFlagSet: boolean; - lockedFlagSet: boolean; -}; - -const GHJK_VERSION = "0.3.0"; - -export async function cli(args: CliArgs) { - logger().debug(`ghjk CLI`, GHJK_VERSION); - if (args.reFlagSet && args.lockedFlagSet) { - throw new Error("GHJK_LOCKED && GHJK_RE both set"); - } - // items to run at end of function - const defer = [] as (() => Promise)[]; - - const ghjkShareDir = $.path(args.ghjkShareDir).resolve().normalize(); - let serializedConfig: object | undefined; - let gcx: GhjkCtx | undefined; - - if (!args.ghjkDirPath && args.ghjkfilePath) { - args.ghjkDirPath = $.path(args.ghjkfilePath).parentOrThrow().join(".ghjk") - .toString(); - } - - const subcmds: Record = {}; - - // most of the CLI is only avail if there's a - // ghjkfile detected - if (args.ghjkDirPath) { - gcx = { - ghjkShareDir, - ghjkDir: $.path(args.ghjkDirPath).resolve().normalize(), - ghjkfilePath: args.ghjkfilePath - ? $.path(args.ghjkfilePath).resolve().normalize() - : undefined, - blackboard: new Map(), - }; - const hcx: HostCtx = { - fileHashMemoStore: new Map(), - curEnvVars: Deno.env.toObject(), - reFlagSet: args.reFlagSet, - lockedFlagSet: args.lockedFlagSet, - }; - logger().debug("context established", { - ghjkDir: gcx?.ghjkDir.toString(), - ghjkfilePath: gcx.ghjkfilePath?.toString(), - }); - - if (!await gcx.ghjkDir.join(".gitignore").exists()) { - gcx.ghjkDir.join(".gitignore").writeText($.dedent` - envs - hash.json`); - } - - // this returns nothing if no valid lockifle or ghjkfile - // is found - const commands = await commandsFromConfig(hcx, gcx); - if (commands) { - serializedConfig = commands.config; - // lock entries are also generated across program usage - // so we defer another write out until the end - defer.push(commands.writeLockFile); - - for ( - const [cmdName, [cmd, src]] of Object.entries(commands.subCommands) - ) { - const conflict = subcmds[cmdName]; - if (conflict) { - throw new Error( - `CLI command conflict under name "${cmdName}" from host and module "${src}"`, - ); - } - subcmds[cmdName] = cmd; - } - } - } - - const initCmd = new cliffy_cmd.Command() - .description("Commands for setting up cwd for ghjk.") - .action(function () { - this.showHelp(); - }); - for (const [name, def] of Object.entries(initTasks)) { - initCmd.command( - name.replace("init-", ""), - new cliffy_cmd.Command() - .description(def.desc!) - .useRawArgs() - .action(async (_, ...argv) => { - const env = Deno.env.toObject(); - const workingDir = Deno.cwd(); - const dollar = task$(argv, env, workingDir, name); - await def.fn!(dollar, { argv, workingDir, env, $: dollar }); - }), - ); - } - - const root = new cliffy_cmd.Command() - .name("ghjk") - .version(GHJK_VERSION) - .description("Programmable runtime manager.") - .action(function () { - this.showHelp(); - }) - .command( - "init", - initCmd, - ) - .command( - "print", - new cliffy_cmd.Command() - .description("Emit different discovered and built values to stdout.") - .action(function () { - this.showHelp(); - }) - .command( - "share-dir-path", - new cliffy_cmd.Command() - .description("Print the path where ghjk is installed in.") - .action(function () { - if (!ghjkShareDir) { - throw new Error("no ghjkfile found."); - } - // deno-lint-ignore no-console - console.log(ghjkShareDir.toString()); - }), - ) - .command( - "ghjkdir-path", - new cliffy_cmd.Command() - .description("Print the path where ghjk is installed in.") - .action(function () { - if (!gcx) { - throw new Error("no ghjkfile found."); - } - // deno-lint-ignore no-console - console.log(gcx.ghjkDir.toString()); - }), - ) - .command( - "ghjkfile-path", - new cliffy_cmd.Command() - .description("Print the path of the ghjk.ts used.") - .action(function () { - if (!gcx?.ghjkfilePath) { - throw new Error("no ghjkfile found."); - } - // deno-lint-ignore no-console - console.log(gcx.ghjkfilePath.toString()); - }), - ) - .command( - "config", - new cliffy_cmd.Command() - .description( - "Print the extracted and serialized config from the ghjkfile.", - ) - .option( - "--json", - `Use json format when printing config.`, - ) - .action(function ({ json }) { - if (!serializedConfig) { - throw new Error("no ghjkfile found."); - } - // deno-lint-ignore no-console - console.log( - json - ? JSON.stringify(serializedConfig) - : $.inspect(serializedConfig), - ); - }), - ), - ) - .command( - "completions", - new cliffy_cmd.CompletionsCommand(), - ) - .command( - "deno", - new cliffy_cmd.Command() - .description("Access the deno cli.") - .useRawArgs() - .action(async function (_, ...args) { - logger().debug(args); - await $.raw`${Deno.execPath()} ${args}` - .env("DENO_EXEC_PATH", Deno.execPath()); - }), - ); - - for (const [name, subcmd] of Object.entries(subcmds)) { - root.command(name, subcmd); - } - - try { - await root.parse(Deno.args); - } catch (err) { - logger().error(err); - Deno.exit(1); - } finally { - await Promise.all(defer.map((fn) => fn())); - } -} - -async function commandsFromConfig(hcx: HostCtx, gcx: GhjkCtx) { - const lockFilePath = gcx.ghjkDir.join("lock.json"); - const hashFilePath = gcx.ghjkDir.join("hash.json"); - - const foundLockObj = await readLockFile(lockFilePath); - const foundHashObj = await readHashFile(hashFilePath); - - if (hcx.lockedFlagSet) { - if (!foundLockObj) { - throw new Error("GHJK_LOCKED set but no lockfile found"); - } - if (!foundHashObj) { - throw new Error("GHJK_LOCKED set but no hashfile found"); - } - } - - const lockEntries = {} as Record; - - const ghjkfileHash = await gcx.ghjkfilePath?.exists() - ? await fileDigestHex(hcx, gcx.ghjkfilePath!) - : undefined; - - if (!hcx.reFlagSet && foundLockObj) { - logger().debug("loading lockfile", lockFilePath); - for (const man of foundLockObj.config.modules) { - const mod = std_modules.map[man.id]; - if (!mod) { - throw new Error( - `unrecognized module specified by lockfile config: ${man.id}`, - ); - } - const entry = foundLockObj.moduleEntries[man.id]; - if (!entry) { - throw new Error( - `no lock entry found for module specified by lockfile config: ${man.id}`, - ); - } - const instance: ModuleBase = new mod.ctor(gcx); - lockEntries[man.id] = await instance.loadLockEntry( - entry as Json, - ); - } - } - - let configExt: SerializedConfigExt | null = null; - let wasReSerialized = false; - if ( - !hcx.reFlagSet && - foundLockObj && - foundHashObj && - (hcx.lockedFlagSet || - // avoid reserializing the config if - // the ghjkfile and environment is _satisfcatorily_ - // similar. "cache validation" - foundLockObj.version == "0" && - await isHashFileValid(hcx, foundLockObj, foundHashObj, ghjkfileHash)) - ) { - configExt = { - config: foundLockObj.config, - envVarHashes: foundHashObj.envVarHashes, - readFileHashes: foundHashObj.readFileHashes, - listedFiles: foundHashObj.listedFiles, - }; - } else if (gcx.ghjkfilePath) { - logger().info("serializing ghjkfile", gcx.ghjkfilePath); - configExt = await readGhjkfile(hcx, gcx.ghjkfilePath); - wasReSerialized = true; - } else { - // nothing to get the commands from - return; - } - - const newHashObj: zod.infer = { - version: "0", - ghjkfileHash, - envVarHashes: configExt.envVarHashes, - readFileHashes: configExt.readFileHashes, - listedFiles: configExt.listedFiles, - }; - // command name to [cmd, source module id] - const subCommands = {} as Record; - const instances = [] as [string, ModuleBase][]; - - for (const man of configExt.config.modules) { - const mod = std_modules.map[man.id]; - if (!mod) { - throw new Error(`unrecognized module specified by ghjk.ts: ${man.id}`); - } - const instance: ModuleBase = new mod.ctor(gcx); - await instance.loadConfig( - man, - configExt.config.blackboard, - lockEntries[man.id], - ); - instances.push([man.id, instance] as const); - for (const [cmdName, cmd] of Object.entries(instance.commands())) { - const conflict = subCommands[cmdName]; - if (conflict) { - throw new Error( - `CLI command conflict under name "${cmdName}" from modules "${man.id}" & "${ - conflict[1] - }"`, - ); - } - subCommands[cmdName] = [cmd, man.id]; - } - } - - // `writeLockFile` can be invoked multiple times - // so we keep track of the last lockfile wrote - // out to disk - // TODO(#90): file system lock file while ghjk is running - // to avoid multiple instances from clobbering each other - let lastLockObj = { ...foundLockObj }; - return { - subCommands, - config: configExt.config, - async writeLockFile() { - if (hcx.lockedFlagSet) return; - - const newLockObj: zod.infer = { - version: "0", - platform: serializePlatform(Deno.build), - moduleEntries: {} as Record, - config: configExt!.config, - }; - - // generate the lock entries after *all* the modules - // are done processing their config to allow - // any shared stores to be properly populated - // e.g. the resolution memo store - newLockObj.moduleEntries = Object.fromEntries( - await Array.fromAsync( - instances.map( - async ( - [id, instance], - ) => [id, await instance.genLockEntry()], - ), - ), - ); - // avoid writing lockfile if nothing's changed - if (!lastLockObj || !deep_eql(newLockObj, lastLockObj)) { - lastLockObj = { ...newLockObj }; - await lockFilePath.writeJsonPretty(newLockObj); - } - - // we only write out hashfile when the serialization - // result was saved in the lock file - if ( - !hcx.lockedFlagSet && wasReSerialized && ( - !foundHashObj || !deep_eql(newHashObj, foundHashObj) - ) - ) { - await hashFilePath.writeJsonPretty(newHashObj); - } - }, - }; -} - -async function isHashFileValid( - hcx: HostCtx, - foundLockFile: zod.infer, - foundHashFile: zod.infer, - ghjkfileHash?: string, -) { - // TODO: figure out cross platform lockfiles :O - const platformMatch = () => - serializePlatform(Deno.build) == foundLockFile.platform; - - const envHashesMatch = () => { - const oldHashes = foundHashFile!.envVarHashes; - const newHashes = envVarDigests(hcx.curEnvVars, [ - ...Object.keys(oldHashes), - ]); - return deep_eql(oldHashes, newHashes); - }; - - const cwd = $.path(Deno.cwd()); - const fileHashesMatch = async () => { - const oldHashes = foundHashFile!.readFileHashes; - const newHashes = await fileDigests(hcx, [ - ...Object.keys(oldHashes), - ], cwd); - return deep_eql(oldHashes, newHashes); - }; - - const fileListingsMatch = async () => { - const oldListed = foundHashFile!.listedFiles; - for (const path of oldListed) { - if (!await cwd.resolve(path).exists()) { - return false; - } - } - return true; - }; - // NOTE: these are ordered by the amount effort it takes - // to check each - // we only check file hash of the ghjk file if it's present - return (ghjkfileHash ? foundHashFile.ghjkfileHash == ghjkfileHash : true) && - platformMatch() && - envHashesMatch() && - await fileListingsMatch() && - await fileHashesMatch(); -} - -type DigestsMap = Record; - -type SerializedConfigExt = Awaited< - ReturnType ->; - -async function readGhjkfile( - hcx: HostCtx, - configPath: Path, -) { - switch (configPath.extname()) { - case "": - logger().warn("config file has no extension, assuming deno config"); - /* falls through */ - case ".ts": { - logger().debug("serializing ts config", configPath); - const res = await denoFile.getSerializedConfig( - configPath.toFileUrl().href, - hcx.curEnvVars, - ); - const envVarHashes = envVarDigests(hcx.curEnvVars, res.accessedEnvKeys); - const cwd = $.path(Deno.cwd()); - const cwdStr = cwd.toString(); - const listedFiles = res.listedFiles - .map((path) => cwd.resolve(path).toString().replace(cwdStr, ".")); - // FIXME: this breaks if the version of the file the config reads - // has changed by this point - // consider reading mtime of files when read by the serializer and comparing - // them before hashing to make sure we get the same file - // not sure what to do if it has changed though, re-serialize? - const readFileHashes = await fileDigests(hcx, res.readFiles, cwd); - - return { - config: validateRawConfig(res.config, configPath), - envVarHashes, - readFileHashes, - listedFiles, - }; - } - // case ".jsonc": - // case ".json": - // raw = await configPath.readJson(); - // break; - default: - throw new Error( - `unrecognized ghjkfile type provided at path: ${configPath}`, - ); - } -} - -function validateRawConfig( - raw: unknown, - configPath: Path, -): SerializedConfig { - try { - return validators.serializedConfig.parse(raw); - } catch (err) { - const validationError = zod_val_err.fromError(err); - throw new Error( - `error parsing seralized config from ${configPath}: ${validationError.toString()}`, - { - cause: validationError, - }, - ); - } -} - -const lockObjValidator = zod.object({ - version: zod.string(), - platform: zod.string(), // TODO custom validator?? - moduleEntries: zod.record(zod.string(), zod.unknown()), - config: validators.serializedConfig, -}); - -/** - * The lock.json file stores the serialized config and some entries - * from modules. It's primary purpose is as a memo store to avoid - * re-serialization on each CLI invocation. - */ -async function readLockFile(lockFilePath: Path) { - const rawStr = await lockFilePath.readMaybeText(); - if (!rawStr) return; - try { - const rawJson = JSON.parse(rawStr); - return lockObjValidator.parse(rawJson); - } catch (err) { - const validationError = zod_val_err.fromError(err); - logger().error( - `error parsing lockfile from ${lockFilePath}: ${validationError.toString()}`, - ); - if (Deno.stderr.isTerminal() && await $.confirm("Discard lockfile?")) { - return; - } else { - throw validationError; - } - } -} - -const hashObjValidator = zod.object({ - version: zod.string(), - ghjkfileHash: zod.string().nullish(), - envVarHashes: zod.record(zod.string(), zod.string().nullish()), - readFileHashes: zod.record(zod.string(), zod.string().nullish()), - listedFiles: zod.string().array(), - // TODO: track listed dirs in case a `walk`ed directory has a new entry -}); - -/** - * The hash.json file stores the digests of all external accesses - * of a ghjkfile during serialization. The primary purpose is to - * do "cache invalidation" on ghjkfiles, re-serializing them if - * any of the digests change. - */ -async function readHashFile(hashFilePath: Path) { - const rawStr = await hashFilePath.readMaybeText(); - if (!rawStr) return; - try { - const rawJson = JSON.parse(rawStr); - return hashObjValidator.parse(rawJson); - } catch (err) { - logger().error( - `error parsing hashfile from ${hashObjValidator}: ${ - zod_val_err.fromError(err).toString() - }`, - ); - logger().warn("discarding invalid hashfile"); - return; - } -} - -function envVarDigests(all: Record, accessed: string[]) { - const hashes = {} as DigestsMap; - for (const key of accessed) { - const val = all[key]; - if (!val) { - // use null if the serializer accessed - hashes[key] = null; - } else { - hashes[key] = stringHash(val); - } - } - return hashes; -} - -async function fileDigests(hcx: HostCtx, readFiles: string[], cwd: Path) { - const cwdStr = cwd.toString(); - const readFileHashes = {} as DigestsMap; - await Promise.all(readFiles.map(async (pathStr) => { - const path = cwd.resolve(pathStr); - const relativePath = path - .toString() - .replace(cwdStr, "."); - // FIXME: stream read into hash to improve mem usage - const stat = await path.lstat(); - if (stat) { - const contentHash = (stat.isFile || stat.isSymlink) - ? await fileDigestHex(hcx, path) - : null; - readFileHashes[relativePath] = objectHash({ - ...JSON.parse(JSON.stringify(stat)), - contentHash, - }); - } else { - readFileHashes[relativePath] = null; - } - })); - return readFileHashes; -} - -/** - * Returns the hash digest of a file. Makes use of a memo - * to dedupe work. - */ -function fileDigestHex(hcx: HostCtx, path: Path) { - const absolute = path.resolve().toString(); - let promise = hcx.fileHashMemoStore.get(absolute); - if (!promise) { - promise = inner(); - hcx.fileHashMemoStore.set(absolute, promise); - } - return promise; - async function inner() { - return await bufferHashAsync( - await path.readBytes(), - ); - } -} diff --git a/install.sh b/install.sh index 30c3475..1eaa503 100755 --- a/install.sh +++ b/install.sh @@ -2,33 +2,173 @@ set -e -u -GHJK_VERSION="${GHJK_VERSION:-v0.3.0}" -GHJK_INSTALLER_URL="${GHJK_INSTALLER_URL:-https://raw.github.com/metatypedev/ghjk/$GHJK_VERSION/install.ts}" -GHJK_SHARE_DIR="${GHJK_SHARE_DIR:-$HOME/.local/share/ghjk}" -DENO_VERSION="${DENO_VERSION:-v2.0.6}" +if ! command -v curl >/dev/null; then + echo "Error: curl is required to install ghjk." 1>&2 + exit 1 +fi + +if ! command -v tar >/dev/null; then + echo "Error: tar is required to install ghjk." 1>&2 + exit 1 +fi + +ORG=metatypedev +REPO=ghjk +EXT=tar.gz +NAME=ghjk +EXE=ghjk + +INSTALLER_URL="https://raw.githubusercontent.com/$ORG/$REPO/main/install.sh" +RELEASE_URL="https://github.com/$ORG/$REPO/releases" + +LATEST_VERSION=$(curl "$RELEASE_URL/latest" -s -L -I -o /dev/null -w '%{url_effective}') +LATEST_VERSION="${LATEST_VERSION##*v}" + +PLATFORM="${PLATFORM:-}" +TMP_DIR=$(mktemp -d) +GHJK_INSTALL_EXEC_DIR="${GHJK_INSTALL_EXEC_DIR:-$HOME/.local/bin}" +VERSION="${VERSION:-$LATEST_VERSION}" # make sure the version is prepended with v -if [ "${DENO_VERSION#"v"}" = "$DENO_VERSION" ]; then - DENO_VERSION="v$DENO_VERSION" +if [ "${VERSION#"v"}" = "$VERSION" ]; then + VERSION="v$VERSION" +fi + +if [ "${PLATFORM:-x}" = "x" ]; then + MACHINE=$(uname -m) + case "$(uname -s | tr '[:upper:]' '[:lower:]')" in + "linux") + case "$MACHINE" in + "arm64"* | "aarch64"* ) PLATFORM='aarch64-unknown-linux-gnu' ;; + *"64") PLATFORM='x86_64-unknown-linux-gnu' ;; + esac + ;; + "darwin") + case "$MACHINE" in + "arm64"* | "aarch64"* ) PLATFORM='aarch64-apple-darwin' ;; + *"64") PLATFORM='x86_64-apple-darwin' ;; + esac + ;; + "msys"*|"cygwin"*|"mingw"*|*"_nt"*|"win"*) + case "$MACHINE" in + *"64") PLATFORM='x86_64-pc-windows-msvc' ;; + esac + ;; + esac + if [ "${PLATFORM:-x}" = "x" ]; then + cat >&2 <&2 </dev/null; then - echo "Error: curl is required to install deno for ghjk." 1>&2 - exit 1 - fi +EOF + if [ ! -d "${GHJK_INSTALL_EXEC_DIR}" ]; then + mkdir -p "$GHJK_INSTALL_EXEC_DIR" + fi - curl -fsSL https://deno.land/x/install/install.sh | DENO_INSTALL="$GHJK_SHARE_DIR" sh -s "$DENO_VERSION" >/dev/null - fi + if [ -w "${GHJK_INSTALL_EXEC_DIR}" ]; then + printf "Press enter to continue (or cancel with Ctrl+C):" >&2 + read -r _throwaway + mv "$TMP_DIR/$EXE" "$GHJK_INSTALL_EXEC_DIR" + else + echo "$GHJK_INSTALL_EXEC_DIR is not writable." + exit 1 + fi fi -export GHJK_SHARE_DIR -export GHJK_INSTALL_DENO_EXEC -"$GHJK_INSTALL_DENO_EXEC" run -A "$GHJK_INSTALLER_URL" +GHJK_INSTALLER_URL="${GHJK_INSTALLER_URL:-https://raw.github.com/$ORG/$REPO/$VERSION/install.ts}" +"$TMP_DIR/$EXE" deno run -A "$GHJK_INSTALLER_URL" + +rm -r "$TMP_DIR" + +SHELL_TYPE=$(basename "$SHELL") + +case $SHELL_TYPE in + bash|zsh|ksh) + SHELL_CONFIG="$HOME/.$SHELL_TYPE"rc + ;; + fish) + SHELL_CONFIG="$HOME/.config/fish/config.fish" + ;; + *) + SHELL_CONFIG="" +esac + +if [ -n "$SHELL_CONFIG" ]; then + printf "\nDetected shell: %s\n" "$SHELL_TYPE" + echo "Do you want to append the new PATH to your configuration ($SHELL_CONFIG)? (y/n): " >&2 + read -r answer + + answer=$(echo "$answer" | tr "[:upper:]" "[:lower:]") + + case $SHELL_TYPE in + bash|zsh|ksh) + APPEND_CMD="export PATH=\"$GHJK_INSTALL_EXEC_DIR:\$PATH\"" + ;; + fish) + APPEND_CMD="fish_add_path $GHJK_INSTALL_EXEC_DIR" + ;; + esac + + if [ "$answer" = "y" ] || [ "$answer" = "yes" ]; then + echo "$APPEND_CMD" >> "$SHELL_CONFIG" + printf "Path added to %s\nRun 'source %s' to apply changes." "$SHELL_CONFIG" "$SHELL_CONFIG" + else + cat < str.trim()) @@ -24,20 +27,11 @@ if (import.meta.main) { // } await install({ ...defaultInstallArgs, - ghjkShareDir: Deno.env.get("GHJK_SHARE_DIR") ?? - defaultInstallArgs.ghjkShareDir, - skipExecInstall: !!skipBinInstall && skipBinInstall != "0" && - skipBinInstall != "false", + ghjkDataDir: Deno.env.get("GHJK_DATA_DIR") ?? + defaultInstallArgs.ghjkDataDir, shellsToHook, - ghjkExecInstallDir: Deno.env.get("GHJK_INSTALL_EXE_DIR") ?? - defaultInstallArgs.ghjkExecInstallDir, - ghjkExecDenoExec: Deno.env.get("GHJK_INSTALL_DENO_EXEC") ?? - defaultInstallArgs.ghjkExecDenoExec, shellHookMarker: Deno.env.get("GHJK_INSTALL_HOOK_MARKER") ?? defaultInstallArgs.shellHookMarker, - noLockfile: !!noLockfile && noLockfile != "0" && noLockfile != "false", - ghjkDenoCacheDir: Deno.env.get("GHJK_INSTALL_DENO_DIR") ?? - defaultInstallArgs.ghjkDenoCacheDir, }); } else { throw new Error( diff --git a/install/bash-preexec.sh b/install/bash-preexec.sh new file mode 100644 index 0000000..29c3f06 --- /dev/null +++ b/install/bash-preexec.sh @@ -0,0 +1,353 @@ +# bash-preexec.sh -- Bash support for ZSH-like 'preexec' and 'precmd' functions. +# https://github.com/rcaloras/bash-preexec +# +# +# 'preexec' functions are executed before each interactive command is +# executed, with the interactive command as its argument. The 'precmd' +# function is executed before each prompt is displayed. +# +# Author: Ryan Caloras (ryan@bashhub.com) +# Forked from Original Author: Glyph Lefkowitz +# +# V0.5.0 +# + +# General Usage: +# +# 1. Source this file at the end of your bash profile so as not to interfere +# with anything else that's using PROMPT_COMMAND. +# +# 2. Add any precmd or preexec functions by appending them to their arrays: +# e.g. +# precmd_functions+=(my_precmd_function) +# precmd_functions+=(some_other_precmd_function) +# +# preexec_functions+=(my_preexec_function) +# +# 3. Consider changing anything using the DEBUG trap or PROMPT_COMMAND +# to use preexec and precmd instead. Preexisting usages will be +# preserved, but doing so manually may be less surprising. +# +# Note: This module requires two Bash features which you must not otherwise be +# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. If you override +# either of these after bash-preexec has been installed it will most likely break. + +# Make sure this is bash that's running and return otherwise. +if [[ -z "${BASH_VERSION:-}" ]]; then + return 1; +fi + +# Avoid duplicate inclusion +if [[ -n "${bash_preexec_imported:-}" ]]; then + return 0 +fi +bash_preexec_imported="defined" + +# WARNING: This variable is no longer used and should not be relied upon. +# Use ${bash_preexec_imported} instead. +__bp_imported="${bash_preexec_imported}" + +# Should be available to each precmd and preexec +# functions, should they want it. $? and $_ are available as $? and $_, but +# $PIPESTATUS is available only in a copy, $BP_PIPESTATUS. +# TODO: Figure out how to restore PIPESTATUS before each precmd or preexec +# function. +__bp_last_ret_value="$?" +BP_PIPESTATUS=("${PIPESTATUS[@]}") +__bp_last_argument_prev_command="$_" + +__bp_inside_precmd=0 +__bp_inside_preexec=0 + +# Initial PROMPT_COMMAND string that is removed from PROMPT_COMMAND post __bp_install +__bp_install_string=$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_install' + +# Fails if any of the given variables are readonly +# Reference https://stackoverflow.com/a/4441178 +__bp_require_not_readonly() { + local var + for var; do + if ! ( unset "$var" 2> /dev/null ); then + echo "bash-preexec requires write access to ${var}" >&2 + return 1 + fi + done +} + +# Remove ignorespace and or replace ignoreboth from HISTCONTROL +# so we can accurately invoke preexec with a command from our +# history even if it starts with a space. +__bp_adjust_histcontrol() { + local histcontrol + histcontrol="${HISTCONTROL:-}" + histcontrol="${histcontrol//ignorespace}" + # Replace ignoreboth with ignoredups + if [[ "$histcontrol" == *"ignoreboth"* ]]; then + histcontrol="ignoredups:${histcontrol//ignoreboth}" + fi; + export HISTCONTROL="$histcontrol" +} + +# This variable describes whether we are currently in "interactive mode"; +# i.e. whether this shell has just executed a prompt and is waiting for user +# input. It documents whether the current command invoked by the trace hook is +# run interactively by the user; it's set immediately after the prompt hook, +# and unset as soon as the trace hook is run. +__bp_preexec_interactive_mode="" + +# These arrays are used to add functions to be run before, or after, prompts. +declare -a precmd_functions +declare -a preexec_functions + +# Trims leading and trailing whitespace from $2 and writes it to the variable +# name passed as $1 +__bp_trim_whitespace() { + local var=${1:?} text=${2:-} + text="${text#"${text%%[![:space:]]*}"}" # remove leading whitespace characters + text="${text%"${text##*[![:space:]]}"}" # remove trailing whitespace characters + printf -v "$var" '%s' "$text" +} + + +# Trims whitespace and removes any leading or trailing semicolons from $2 and +# writes the resulting string to the variable name passed as $1. Used for +# manipulating substrings in PROMPT_COMMAND +__bp_sanitize_string() { + local var=${1:?} text=${2:-} sanitized + __bp_trim_whitespace sanitized "$text" + sanitized=${sanitized%;} + sanitized=${sanitized#;} + __bp_trim_whitespace sanitized "$sanitized" + printf -v "$var" '%s' "$sanitized" +} + +# This function is installed as part of the PROMPT_COMMAND; +# It sets a variable to indicate that the prompt was just displayed, +# to allow the DEBUG trap to know that the next command is likely interactive. +__bp_interactive_mode() { + __bp_preexec_interactive_mode="on"; +} + + +# This function is installed as part of the PROMPT_COMMAND. +# It will invoke any functions defined in the precmd_functions array. +__bp_precmd_invoke_cmd() { + # Save the returned value from our last command, and from each process in + # its pipeline. Note: this MUST be the first thing done in this function. + __bp_last_ret_value="$?" BP_PIPESTATUS=("${PIPESTATUS[@]}") + + # Don't invoke precmds if we are inside an execution of an "original + # prompt command" by another precmd execution loop. This avoids infinite + # recursion. + if (( __bp_inside_precmd > 0 )); then + return + fi + local __bp_inside_precmd=1 + + # Invoke every function defined in our function array. + local precmd_function + for precmd_function in "${precmd_functions[@]}"; do + + # Only execute this function if it actually exists. + # Test existence of functions with: declare -[Ff] + if type -t "$precmd_function" 1>/dev/null; then + __bp_set_ret_value "$__bp_last_ret_value" "$__bp_last_argument_prev_command" + # Quote our function invocation to prevent issues with IFS + "$precmd_function" + fi + done + + __bp_set_ret_value "$__bp_last_ret_value" +} + +# Sets a return value in $?. We may want to get access to the $? variable in our +# precmd functions. This is available for instance in zsh. We can simulate it in bash +# by setting the value here. +__bp_set_ret_value() { + return ${1:-} +} + +__bp_in_prompt_command() { + + local prompt_command_array + IFS=$'\n;' read -rd '' -a prompt_command_array <<< "${PROMPT_COMMAND:-}" + + local trimmed_arg + __bp_trim_whitespace trimmed_arg "${1:-}" + + local command trimmed_command + for command in "${prompt_command_array[@]:-}"; do + __bp_trim_whitespace trimmed_command "$command" + if [[ "$trimmed_command" == "$trimmed_arg" ]]; then + return 0 + fi + done + + return 1 +} + +# This function is installed as the DEBUG trap. It is invoked before each +# interactive prompt display. Its purpose is to inspect the current +# environment to attempt to detect if the current command is being invoked +# interactively, and invoke 'preexec' if so. +__bp_preexec_invoke_exec() { + + # Save the contents of $_ so that it can be restored later on. + # https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702 + __bp_last_argument_prev_command="${1:-}" + # Don't invoke preexecs if we are inside of another preexec. + if (( __bp_inside_preexec > 0 )); then + return + fi + local __bp_inside_preexec=1 + + # Checks if the file descriptor is not standard out (i.e. '1') + # __bp_delay_install checks if we're in test. Needed for bats to run. + # Prevents preexec from being invoked for functions in PS1 + if [[ ! -t 1 && -z "${__bp_delay_install:-}" ]]; then + return + fi + + if [[ -n "${COMP_LINE:-}" ]]; then + # We're in the middle of a completer. This obviously can't be + # an interactively issued command. + return + fi + if [[ -z "${__bp_preexec_interactive_mode:-}" ]]; then + # We're doing something related to displaying the prompt. Let the + # prompt set the title instead of me. + return + else + # If we're in a subshell, then the prompt won't be re-displayed to put + # us back into interactive mode, so let's not set the variable back. + # In other words, if you have a subshell like + # (sleep 1; sleep 2) + # You want to see the 'sleep 2' as a set_command_title as well. + if [[ 0 -eq "${BASH_SUBSHELL:-}" ]]; then + __bp_preexec_interactive_mode="" + fi + fi + + if __bp_in_prompt_command "${BASH_COMMAND:-}"; then + # If we're executing something inside our prompt_command then we don't + # want to call preexec. Bash prior to 3.1 can't detect this at all :/ + __bp_preexec_interactive_mode="" + return + fi + + local this_command + this_command=$( + export LC_ALL=C + HISTTIMEFORMAT= builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //' + ) + + # Sanity check to make sure we have something to invoke our function with. + if [[ -z "$this_command" ]]; then + return + fi + + # Invoke every function defined in our function array. + local preexec_function + local preexec_function_ret_value + local preexec_ret_value=0 + for preexec_function in "${preexec_functions[@]:-}"; do + + # Only execute each function if it actually exists. + # Test existence of function with: declare -[fF] + if type -t "$preexec_function" 1>/dev/null; then + __bp_set_ret_value ${__bp_last_ret_value:-} + # Quote our function invocation to prevent issues with IFS + "$preexec_function" "$this_command" + preexec_function_ret_value="$?" + if [[ "$preexec_function_ret_value" != 0 ]]; then + preexec_ret_value="$preexec_function_ret_value" + fi + fi + done + + # Restore the last argument of the last executed command, and set the return + # value of the DEBUG trap to be the return code of the last preexec function + # to return an error. + # If `extdebug` is enabled a non-zero return value from any preexec function + # will cause the user's command not to execute. + # Run `shopt -s extdebug` to enable + __bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command" +} + +__bp_install() { + # Exit if we already have this installed. + if [[ "${PROMPT_COMMAND:-}" == *"__bp_precmd_invoke_cmd"* ]]; then + return 1; + fi + + trap '__bp_preexec_invoke_exec "$_"' DEBUG + + # Preserve any prior DEBUG trap as a preexec function + local prior_trap=$(sed "s/[^']*'\(.*\)'[^']*/\1/" <<<"${__bp_trap_string:-}") + unset __bp_trap_string + if [[ -n "$prior_trap" ]]; then + eval '__bp_original_debug_trap() { + '"$prior_trap"' + }' + preexec_functions+=(__bp_original_debug_trap) + fi + + # Adjust our HISTCONTROL Variable if needed. + __bp_adjust_histcontrol + + # Issue #25. Setting debug trap for subshells causes sessions to exit for + # backgrounded subshell commands (e.g. (pwd)& ). Believe this is a bug in Bash. + # + # Disabling this by default. It can be enabled by setting this variable. + if [[ -n "${__bp_enable_subshells:-}" ]]; then + + # Set so debug trap will work be invoked in subshells. + set -o functrace > /dev/null 2>&1 + shopt -s extdebug > /dev/null 2>&1 + fi; + + local existing_prompt_command + # Remove setting our trap install string and sanitize the existing prompt command string + existing_prompt_command="${PROMPT_COMMAND:-}" + existing_prompt_command="${existing_prompt_command//$__bp_install_string[;$'\n']}" # Edge case of appending to PROMPT_COMMAND + existing_prompt_command="${existing_prompt_command//$__bp_install_string}" + __bp_sanitize_string existing_prompt_command "$existing_prompt_command" + + # Install our hooks in PROMPT_COMMAND to allow our trap to know when we've + # actually entered something. + PROMPT_COMMAND=$'__bp_precmd_invoke_cmd\n' + if [[ -n "$existing_prompt_command" ]]; then + PROMPT_COMMAND+=${existing_prompt_command}$'\n' + fi; + PROMPT_COMMAND+='__bp_interactive_mode' + + # Add two functions to our arrays for convenience + # of definition. + precmd_functions+=(precmd) + preexec_functions+=(preexec) + + # Invoke our two functions manually that were added to $PROMPT_COMMAND + __bp_precmd_invoke_cmd + __bp_interactive_mode +} + +# Sets an installation string as part of our PROMPT_COMMAND to install +# after our session has started. This allows bash-preexec to be included +# at any point in our bash profile. +__bp_install_after_session_init() { + # bash-preexec needs to modify these variables in order to work correctly + # if it can't, just stop the installation + __bp_require_not_readonly PROMPT_COMMAND HISTCONTROL HISTTIMEFORMAT || return + + local sanitized_prompt_command + __bp_sanitize_string sanitized_prompt_command "${PROMPT_COMMAND:-}" + if [[ -n "$sanitized_prompt_command" ]]; then + PROMPT_COMMAND=${sanitized_prompt_command}$'\n' + fi; + PROMPT_COMMAND+=${__bp_install_string} +} + +# Run our install so long as we're not delaying it. +if [[ -z "${__bp_delay_install:-}" ]]; then + __bp_install_after_session_init +fi; diff --git a/install/ghjk.sh b/install/ghjk.sh deleted file mode 100644 index 49d0d83..0000000 --- a/install/ghjk.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh - -export GHJK_SHARE_DIR="${GHJK_SHARE_DIR:-__GHJK_SHARE_DIR__}" -export DENO_DIR="${GHJK_DENO_DIR:-__DENO_CACHE_DIR}" -export DENO_NO_UPDATE_CHECK=1 -GHJK_MAIN_URL="${GHJK_MAIN_URL:-__MAIN_TS_URL__}" - -# NOTE: avoid putting too much in here as this is only one -# method of getting the ghjk bin which is all ultimately optional -# anyways. - -# NOTE: keep this in sync with impls in install/exec.ts - -# if ghjkfile var is set, set the GHJK_DIR overriding -# any set by the user -if [ -n "${GHJKFILE+x}" ]; then - - GHJK_DIR="$(dirname "$GHJKFILE")/.ghjk" - -# if both GHJKFILE and GHJK_DIR are unset -elif [ -z "${GHJK_DIR+x}" ]; then - - # look for ghjk dirs in parents - cur_dir=$PWD - while true; do - if [ -d "$cur_dir/.ghjk" ] || [ -e "$cur_dir/ghjk.ts" ]; then - GHJK_DIR="$cur_dir/.ghjk" - break - fi - # recursively look in parent directory - next_cur_dir="$(dirname "$cur_dir")" - if [ "$next_cur_dir" = / ] && [ "$cur_dir" = "/" ]; then - break - fi - cur_dir="$next_cur_dir" - done - -fi - -if [ -n "${GHJK_DIR+x}" ]; then - - export GHJK_DIR - mkdir -p "$GHJK_DIR" - lock_flag="--lock $GHJK_DIR/deno.lock" - -else - - lock_flag="--no-lock" - -fi - -# we don't want to quote $lock_flag as it's not exactly a single -# string param to deno -# shellcheck disable=SC2086 -exec __DENO_EXEC__ run __UNSTABLE_FLAGS__ -A $lock_flag $GHJK_MAIN_URL "$@" diff --git a/install/hook.fish b/install/hook.fish index 916890c..0d0d714 100644 --- a/install/hook.fish +++ b/install/hook.fish @@ -109,6 +109,7 @@ function __ghjk_preexec --on-event fish_preexec # activate script has reloaded else if set --query GHJK_LAST_ENV_DIR; + and test -e $next_env_dir/activate.fish; and test (__ghjk_get_mtime_ts $GHJK_LAST_ENV_DIR/activate.fish) -gt $GHJK_LAST_ENV_DIR_MTIME; ghjk_hook end diff --git a/install/hook.sh b/install/hook.sh index 2e697b9..2038bde 100644 --- a/install/hook.sh +++ b/install/hook.sh @@ -109,7 +109,7 @@ precmd() { rm "$GHJK_NEXTFILE" # - the env dir loader mtime changes - elif [ -n "${GHJK_LAST_ENV_DIR+x}" ] && [ "$(__ghjk_get_mtime_ts "$GHJK_LAST_ENV_DIR/activate.sh")" -gt "$GHJK_LAST_ENV_DIR_MTIME" ]; then + elif [ -n "${GHJK_LAST_ENV_DIR+x}" ] && [ -e "$GHJK_LAST_ENV_DIR/activate.sh" ] && [ "$(__ghjk_get_mtime_ts "$GHJK_LAST_ENV_DIR/activate.sh")" -gt "$GHJK_LAST_ENV_DIR_MTIME" ]; then ghjk_hook diff --git a/install/mod.ts b/install/mod.ts index 3210506..fb764b0 100644 --- a/install/mod.ts +++ b/install/mod.ts @@ -5,19 +5,12 @@ // relying on --frozen-lockfile import getLogger from "../utils/logger.ts"; -import { $, dirs, importRaw } from "../utils/mod.ts"; +import { $, importRaw } from "../utils/mod.ts"; import type { Path } from "../utils/mod.ts"; +import { xdg } from "../deps/install.ts"; const logger = getLogger(import.meta); -/** - * Deno unstable flags needed for ghjk host. - */ -export const unstableFlags = [ - "--unstable-kv", - "--unstable-worker-options", -]; - // TODO: calculate and add integrity hashes to these raw imports // as they won't be covered by deno.lock // - use pre-commit-hook plus ghjk tasks to do find+replace @@ -39,7 +32,7 @@ const getHooksVfs = async () => ({ "env.bash": [ "# importing bash-preexec, see the ghjk hook at then end\n\n", await importRaw( - "https://raw.githubusercontent.com/rcaloras/bash-preexec/0.5.0/bash-preexec.sh", + import.meta.resolve("./bash-preexec.sh"), ), await importRaw(import.meta.resolve("./hook.sh")), ].join("\n"), @@ -104,51 +97,37 @@ async function filterAddContent( interface InstallArgs { homeDir: string; - ghjkShareDir: string; + ghjkDataDir: string; shellsToHook?: string[]; /** The mark used when adding the hook to the user's shell rcs. * Override to allow multiple hooks in your rc. */ shellHookMarker: string; - /** - * The ghjk bin is optional, one can always invoke it - * using `deno run --flags uri/to/ghjk/main.ts`; - */ - skipExecInstall: boolean; - /** The directory in which to install the ghjk exec - * Preferrably, one that's in PATH - */ - ghjkExecInstallDir: string; - /** - * The deno exec to be used by the ghjk executable - * by default will be "deno" i.e. whatever in $PATH that resolves that to. - */ - ghjkExecDenoExec: string; - /** - * The cache dir to use by the ghjk deno installation. - */ - ghjkDenoCacheDir?: string; - /** - * Disable using a lockfile for the ghjk command - */ - noLockfile: boolean; +} + +function getHomeDir() { + switch (Deno.build.os) { + case "linux": + case "darwin": + return Deno.env.get("HOME") ?? null; + case "windows": + return Deno.env.get("USERPROFILE") ?? null; + default: + return null; + } +} +const homeDir = getHomeDir(); +if (!homeDir) { + throw new Error("cannot find home dir"); } export const defaultInstallArgs: InstallArgs = { - ghjkShareDir: $.path(dirs().shareDir).resolve("ghjk").toString(), - homeDir: dirs().homeDir, + // remove first the xdg.data suffix added in windows by lib + ghjkDataDir: $.path(xdg.data().replace("xdg.data", "")).resolve("ghjk") + .toString(), + homeDir, shellsToHook: [], shellHookMarker: "ghjk-hook-default", - skipExecInstall: true, - // TODO: respect xdg dirs - ghjkExecInstallDir: $.path(dirs().homeDir).resolve(".local", "bin") - .toString(), - ghjkExecDenoExec: Deno.execPath(), - /** - * the default behvaior kicks in with ghjkDenoCacheDir is falsy - * ghjkDenoCacheDir: undefined, - */ - noLockfile: false, }; const shellConfig: Record = { @@ -165,14 +144,14 @@ export async function install( if (Deno.build.os == "windows") { throw new Error("windows is not yet supported, please use wsl"); } - const ghjkShareDir = $.path(Deno.cwd()) - .resolve(args.ghjkShareDir); + const ghjkDataDir = $.path(Deno.cwd()) + .resolve(args.ghjkDataDir); - logger.info("unpacking vfs", { ghjkShareDir }); + logger.info("unpacking vfs", { ghjkDataDir }); await unpackVFS( await getHooksVfs(), - ghjkShareDir, - [[/__GHJK_SHARE_DIR__/g, ghjkShareDir.toString()]], + ghjkDataDir, + [[/__GHJK_DATA_DIR__/g, ghjkDataDir.toString()]], ); for (const shell of args.shellsToHook ?? Object.keys(shellConfig)) { const { homeDir } = args; @@ -188,7 +167,7 @@ export async function install( continue; } logger.info("installing hook", { - ghjkShareDir, + ghjkDataDir, shell, marker: args.shellHookMarker, rcPath, @@ -196,60 +175,7 @@ export async function install( await filterAddContent( rcPath, new RegExp(args.shellHookMarker, "g"), - `. ${ghjkShareDir}/env.${shell} # ${args.shellHookMarker}`, - ); - } - - if (!args.skipExecInstall) { - const installDir = await $.path(args.ghjkExecInstallDir).ensureDir(); - switch (Deno.build.os) { - case "linux": - case "freebsd": - case "solaris": - case "illumos": - case "darwin": { - const exePath = installDir.resolve(`ghjk`); - logger.debug("installing executable", { exePath }); - - // use an isolated cache by default - const denoCacheDir = args.ghjkDenoCacheDir - ? $.path(args.ghjkDenoCacheDir) - : ghjkShareDir.resolve("deno"); - await exePath.writeText( - (await importRaw(import.meta.resolve("./ghjk.sh"))) - .replaceAll( - "__GHJK_SHARE_DIR__", - ghjkShareDir.toString(), - ) - .replaceAll( - "__DENO_CACHE_DIR", - denoCacheDir.toString(), - ) - .replaceAll( - "__DENO_EXEC__", - args.ghjkExecDenoExec, - ) - .replaceAll( - "__UNSTABLE_FLAGS__", - unstableFlags.join(" "), - ) - .replaceAll( - "__MAIN_TS_URL__", - import.meta.resolve("../main.ts"), - ), - { mode: 0o700 }, - ); - break; - } - default: - throw new Error(`${Deno.build.os} is not yet supported`); - } - logger.warn( - "make sure to add the following to your $PATH to access the ghjk CLI", - ); - logger.warn( - installDir.toString(), + `. ${ghjkDataDir}/env.${shell} # ${args.shellHookMarker}`, ); } - logger.info("install success"); } diff --git a/install/utils.ts b/install/utils.ts index 1f5bb9b..a679684 100644 --- a/install/utils.ts +++ b/install/utils.ts @@ -1,44 +1,31 @@ //! Please keep these in sync with `./ghjk.ts` import type { GhjkCtx } from "../modules/types.ts"; -import { unstableFlags } from "./mod.ts"; /** * Returns a simple posix function to invoke the ghjk CLI. + * This shim assumes it's running inside the ghjk embedded deno runtime. */ export function ghjk_sh( gcx: GhjkCtx, - denoDir: string, functionName = "__ghjk_shim", ) { return `${functionName} () { - GHJK_SHARE_DIR="${gcx.ghjkShareDir}" \\ - DENO_DIR="${denoDir}" \\ - DENO_NO_UPDATE_CHECK=1 \\ GHJK_DIR="${gcx.ghjkDir}" \\ - ${Deno.execPath()} run ${ - unstableFlags.join(" ") - } -A --lock ${gcx.ghjkDir}/deno.lock ${import.meta.resolve("../main.ts")} "$@" + ${Deno.execPath()} "$@" }`; } /** * Returns a simple fish function to invoke the ghjk CLI. + * This shim assumes it's running inside the ghjk embedded deno runtime. */ export function ghjk_fish( gcx: GhjkCtx, - denoDir: string, functionName = "__ghjk_shim", ) { return `function ${functionName} - GHJK_SHARE_DIR="${gcx.ghjkShareDir}" \\ - DENO_DIR="${denoDir}" \\ - DENO_NO_UPDATE_CHECK=1 \\ GHJK_DIR="${gcx.ghjkDir}" \\ - ${Deno.execPath()} run ${ - unstableFlags.join(" ") - } -A --lock ${gcx.ghjkDir}/deno.lock ${ - import.meta.resolve("../main.ts") - } $argv + ${Deno.execPath()} $argv end`; } diff --git a/main.ts b/main.ts deleted file mode 100755 index 35a2f83..0000000 --- a/main.ts +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env -S deno run --unstable-worker-options -A - -import "./setup_logger.ts"; -import { cli } from "./host/mod.ts"; -import { std_path } from "./deps/common.ts"; -import logger from "./utils/logger.ts"; -import { dirs, findEntryRecursive } from "./utils/mod.ts"; - -if (import.meta.main) { - // look for ghjkdir - let ghjkdir = Deno.env.get("GHJK_DIR") ?? - await findEntryRecursive(Deno.cwd(), ".ghjk"); - const ghjkfile = ghjkdir - ? await findEntryRecursive(std_path.dirname(ghjkdir), "ghjk.ts") - : await findEntryRecursive(Deno.cwd(), "ghjk.ts"); - if (!ghjkdir && !ghjkfile) { - logger().warn( - "ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.", - ); - // Deno.exit(2); - } - if (ghjkfile && !ghjkdir) { - ghjkdir = std_path.resolve(std_path.dirname(ghjkfile), ".ghjk"); - } - await cli({ - // FIXME: better - reFlagSet: !!Deno.env.get("GHJK_RE") && - !(["false", "", ""].includes(Deno.env.get("GHJK_RE")!)), - lockedFlagSet: !!Deno.env.get("GHJK_LOCKED") && - !(["false", "", ""].includes(Deno.env.get("GHJK_LOCKED")!)), - - ghjkShareDir: Deno.env.get("GHJK_SHARE_DIR") ?? - dirs().shareDir.resolve("ghjk").toString(), - ghjkfilePath: ghjkfile ? std_path.resolve(Deno.cwd(), ghjkfile) : undefined, - ghjkDirPath: ghjkdir ? std_path.resolve(Deno.cwd(), ghjkdir) : undefined, - }); -} else { - throw new Error( - `unexpected context: this module is an entrypoint. If you want to programmatically invoke the ghjk cli, import \`cli\` from ${ - import.meta.resolve("./host/mod.ts") - }`, - ); -} diff --git a/modules/envs/mod.ts b/modules/envs/mod.ts index d15d706..996970a 100644 --- a/modules/envs/mod.ts +++ b/modules/envs/mod.ts @@ -1,6 +1,6 @@ export * from "./types.ts"; -import { cliffy_cmd, zod } from "../../deps/cli.ts"; +import { zod } from "../../deps/cli.ts"; import { $, detectShellPath, Json, unwrapZodRes } from "../../utils/mod.ts"; import validators from "./types.ts"; import type { @@ -20,6 +20,7 @@ import type { import { buildInstallGraph, syncCtxFromGhjk } from "../ports/sync.ts"; import { getEnvsCtx } from "./inter.ts"; import { getTasksCtx } from "../tasks/inter.ts"; +import { CliCommand } from "../../src/deno_systems/types.ts"; export type EnvsCtx = { activeEnv: string; @@ -34,7 +35,7 @@ const lockValidator = zod.object({ type EnvsLockEnt = zod.infer; export class EnvsModule extends ModuleBase { - loadConfig( + override loadConfig( manifest: ModuleManifest, _bb: Blackboard, _lockEnt: EnvsLockEnt | undefined, @@ -59,7 +60,7 @@ export class EnvsModule extends ModuleBase { } } - commands() { + override commands(): CliCommand[] { const gcx = this.gcx; const ecx = getEnvsCtx(this.gcx); @@ -89,20 +90,32 @@ export class EnvsModule extends ModuleBase { : { envKey: envKeyMaybe ?? ecx.activeEnv }; } - return { - envs: new cliffy_cmd - .Command() - .description("Envs module, reproducable posix shells environments.") - .alias("e") - // .alias("env") - .action(function () { - this.showHelp(); - }) - .command( - "ls", - new cliffy_cmd.Command() - .description("List environments defined in the ghjkfile.") - .action(() => { + const commonFlags: CliCommand["flags"] = { + taskEnv: { + short: "t", + long: "task-env", + value_name: "TASK NAME", + help: "Activate the environment used by the named task", + exclusive: true, + }, + }; + + const commonArgs: CliCommand["args"] = { + envKey: { + value_name: "ENV KEY", + }, + }; + + return [ + { + name: "envs", + visible_aliases: ["e"], + about: "Envs module, reproducable posix shells environments.", + sub_commands: [ + { + name: "ls", + about: "List environments defined in the ghjkfile.", + action: () => { // deno-lint-ignore no-console console.log( Object.entries(ecx.config.envsNamed) @@ -115,66 +128,84 @@ export class EnvsModule extends ModuleBase { }) .join("\n"), ); - }), - ) - .command( - "activate", - new cliffy_cmd.Command() - .description(`Activate an environment. - -- If no [envName] is specified and no env is currently active, this activates the configured default env [${ecx.config.defaultEnv}].`) - .arguments("[envName:string]") - .option( - "-t, --task-env ", - "Synchronize to the environment used by the named task", - { standalone: true }, - ) - .action(async function ({ taskEnv }, envKeyMaybe) { + }, + }, + { + name: "activate", + about: `Activate an environment.`, + before_long_help: + `- If no ENV KEY is specified and no env is currently active, this activates the configured default env [${ecx.config.defaultEnv}].`, + flags: { + ...commonFlags, + }, + args: { + ...commonArgs, + }, + action: async function ( + { + flags: { taskEnv: taskKeyMaybe }, + args: { envKey: envKeyMaybe }, + }, + ) { const { envKey } = envKeyArgs({ - taskKeyMaybe: taskEnv, - envKeyMaybe, + taskKeyMaybe: taskKeyMaybe as string, + envKeyMaybe: (Array.isArray(envKeyMaybe) + ? envKeyMaybe[0] + : envKeyMaybe) as string, }); await activateEnv(envKey); - }), - ) - .command( - "cook", - new cliffy_cmd.Command() - .description(`Cooks the environment to a posix shell. - -- If no [envName] is specified, this will cook the active env [${ecx.activeEnv}]`) - .arguments("[envName:string]") - .option( - "-t, --task-env ", - "Synchronize to the environment used by the named task", - { standalone: true }, - ) - .action(async function ({ taskEnv }, envKeyMaybe) { + }, + }, + { + name: "cook", + about: `Cooks the environment to a posix shell.`, + before_long_help: + `- If no ENV KEY is specified, this will cook the active env [${ecx.activeEnv}]`, + flags: { + ...commonFlags, + }, + args: { + ...commonArgs, + }, + action: async function ( + { + flags: { taskEnv: taskKeyMaybe }, + args: { envKey: envKeyMaybe }, + }, + ) { const { envKey, envName } = envKeyArgs({ - taskKeyMaybe: taskEnv, - envKeyMaybe, + taskKeyMaybe: taskKeyMaybe as string, + envKeyMaybe: (Array.isArray(envKeyMaybe) + ? envKeyMaybe[0] + : envKeyMaybe) as string, }); await reduceAndCookEnv(gcx, ecx, envKey, envName ?? envKey); - }), - ) - .command( - "show", - new cliffy_cmd.Command() - .description(`Show details about an environment. + }, + }, + { + name: "show", + about: `Cooks the environment to a posix shell.`, + before_long_help: `Show details about an environment. -- If no [envName] is specified, this shows details of the active env [${ecx.activeEnv}]. -- If no [envName] is specified and no env is active, this shows details of the default env [${ecx.config.defaultEnv}]. - `) - .arguments("[envName:string]") - .option( - "-t, --task-env ", - "Synchronize to the environment used by the named task", - { standalone: true }, - ) - .action(async function ({ taskEnv }, envKeyMaybe) { +- If no ENV KEY is specified, this shows details of the active env [${ecx.activeEnv}]. +- If no ENV KEY is specified and no env is active, this shows details of the default env [${ecx.config.defaultEnv}].`, + flags: { + ...commonFlags, + }, + args: { + ...commonArgs, + }, + action: async function ( + { + flags: { taskEnv: taskKeyMaybe }, + args: { envKey: envKeyMaybe }, + }, + ) { const { envKey } = envKeyArgs({ - taskKeyMaybe: taskEnv, - envKeyMaybe, + taskKeyMaybe: taskKeyMaybe as string, + envKeyMaybe: (Array.isArray(envKeyMaybe) + ? envKeyMaybe[0] + : envKeyMaybe) as string, }); const env = ecx.config.envs[envKey]; if (!env) { @@ -182,24 +213,30 @@ export class EnvsModule extends ModuleBase { } // deno-lint-ignore no-console console.log($.inspect(await showableEnv(gcx, env, envKey))); - }), - ), - sync: new cliffy_cmd.Command() - .description(`Synchronize your shell to what's in your config. - -Cooks and activates an environment. -- If no [envName] is specified and no env is currently active, this syncs the configured default env [${ecx.config.defaultEnv}]. -- If the environment is already active, this doesn't launch a new shell.`) - .arguments("[envName:string]") - .option( - "-t, --task-env ", - "Synchronize to the environment used by the named task", - { standalone: true }, - ) - .action(async function ({ taskEnv }, envKeyMaybe) { + }, + }, + ], + }, + { + name: "sync", + about: "Synchronize your shell to what's in your config.", + before_long_help: `Cooks and activates an environment. +- If no ENV KEY is specified and no env is currently active, this syncs the configured default env [${ecx.config.defaultEnv}]. +- If the environment is already active, this doesn't launch a new shell.`, + flags: { + ...commonFlags, + }, + args: { + ...commonArgs, + }, + action: async function ( + { flags: { taskEnv: taskKeyMaybe }, args: { envKey: envKeyMaybe } }, + ) { const { envKey, envName } = envKeyArgs({ - taskKeyMaybe: taskEnv, - envKeyMaybe, + taskKeyMaybe: taskKeyMaybe as string, + envKeyMaybe: (Array.isArray(envKeyMaybe) + ? envKeyMaybe[0] + : envKeyMaybe) as string, }); await reduceAndCookEnv( gcx, @@ -208,8 +245,9 @@ Cooks and activates an environment. envName ?? envKey, ); await activateEnv(envKey); - }), - }; + }, + }, + ]; } loadLockEntry(raw: Json) { diff --git a/modules/envs/posix.ts b/modules/envs/posix.ts index 73f479e..d7466dd 100644 --- a/modules/envs/posix.ts +++ b/modules/envs/posix.ts @@ -202,7 +202,7 @@ async function writeActivators( onExitHooks: [string, string[]][], ) { const ghjkDirVar = "_ghjk_dir"; - const shareDirVar = "_ghjk_share_dir"; + const dataDirVar = "_ghjk_data_dir"; pathVars = { ...Object.fromEntries( Object.entries(pathVars).map(( @@ -211,7 +211,7 @@ async function writeActivators( key, val .replace(gcx.ghjkDir.toString(), "$" + ghjkDirVar) - .replace(gcx.ghjkShareDir.toString(), "$" + shareDirVar), + .replace(gcx.ghjkDataDir.toString(), "$" + dataDirVar), ]), ), }; @@ -227,9 +227,6 @@ async function writeActivators( .join(" ").replaceAll("'", "'\\''") ); - // ghjk.sh sets the DENO_DIR so we can usually - // assume it's set - const denoDir = Deno.env.get("DENO_DIR") ?? ""; const scripts = { // // posix shell version @@ -252,7 +249,7 @@ async function writeActivators( ``, `# the following variables are used to make the script more human readable`, `${ghjkDirVar}="${gcx.ghjkDir.toString()}"`, - `${shareDirVar}="${gcx.ghjkShareDir.toString()}"`, + `${dataDirVar}="${gcx.ghjkDataDir.toString()}"`, ``, `export GHJK_CLEANUP_POSIX="";`, `# env vars`, @@ -305,11 +302,8 @@ async function writeActivators( }), ``, `# hooks that want to invoke ghjk are made to rely`, - `# on this shim instead to improve latency`, - // the ghjk executable is itself a shell script - // which execs deno, we remove the middleman here - // also, the ghjk executable is optional - ghjk_sh(gcx, denoDir, ghjkShimName), + `# on this shim to improve to improve reliablity`, + ghjk_sh(gcx, ghjkShimName), ``, `# only run the hooks in interactive mode`, `case "$-" in`, @@ -346,7 +340,7 @@ async function writeActivators( ``, `# the following variables are used to make the script more human readable`, `set ${ghjkDirVar} "${gcx.ghjkDir.toString()}"`, - `set ${shareDirVar} "${gcx.ghjkShareDir.toString()}"`, + `set ${dataDirVar} "${gcx.ghjkDataDir.toString()}"`, ``, `# env vars`, `# we keep track of old values before this script is run`, @@ -376,8 +370,8 @@ async function writeActivators( }), ``, `# hooks that want to invoke ghjk are made to rely`, - `# on this shim to improve latency`, - ghjk_fish(gcx, denoDir, ghjkShimName), + `# on this shim to improve to improve reliablity`, + ghjk_fish(gcx, ghjkShimName), ``, `# only run the hooks in interactive mode`, `if status is-interactive;`, diff --git a/modules/mod.ts b/modules/mod.ts index 9ec8165..210079a 100644 --- a/modules/mod.ts +++ b/modules/mod.ts @@ -1,5 +1,5 @@ -import { cliffy_cmd } from "../deps/cli.ts"; import { Blackboard } from "../host/types.ts"; +import { CliCommand } from "../src/deno_systems/types.ts"; import type { Json } from "../utils/mod.ts"; import type { GhjkCtx, ModuleManifest } from "./types.ts"; @@ -18,5 +18,5 @@ export abstract class ModuleBase { raw: Json, ): Promise | LockEnt | undefined; abstract genLockEntry(): Promise | Json; - abstract commands(): Record>; + abstract commands(): CliCommand[]; } diff --git a/modules/ports/mod.ts b/modules/ports/mod.ts index 9211346..98f9b7b 100644 --- a/modules/ports/mod.ts +++ b/modules/ports/mod.ts @@ -1,6 +1,6 @@ export * from "./types.ts"; -import { cliffy_cmd, Table, zod } from "../../deps/cli.ts"; +import { Table, zod } from "../../deps/cli.ts"; import { $, Json, unwrapZodRes } from "../../utils/mod.ts"; import logger from "../../utils/logger.ts"; import validators, { @@ -35,6 +35,7 @@ import type { Provision, ProvisionReducer } from "../envs/types.ts"; import { getPortsCtx } from "./inter.ts"; import { updateInstall } from "./utils.ts"; import { getEnvsCtx } from "../envs/inter.ts"; +import { CliCommand } from "../../src/deno_systems/types.ts"; export type PortsCtx = { config: PortsModuleConfigX; @@ -110,163 +111,61 @@ export class PortsModule extends ModuleBase { ); } - commands() { + override commands() { const gcx = this.gcx; const pcx = getPortsCtx(gcx); - return { - ports: new cliffy_cmd.Command() - .alias("p") - .action(function () { - this.showHelp(); - }) - .description("Ports module, install programs into your env.") - .command( - "resolve", - new cliffy_cmd.Command() - .description(`Resolve all installs declared in config. - -- Useful to pre-resolve and add all install configs to the lockfile.`) - .action(async function () { - // scx contains a reference counted db connection - // somewhere deep in there - // so we need to use `using` - await using scx = await syncCtxFromGhjk(gcx); - for (const [_id, set] of Object.entries(pcx.config.sets)) { - void await buildInstallGraph(scx, set); - } - }), - ) - .command( - "outdated", - new cliffy_cmd.Command() - .description("Show a version table for installs.") - .option( - "-u, --update-install ", - "Update specific install", - ) - .option("-n, --update-all", "Update all installs") - .action(async (opts) => { - const envsCtx = getEnvsCtx(gcx); - const envName = envsCtx.activeEnv; - - const installSets = pcx.config.sets; - - let currInstallSetId; - { - const activeEnvName = envsCtx.activeEnv; - const activeEnv = envsCtx.config - .envs[ - envsCtx.config.envsNamed[activeEnvName] ?? activeEnvName - ]; - if (!activeEnv) { - throw new Error( - `No env found under given name "${activeEnvName}"`, - ); - } - - const instSetRef = activeEnv.provides.filter((prov) => - prov.ty === installSetRefProvisionTy - )[0] as InstallSetRefProvision; - - currInstallSetId = instSetRef.setId; - } - const currInstallSet = installSets[currInstallSetId]; - const allowedDeps = currInstallSet.allowedBuildDeps; - - const rows = []; - const { - installedPortsVersions: installed, - latestPortsVersions: latest, - installConfigs, - } = await getOldNewVersionComparison( - gcx, - envName, - allowedDeps, - ); - for (let [installId, installedVersion] of installed.entries()) { - let latestVersion = latest.get(installId); - if (!latestVersion) { - throw new Error( - `Couldn't find the latest version for install id: ${installId}`, - ); - } - - if (latestVersion[0] === "v") { - latestVersion = latestVersion.slice(1); - } - if (installedVersion[0] === "v") { - installedVersion = installedVersion.slice(1); - } - - const config = installConfigs.get(installId); - - if (!config) { - throw new Error( - `Config not found for install id: ${installId}`, - ); - } - - if (config["specifiedVersion"]) { - latestVersion = "=" + latestVersion; - } - - const presentableConfig = { ...config }; - ["buildDepConfigs", "version", "specifiedVersion"].map( - (key) => { - delete presentableConfig[key]; - }, - ); - const row = [ - $.inspect(presentableConfig), - installedVersion, - latestVersion, - ]; - rows.push(row); - } - - if (opts.updateInstall) { - const installName = opts.updateInstall; - // TODO: convert from install name to install id, after port module refactor - let installId!: string; - const newVersion = latest.get(installId); - if (!newVersion) { - logger().info( - `Error while fetching the latest version for: ${installName}`, - ); - return; - } - await updateInstall(gcx, installId, newVersion, allowedDeps); - return; - } - - if (opts.updateAll) { - for (const [installId, newVersion] of latest.entries()) { - await updateInstall(gcx, installId, newVersion, allowedDeps); - } - return; - } - - const _versionTable = new Table() - .header(["Install Config", "Old Version", "New Version"]) - .body(rows) - .border() - .padding(1) - .indent(2) - .maxColWidth(30) - .render(); - }), - ) - .command( - "cleanup", - new cliffy_cmd.Command() - .description("TODO") - .action(function () { - throw new Error("TODO"); - }), - ), - }; + const out: CliCommand[] = [{ + name: "ports", + visible_aliases: ["p"], + about: "Ports module, install programs into your env.", + sub_commands: [ + { + name: "resolve", + about: "Resolve all installs declared in config.", + before_long_help: + `- Useful to pre-resolve and add all install configs to the lockfile.`, + action: async function () { + // scx contains a reference counted db connection + // somewhere deep in there + // so we need to use `using` + await using scx = await syncCtxFromGhjk(gcx); + for (const [_id, set] of Object.entries(pcx.config.sets)) { + void await buildInstallGraph(scx, set); + } + }, + }, + { + name: "outdated", + about: "Show a version table for installs.", + flags: { + updateInstall: { + short: "u", + long: "update-install", + value_name: "INSTALL ID", + }, + updateAll: { + short: "a", + long: "update-all", + action: "SetTrue", + }, + }, + action: async function ( + { flags: { updateInstall, updateAll } }, + ) { + await outdatedCommand( + gcx, + pcx, + updateInstall as string | undefined, + updateAll as boolean | undefined, + ); + }, + }, + ], + }]; + return out; } + loadLockEntry(raw: Json) { const entry = lockValidator.parse(raw); @@ -300,6 +199,120 @@ export class PortsModule extends ModuleBase { } } +async function outdatedCommand( + gcx: GhjkCtx, + pcx: PortsCtx, + updateInstallFlag?: string, + updateAllFlag?: boolean, +) { + const envsCtx = getEnvsCtx(gcx); + const envName = envsCtx.activeEnv; + + const installSets = pcx.config.sets; + + let currInstallSetId; + { + const activeEnvName = envsCtx.activeEnv; + const activeEnv = envsCtx.config + .envs[ + envsCtx.config.envsNamed[activeEnvName] ?? activeEnvName + ]; + if (!activeEnv) { + throw new Error( + `No env found under given name "${activeEnvName}"`, + ); + } + + const instSetRef = activeEnv.provides.filter((prov) => + prov.ty === installSetRefProvisionTy + )[0] as InstallSetRefProvision; + + currInstallSetId = instSetRef.setId; + } + const currInstallSet = installSets[currInstallSetId]; + const allowedDeps = currInstallSet.allowedBuildDeps; + + const rows = []; + const { + installedPortsVersions: installed, + latestPortsVersions: latest, + installConfigs, + } = await getOldNewVersionComparison( + gcx, + envName, + allowedDeps, + ); + for (let [installId, installedVersion] of installed.entries()) { + let latestVersion = latest.get(installId); + if (!latestVersion) { + throw new Error( + `Couldn't find the latest version for install id: ${installId}`, + ); + } + + if (latestVersion[0] === "v") { + latestVersion = latestVersion.slice(1); + } + if (installedVersion[0] === "v") { + installedVersion = installedVersion.slice(1); + } + + const config = installConfigs.get(installId); + + if (!config) { + throw new Error( + `Config not found for install id: ${installId}`, + ); + } + + if (config["specifiedVersion"]) { + latestVersion = "=" + latestVersion; + } + + const presentableConfig = { ...config }; + ["buildDepConfigs", "version", "specifiedVersion"].map( + (key) => { + delete presentableConfig[key]; + }, + ); + const row = [ + $.inspect(presentableConfig), + installedVersion, + latestVersion, + ]; + rows.push(row); + } + + if (updateInstallFlag) { + const installId = updateInstallFlag; + const newVersion = latest.get(installId); + if (!newVersion) { + logger().info( + `Error while fetching the latest version for: ${installId}`, + ); + return; + } + await updateInstall(gcx, installId, newVersion, allowedDeps); + return; + } + + if (updateAllFlag) { + for (const [installId, newVersion] of latest.entries()) { + await updateInstall(gcx, installId, newVersion, allowedDeps); + } + return; + } + + const _versionTable = new Table() + .header(["Install Config", "Old Version", "New Version"]) + .body(rows) + .border() + .padding(1) + .indent(2) + .maxColWidth(30) + .render(); +} + async function getOldNewVersionComparison( gcx: GhjkCtx, envName: string, diff --git a/modules/ports/sync.ts b/modules/ports/sync.ts index c39e659..9a0ad98 100644 --- a/modules/ports/sync.ts +++ b/modules/ports/sync.ts @@ -53,7 +53,7 @@ export type SyncCtx = Awaited>; export async function syncCtxFromGhjk( gcx: GhjkCtx, ) { - const portsPath = await $.path(gcx.ghjkShareDir).resolve("ports") + const portsPath = await $.path(gcx.ghjkDataDir).resolve("ports") .ensureDir(); const [installsPath, downloadsPath, tmpPath] = ( await Promise.all([ diff --git a/modules/ports/worker.ts b/modules/ports/worker.ts index 383673c..97bf2d5 100644 --- a/modules/ports/worker.ts +++ b/modules/ports/worker.ts @@ -164,6 +164,8 @@ export class DenoWorkerPort extends PortBase { const worker = new Worker(import.meta.url, { name: `${this.manifest.name}@${this.manifest.version}`, type: "module", + // FIXME: catch worker errors or they bring down the whole + // program (no lockfile generated) // TODO: proper permissions }); // promise that resolves when worker replies diff --git a/modules/tasks/mod.ts b/modules/tasks/mod.ts index 7bdb2a2..c5349c2 100644 --- a/modules/tasks/mod.ts +++ b/modules/tasks/mod.ts @@ -1,6 +1,6 @@ export * from "./types.ts"; -import { cliffy_cmd, zod } from "../../deps/cli.ts"; +import { zod } from "../../deps/cli.ts"; import { Json, unwrapZodRes } from "../../utils/mod.ts"; import validators from "./types.ts"; @@ -11,6 +11,7 @@ import { ModuleBase } from "../mod.ts"; import { buildTaskGraph, execTask, type TaskGraph } from "./exec.ts"; import { Blackboard } from "../../host/types.ts"; import { getTasksCtx } from "./inter.ts"; +import { CliCommand } from "../../src/deno_systems/types.ts"; export type TasksCtx = { config: TasksModuleConfigX; @@ -46,58 +47,57 @@ export class TasksModule extends ModuleBase { tcx.taskGraph = taskGraph; } - commands() { + override commands() { const gcx = this.gcx; const tcx = getTasksCtx(this.gcx); const namedSet = new Set(tcx.config.tasksNamed); - const commands = Object.keys(tcx.config.tasks) - .sort() - .map( - (key) => { - const def = tcx.config.tasks[key]; - const cmd = new cliffy_cmd.Command() - .name(key) - .useRawArgs() - .action(async (_, ...args) => { - await execTask( - gcx, - tcx.config, - tcx.taskGraph, - key, - args, - ); - }); - if (def.desc) { - cmd.description(def.desc); - } - if (!namedSet.has(key)) { - cmd.hidden(); - } - return cmd; - }, - ); - const root = new cliffy_cmd.Command() - .alias("x") - .action(function () { - this.showHelp(); - }) - .description(`Tasks module. - -The named tasks in your ghjkfile will be listed here.`); - for (const cmd of commands) { - root.command(cmd.getName(), cmd); - } - return { - tasks: root, - }; + const out: CliCommand[] = [{ + name: "tasks", + visible_aliases: ["x"], + about: "Tasks module, execute your task programs.", + before_long_help: "The named tasks in your ghjkfile will be listed here.", + disable_help_subcommand: true, + sub_commands: [ + ...Object.keys(tcx.config.tasks) + .sort() + .map( + (key) => { + const def = tcx.config.tasks[key]; + return { + name: key, + about: def.desc, + hide: !namedSet.has(key), + args: { + raw: { + value_name: "TASK ARGS", + trailing_var_arg: true, + allow_hyphen_values: true, + action: "Append", + }, + }, + action: async ({ args: { raw } }) => { + await execTask( + gcx, + tcx.config, + tcx.taskGraph, + key, + (raw as string[]) ?? [], + ); + }, + } as CliCommand; + }, + ), + ], + }]; + return out; } loadLockEntry(raw: Json) { const entry = lockValidator.parse(raw); if (entry.version != "0") { - throw new Error(`unexepected version tag deserializing lockEntry`); + throw new Error(`unexpected version tag deserializing lockEntry`); } return entry; diff --git a/modules/types.ts b/modules/types.ts index f1c23ce..561fa2b 100644 --- a/modules/types.ts +++ b/modules/types.ts @@ -16,7 +16,7 @@ export type ModuleManifest = zod.infer; export type GhjkCtx = { ghjkfilePath?: Path; ghjkDir: Path; - ghjkShareDir: Path; + ghjkDataDir: Path; blackboard: Map; }; diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..762d4cf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,6 @@ +[toolchain] +# NOTE: to change this, change the const RUST_VERSION in ghjk.ts and +# then use the lock-sed task +channel = "1.82.0" +components = ["rustfmt", "clippy"] +targets = ["wasm32-unknown-unknown", "wasm32-wasi"] diff --git a/scripts/dev.ts b/scripts/dev.ts index 45c2033..d6e737c 100755 --- a/scripts/dev.ts +++ b/scripts/dev.ts @@ -14,38 +14,47 @@ const devDir = $.path( // }), ).join("../.dev"); -const ghjkShareDir = await devDir.join("ghjk").ensureDir(); +const ghjkDataDir = await devDir.join("ghjk").ensureDir(); await (await $.removeIfExists(devDir.join("ghjk.ts"))) .symlinkTo(import.meta.resolve("../ghjk.ts")); +const ghjkExePath = $.path(import.meta.resolve("../target/debug/ghjk")); +await ghjkDataDir + .join("ghjk") + .writeText( + `#!/bin/sh +exec ${ghjkExePath.resolve().toString()} "$@"`, + { mode: 0o700 }, + ); + const env: Record = { - BASH_ENV: `${ghjkShareDir.toString()}/env.bash`, - ZDOTDIR: ghjkShareDir.toString(), - GHJK_SHARE_DIR: ghjkShareDir.toString(), - PATH: `${ghjkShareDir.toString()}:${Deno.env.get("PATH")}`, + BASH_ENV: `${ghjkDataDir.toString()}/env.bash`, + ZDOTDIR: ghjkDataDir.toString(), + GHJK_DATA_DIR: ghjkDataDir.toString(), + PATH: `${ghjkDataDir.toString()}:${Deno.env.get("PATH")}`, + GHJK_CONFIG_DIR: devDir.toString(), // HOME: devDir.toString(), }; +await devDir.join("config.json").writeJsonPretty({ + "data_dir": ghjkDataDir.toString(), +}); + // install ghjk await install({ ...defaultInstallArgs, - skipExecInstall: false, - ghjkExecInstallDir: ghjkShareDir.toString(), - // share the system's deno cache - ghjkDenoCacheDir: Deno.env.get("DENO_DIR") ?? - $.path(Deno.env.get("HOME")!).join(".cache", "deno").toString(), - ghjkShareDir: ghjkShareDir.toString(), + ghjkDataDir: ghjkDataDir.toString(), // don't modify system shell configs shellsToHook: [], }); -// await $`${ghjkShareDir.join("ghjk").toString()} print config` +// await $`${ghjkDataDir.join("ghjk").toString()} print config` // .cwd(devDir.toString()) // .clearEnv() // .env(env); // -// await $`${ghjkShareDir.join("ghjk").toString()} envs cook` +// await $`${ghjkDataDir.join("ghjk").toString()} envs cook` // .cwd(devDir.toString()) // .clearEnv() // .env(env); @@ -56,7 +65,7 @@ if (Deno.args.length) { } else if (Deno.args[0] == "fish" && Deno.args.length == 1) { // cmd = $`fish --no-config --init-command 'source ${ cmd = $`fish --init-command 'source ${ - ghjkShareDir.join("env.fish").toString() + ghjkDataDir.join("env.fish").toString() }'`; } else { cmd = $`${Deno.args}`; diff --git a/src/deno_systems/bindings.ts b/src/deno_systems/bindings.ts index bbfd0e3..496d2cd 100644 --- a/src/deno_systems/bindings.ts +++ b/src/deno_systems/bindings.ts @@ -1,53 +1,55 @@ // import "../../src/ghjk/js/mock.sfx.ts"; import { zod } from "../../deps/common.ts"; -import { $, Json, unwrapZodRes } from "../../utils/mod.ts"; +import { $, unwrapZodRes } from "../../utils/mod.ts"; import type { GhjkCtx, ModuleManifest } from "../../modules/types.ts"; import type { ModuleBase } from "../../modules/mod.ts"; import type { Blackboard } from "../../host/types.ts"; -import { Ghjk } from "../ghjk/js/runtime.js"; +import { Ghjk, Json } from "../ghjk/js/runtime.js"; + +import type { + CliCommand, + CliCommandBindedX, + DenoSystemsRoot, +} from "./types.ts"; +import bindingTypes from "./types.ts"; + +// start an interval to prevent the event loop exiting +// after loading systems +setInterval(() => {/* beat */}, 1000); +// FIXME: better means of exit detection, keep alive as long +// as callbacks are registered? +// globalThis.onbeforeunload = (evt) => { +// evt.preventDefault(); +// }; const prepareArgs = zod.object({ uri: zod.string(), - gcx: zod.object({ - ghjkfile_path: zod.string().optional(), - ghjk_dir_path: zod.string(), - share_dir_path: zod.string(), + config: zod.object({ + ghjkfile: zod.string().optional(), + ghjkdir: zod.string(), + data_dir: zod.string(), + deno_lockfile: zod.string().optional(), + repo_root: zod.string(), + deno_dir: zod.string(), }), }); -const denoSystemsRoot = zod.object({ - systems: zod.record(zod.function()), -}); - -type DenoSystemCtor = (gcx: GhjkCtx) => ModuleBase; - -export type DenoSystemsRoot = { - systems: Record; -}; - -type ManifestDesc = { - id: string; - ctor_cb_key: string; -}; -type InstanceDesc = { - load_lock_entry_cb_key: string; - gen_lock_entry_cb_key: string; - load_config_cb_key: string; -}; +const args = prepareArgs.parse(Ghjk.blackboard.get("args")); +await prepareSystems(args); async function prepareSystems(args: zod.infer) { const gcx = { - ghjkDir: $.path(args.gcx.ghjk_dir_path), - ghjkShareDir: $.path(args.gcx.share_dir_path), - ghjkfilePath: args.gcx.ghjkfile_path - ? $.path(args.gcx.ghjkfile_path) + ghjkDir: $.path(args.config.ghjkdir), + ghjkDataDir: $.path(args.config.data_dir), + ghjkfilePath: args.config.ghjkfile + ? $.path(args.config.ghjkfile) : undefined, blackboard: new Map(), } satisfies GhjkCtx; const { default: mod } = await import(args.uri); const { systems } = unwrapZodRes( - denoSystemsRoot.safeParse(mod), + bindingTypes.denoSystemsRoot.safeParse(mod), ) as DenoSystemsRoot; const manifests = [] as ManifestDesc[]; @@ -67,6 +69,18 @@ async function prepareSystems(args: zod.infer) { await Ghjk.hostcall("register_systems", manifests); } +type ManifestDesc = { + id: string; + ctor_cb_key: string; +}; + +type InstanceDesc = { + load_lock_entry_cb_key: string; + gen_lock_entry_cb_key: string; + load_config_cb_key: string; + cli_commands_cb_key: string; +}; + function instanceBinding( gcx: GhjkCtx, sys_id: string, @@ -110,17 +124,37 @@ function instanceBinding( return instance.genLockEntry(); }, ), + cli_commands_cb_key: Ghjk.callbacks.set( + `sys_cli_commands_${instanceId}`, + (_) => { + const commandsRaw = instance.commands(); + return commandsRaw.map((cmd) => + commandBinding(cmd) as CliCommandBindedX + ); + }, + ), } satisfies InstanceDesc; } -// start an interval to prevent the event loop exiting -// after loading systems -setInterval(() => {/* beat */}, 1000); -// FIXME: better means of exit detection, keep alive as long -// as callbacks are registered? -// globalThis.onbeforeunload = (evt) => { -// evt.preventDefault(); -// }; - -const args = prepareArgs.parse(Ghjk.blackboard.get("args")); -await prepareSystems(args); +function commandBinding(commandRaw: CliCommand): CliCommandBindedX { + const { action, sub_commands, ...command } = bindingTypes.cliCommand.parse( + commandRaw, + ); + const actionId = crypto.randomUUID(); + return { + ...command, + sub_commands: sub_commands + ? sub_commands.map((cmd) => commandBinding(cmd)) + : undefined, + action_cb_key: action + ? Ghjk.callbacks.set( + `sys_cli_command_action_${command.name}_${actionId}`, + async (args) => { + const actionArgs = bindingTypes.cliActionArgs.parse(args); + await action(actionArgs); + return {}; + }, + ) + : undefined, + } satisfies CliCommandBindedX; +} diff --git a/src/deno_systems/mod.ts b/src/deno_systems/mod.ts index ddfcea4..92e4531 100644 --- a/src/deno_systems/mod.ts +++ b/src/deno_systems/mod.ts @@ -1,5 +1,5 @@ import { map } from "../../modules/std.ts"; -import type { DenoSystemsRoot } from "./bindings.ts"; +import type { DenoSystemsRoot } from "./types.ts"; export default { systems: Object.fromEntries( diff --git a/src/deno_systems/types.ts b/src/deno_systems/types.ts new file mode 100644 index 0000000..0f887fc --- /dev/null +++ b/src/deno_systems/types.ts @@ -0,0 +1,145 @@ +import { zod } from "../../deps/common.ts"; +import type { GhjkCtx } from "../../modules/types.ts"; +import type { ModuleBase } from "../../modules/mod.ts"; + +const denoSystemsRoot = zod.object({ + systems: zod.record(zod.function()), +}); + +const charSchema = zod.string().length(1); + +const cliArg = zod.object({ + value_name: zod.string().optional(), + value_hint: zod.enum([ + "Unknown", + "Other", + "AnyPath", + "FilePath", + "DirPath", + "ExecutablePath", + "CommandName", + "CommandString", + // "CommandWithArguments", + "Username", + "Hostname", + "Url", + "EmailAddress", + ]).optional(), + + action: zod.enum([ + "Set", + "Append", + "SetTrue", + "SetFalse", + "Count", + "Help", + "HelpShort", + "HelpLong", + "Version", + ]).optional(), + + required: zod.boolean().optional(), + global: zod.boolean().optional(), + hide: zod.boolean().optional(), + exclusive: zod.boolean().optional(), + trailing_var_arg: zod.boolean().optional(), + + env: zod.string().optional(), + + help: zod.string().optional(), + long_help: zod.string().optional(), +}); + +const cliFlag = cliArg.extend({ + long: zod.string().optional(), + long_aliases: zod.string().array().optional(), + visible_long_aliases: zod.string().array().optional(), + + short: charSchema.optional(), + short_aliases: charSchema.array().optional(), + visible_short_aliases: charSchema.array().optional(), +}); + +const cliCommandBase = zod.object({ + name: zod.string(), + + aliases: zod.string().array().optional(), + visible_aliases: zod.string().array().optional(), + + hide: zod.boolean().optional(), + disable_help_subcommand: zod.boolean().optional(), + + about: zod.string().optional(), + before_help: zod.string().optional(), + before_long_help: zod.string().optional(), + + args: zod.record(cliArg).optional().optional(), + flags: zod.record(cliFlag).optional().optional(), +}); + +const flagsAndArgs = zod.record( + zod.union([ + zod.string(), + zod.string().array(), + zod.number(), + zod.boolean(), + ]).optional(), +); + +const cliActionArgs = zod.object({ + flags: flagsAndArgs, + args: flagsAndArgs, +}); + +const cliCommandActionBase = cliCommandBase.extend({ + action: zod.function() + .args(cliActionArgs) + .returns(zod.union([zod.promise(zod.void()), zod.void()])).optional(), +}); + +const cliCommandBindedBase = cliCommandBase.extend({ + action_cb_key: zod.string().optional(), +}); + +const cliCommand: zod.ZodType = cliCommandActionBase.extend({ + sub_commands: zod.lazy(() => zod.array(cliCommand).optional()), +}); + +const cliCommandBinded: zod.ZodType = cliCommandBindedBase + .extend({ + sub_commands: zod.lazy(() => zod.array(cliCommandBinded).optional()), + }); + +type DenoSystemCtor = (gcx: GhjkCtx) => ModuleBase; + +export type DenoSystemsRoot = { + systems: Record; +}; + +export type CliCommand = zod.input & { + sub_commands?: CliCommand[]; +}; +export type CliCommandX = zod.infer & { + sub_commands?: CliCommandX[]; +}; + +export type CliCommandBinded = zod.input & { + sub_commands?: CliCommandBinded[]; +}; +export type CliCommandBindedX = zod.infer & { + sub_commands?: CliCommandBindedX[]; +}; + +export type CliFlag = zod.input; +export type CliFlagX = zod.infer; + +export type CliArg = zod.input; +export type CliArgX = zod.infer; + +export default { + denoSystemsRoot, + cliFlag, + cliArg, + cliCommand, + cliActionArgs, +}; diff --git a/src/denort/lib.rs b/src/denort/lib.rs index e7ab513..22c7a94 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -3,6 +3,8 @@ pub use deno; pub mod promises; +pub mod unsync; +pub mod worker; #[allow(unused)] mod interlude { @@ -21,15 +23,11 @@ mod interlude { } use crate::interlude::*; -use deno::{ - deno_runtime::{ - deno_core::{futures::FutureExt, unsync::JoinHandle, ModuleSpecifier}, - deno_permissions, - tokio_util::create_and_run_current_thread_with_maybe_metrics, - }, - *, +use deno::deno_runtime::{ + deno_core::{futures::FutureExt, unsync::JoinHandle, ModuleSpecifier}, + deno_permissions, + tokio_util::create_and_run_current_thread_with_maybe_metrics, }; -use std::sync::atomic::AtomicBool; #[rustfmt::skip] use deno_runtime::deno_core as deno_core; // necessary for re-exported macros to work @@ -50,526 +48,6 @@ pub fn init() { }; } -// thread tag used for basic sanity checks -pub const WORKER_THREAD_NAME: &str = "denort-worker-thread"; - -/// This starts a new thread and uses it to run all the tasks -/// that'll need to touch deno internals. Deno is single threaded. -/// -/// Returned handles will use channels internally to communicate to this worker. -pub async fn worker( - flags: deno::args::Flags, - custom_extensions_cb: Option>, -) -> Res { - let cx = WorkerContext::from_config(flags, custom_extensions_cb).await?; - - let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); - let rt = tokio::runtime::Handle::current(); - - let term_signal = AtomicBool::new(false); - let term_signal = Arc::new(term_signal); - - let global_term_signal = term_signal.clone(); - let join_handle = new_thread_builder() - .name(WORKER_THREAD_NAME.into()) - .spawn(move || { - let local = tokio::task::LocalSet::new(); - - local.spawn_local( - async move { - debug!("starting deno worker"); - while let Some(msg) = rx.recv().await { - debug!(?msg, "deno worker msg"); - match msg { - DenoWorkerMsg::PrepareModule { - response_channel, - inner, - } => { - response_channel - .send( - module_worker(&cx, global_term_signal.clone(), inner).await, - ) - .expect_or_log("channel error"); - } - } - } - debug!("deno worker done"); - } - .instrument(tracing::debug_span!("deno-worker")), - ); - rt.block_on(local); - }) - .unwrap(); - let join_handle = Arc::new(std::sync::Mutex::new(Some(join_handle))); - Ok(DenoWorkerHandle { - sender: tx, - term_signal, - join_handle, - }) -} - -async fn module_worker( - cx: &WorkerContext, - global_term_signal: Arc, - msg: PrepareModuleMsg, -) -> Res { - let mut module_cx = cx - .prepare_module( - msg.main_module, - &msg.permissions, - msg.mode, - msg.stdio, - msg.custom_extensions_cb, - ) - .await?; - - let (module_tx, mut module_rx) = tokio::sync::mpsc::channel::(1); - tokio::task::spawn_local( - async move { - debug!("starting module worker"); - while let Some(msg) = module_rx.recv().await { - debug!(?msg, "module worker msg"); - match msg { - ModuleWorkerReq::Run { response_channel } => response_channel - .send( - module_cx - .run(&global_term_signal) - .await - .map_err(|err| ferr!(Box::new(err))), - ) - .expect_or_log("channel error"), - ModuleWorkerReq::DriveTillExit { - term_signal, - response_channel, - } => response_channel - .send( - module_cx - .drive_till_exit(&global_term_signal, &term_signal) - .await - .map_err(|err| ferr!(Box::new(err))), - ) - .expect_or_log("channel error"), - ModuleWorkerReq::Execute { response_channel } => response_channel - .send( - module_cx - .execute_main_module() - .await - .map_err(|err| ferr!(Box::new(err))), - ) - .expect_or_log("channel error"), - ModuleWorkerReq::GetLoadedModules { response_channel } => response_channel - .send(module_cx.get_loaded_modules()) - .expect_or_log("channel error"), - } - } - debug!("module worker done"); - } - .instrument(tracing::debug_span!("deno-module-worker")), - ); - Ok(ModuleWorkerHandle { sender: module_tx }) -} - -#[derive(educe::Educe)] -#[educe(Debug)] -struct WorkerContext { - #[educe(Debug(ignore))] - cli_factory: deno::factory::CliFactory, - #[educe(Debug(ignore))] - worker_factory: deno::worker::CliMainWorkerFactory, - #[educe(Debug(ignore))] - graph: Arc, -} - -impl WorkerContext { - async fn from_config( - flags: deno::args::Flags, - root_custom_extensions_cb: Option>, - ) -> Res { - deno_permissions::set_prompt_callbacks( - Box::new(util::draw_thread::DrawThread::hide), - Box::new(util::draw_thread::DrawThread::show), - ); - - let flags = args::Flags { ..flags }; - let flags = Arc::new(flags); - let cli_factory = factory::CliFactory::from_flags(flags); - let cli_factory = if let Some(custom_extensions_cb) = &root_custom_extensions_cb { - cli_factory.with_custom_ext_cb(custom_extensions_cb.clone()) - } else { - cli_factory - }; - let worker_factory = cli_factory - .create_cli_main_worker_factory() - .await - .map_err(|err| ferr!(Box::new(err)))?; - - let graph = cli_factory - .main_module_graph_container() - .await - .map_err(|err| ferr!(Box::new(err)))? - .clone(); - Ok(Self { - cli_factory, - worker_factory, - graph, - }) - } - - async fn prepare_module( - &self, - main_module: ModuleSpecifier, - permissions: &deno_permissions::PermissionsOptions, - mode: deno_runtime::WorkerExecutionMode, - stdio: deno_runtime::deno_io::Stdio, - custom_extensions_cb: Option>, - ) -> Res { - let desc_parser = self - .cli_factory - .permission_desc_parser() - .map_err(|err| ferr!(Box::new(err)))? - .clone(); - let permissions = - deno_permissions::Permissions::from_options(desc_parser.as_ref(), permissions)?; - let permissions = deno_permissions::PermissionsContainer::new(desc_parser, permissions); - let mut worker = self - .worker_factory - .create_custom_worker( - mode, - main_module.clone(), - permissions, - custom_extensions_cb, - stdio, - ) - .await - .map_err(|err| ferr!(Box::new(err)))?; - let maybe_coverage_collector = worker - .maybe_setup_coverage_collector() - .await - .map_err(|err| ferr!(Box::new(err)))?; - - // TODO: hot module support, expose shared worker contet from deno/cli/worker - // let maybe_hmr_runner = worker - // .maybe_setup_hmr_runner() - // .await - // .map_err(|err| ferr!(Box::new(err)))?; - - let worker = worker.into_main_worker(); - - Ok(ModuleWorkerContext { - main_module, - worker, - graph: self.graph.clone(), - maybe_coverage_collector, - // maybe_hmr_runner, - }) - } -} - -#[derive(educe::Educe)] -#[educe(Debug)] -struct PrepareModuleMsg { - main_module: ModuleSpecifier, - permissions: deno_permissions::PermissionsOptions, - #[educe(Debug(ignore))] - mode: deno_runtime::WorkerExecutionMode, - #[educe(Debug(ignore))] - stdio: deno_runtime::deno_io::Stdio, - #[educe(Debug(ignore))] - custom_extensions_cb: Option>, -} - -#[derive(educe::Educe)] -#[educe(Debug)] -enum DenoWorkerMsg { - PrepareModule { - #[educe(Debug(ignore))] - response_channel: tokio::sync::oneshot::Sender>, - inner: PrepareModuleMsg, - }, -} - -#[derive(Clone, Debug)] -pub struct DenoWorkerHandle { - sender: tokio::sync::mpsc::UnboundedSender, - join_handle: Arc>>>, - term_signal: Arc, -} - -impl DenoWorkerHandle { - pub fn terminate(self) { - self.term_signal - .store(true, std::sync::atomic::Ordering::Relaxed); - let join_handle = { - let mut opt = self.join_handle.lock().expect_or_log("mutex error"); - opt.take() - }; - let Some(join_handle) = join_handle else { - return; - }; - join_handle.join().expect_or_log("join error") - } -} - -impl DenoWorkerHandle { - pub async fn prepare_module( - &self, - main_module: ModuleSpecifier, - permissions: deno_permissions::PermissionsOptions, - mode: deno_runtime::WorkerExecutionMode, - stdio: deno_runtime::deno_io::Stdio, - custom_extensions_cb: Option>, - ) -> Res { - let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender - .send(DenoWorkerMsg::PrepareModule { - response_channel: tx, - inner: PrepareModuleMsg { - main_module, - permissions, - mode, - stdio, - custom_extensions_cb, - }, - }) - .expect_or_log("channel error"); - rx.await.expect_or_log("channel error") - } -} - -#[derive(educe::Educe)] -#[educe(Debug)] -struct ModuleWorkerContext { - main_module: deno_core::ModuleSpecifier, - #[educe(Debug(ignore))] - worker: deno_runtime::worker::MainWorker, - #[educe(Debug(ignore))] - graph: Arc, - #[educe(Debug(ignore))] - maybe_coverage_collector: Option>, - // maybe_hmr_runner: Option>, -} - -impl ModuleWorkerContext { - fn get_loaded_modules(&self) -> Vec { - use deno::graph_container::*; - self.graph - .graph() - .walk( - [&self.main_module].into_iter(), - deno::deno_graph::WalkOptions { - kind: deno::deno_graph::GraphKind::CodeOnly, - check_js: false, - follow_dynamic: true, - prefer_fast_check_graph: false, - }, - ) - .map(|(url, _)| url.clone()) - .collect() - } - - async fn run(&mut self, global_term_signal: &AtomicBool) -> anyhow::Result { - debug!("main_module {}", self.main_module); - self.execute_main_module().await?; - self.drive_till_exit(global_term_signal, &AtomicBool::new(false)) - .await - } - - async fn drive_till_exit( - &mut self, - global_term_signal: &AtomicBool, - term_signal: &AtomicBool, - ) -> anyhow::Result { - self.worker.dispatch_load_event()?; - loop { - /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { - let watcher_communicator = - self.shared.maybe_file_watcher_communicator.clone().unwrap(); - - let hmr_future = hmr_runner.run().boxed_local(); - let event_loop_future = self.worker.run_event_loop(false).boxed_local(); - - let result; - tokio::select! { - hmr_result = hmr_future => { - result = hmr_result; - }, - event_loop_result = event_loop_future => { - result = event_loop_result; - } - } - if let Err(e) = result { - watcher_communicator.change_restart_mode(WatcherRestartMode::Automatic); - return Err(e); - } - } else { - self.worker - .run_event_loop(self.maybe_coverage_collector.is_none()) - .await?; - } */ - self.worker - .run_event_loop(self.maybe_coverage_collector.is_none()) - .await?; - - if term_signal.load(std::sync::atomic::Ordering::Relaxed) { - trace!("worker term signal lit, shutting down event loop"); - break; - } - - if global_term_signal.load(std::sync::atomic::Ordering::Relaxed) { - trace!("globalterm signal lit, shutting down event loop"); - break; - } - - let web_continue = self.worker.dispatch_beforeunload_event()?; - if !web_continue { - let node_continue = self.worker.dispatch_process_beforeexit_event()?; - if !node_continue { - trace!("beforeunload and beforeexit success, shutting down loop"); - break; - } - } - } - self.worker.dispatch_unload_event()?; - self.worker.dispatch_process_exit_event()?; - if let Some(coverage_collector) = self.maybe_coverage_collector.as_mut() { - self.worker - .js_runtime - .with_event_loop_future( - coverage_collector.stop_collecting().boxed_local(), - deno_core::PollEventLoopOptions::default(), - ) - .await?; - } - /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { - self.worker - .js_runtime - .with_event_loop_future( - hmr_runner.stop().boxed_local(), - deno_core::PollEventLoopOptions::default(), - ) - .await?; - } */ - Ok(self.worker.exit_code()) - //.map_err(|err| ferr!(Box::new(err))) - } - - async fn execute_main_module(&mut self) -> anyhow::Result<()> { - let id = self.worker.preload_main_module(&self.main_module).await?; - self.worker.evaluate_module(id).await - } -} - -#[derive(educe::Educe)] -#[educe(Debug)] -enum ModuleWorkerReq { - Run { - #[educe(Debug(ignore))] - response_channel: tokio::sync::oneshot::Sender>, - }, - DriveTillExit { - #[educe(Debug(ignore))] - term_signal: Arc, - #[educe(Debug(ignore))] - response_channel: tokio::sync::oneshot::Sender>, - }, - Execute { - #[educe(Debug(ignore))] - response_channel: tokio::sync::oneshot::Sender>, - }, - GetLoadedModules { - #[educe(Debug(ignore))] - response_channel: tokio::sync::oneshot::Sender>, - }, -} - -#[derive(Clone, Debug)] -pub struct ModuleWorkerHandle { - sender: tokio::sync::mpsc::Sender, -} - -#[derive(Clone, Debug)] -pub struct FinishedWorkerHandle { - sender: tokio::sync::mpsc::Sender, -} - -impl ModuleWorkerHandle { - /// Load and execute the main module - /// and drive the main loop until the program - /// exits. - pub async fn run(self) -> Res<(i32, FinishedWorkerHandle)> { - let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender - .send(ModuleWorkerReq::Run { - response_channel: tx, - }) - .await - .expect_or_log("channel error"); - Ok(( - rx.await.expect_or_log("channel error")?, - FinishedWorkerHandle { - sender: self.sender, - }, - )) - } - - /// Load and execute the main module - /// but doesn't progress the main event - /// loop. - pub async fn execute(&mut self) -> Res<()> { - let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender - .send(ModuleWorkerReq::Execute { - response_channel: tx, - }) - .await - .expect_or_log("channel error"); - rx.await.expect_or_log("channel error") - } - - /// Drive the event loop until exit and return - /// result in returned channel. - /// Expects that [`execute`] was called first on the worker. - pub async fn drive_till_exit( - self, - ) -> Res<( - tokio::sync::oneshot::Receiver>, - Arc, - FinishedWorkerHandle, - )> { - let term_signal = AtomicBool::new(false); - let term_signal = Arc::new(term_signal); - let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender - .send(ModuleWorkerReq::DriveTillExit { - term_signal: term_signal.clone(), - response_channel: tx, - }) - .await - .expect_or_log("channel error"); - Ok(( - rx, - term_signal, - FinishedWorkerHandle { - sender: self.sender, - }, - )) - } -} - -impl FinishedWorkerHandle { - pub async fn get_loaded_modules(&mut self) -> Vec { - let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender - .send(ModuleWorkerReq::GetLoadedModules { - response_channel: tx, - }) - .await - .expect_or_log("channel error"); - // FIXME: can use sync oneshot here? - rx.await.expect_or_log("channel error") - } -} - /// Ensure that the subcommand runs in a task, rather than being directly executed. Since some of these /// futures are very large, this prevents the stack from getting blown out from passing them by value up /// the callchain (especially in debug mode when Rust doesn't have a chance to elide copies!). @@ -580,15 +58,15 @@ fn spawn_subcommand + 'static>(f: F) -> JoinHandle<()> { } pub fn run_sync( main_mod: ModuleSpecifier, - import_map_url: Option, - permissions: args::PermissionFlags, - custom_extensions: Arc, + config_file: Option, + permissions: deno::args::PermissionFlags, + custom_extensions: Arc, ) { new_thread_builder() .spawn(|| { create_and_run_current_thread_with_maybe_metrics(async move { spawn_subcommand(async move { - run(main_mod, import_map_url, permissions, custom_extensions) + run(main_mod, config_file, permissions, custom_extensions) .await .unwrap() }) @@ -603,16 +81,15 @@ pub fn run_sync( pub async fn run( main_module: ModuleSpecifier, - import_map_url: Option, - permissions: args::PermissionFlags, - custom_extensions: Arc, + config_file: Option, + permissions: deno::args::PermissionFlags, + custom_extensions: Arc, ) -> anyhow::Result<()> { // NOTE: avoid using the Run subcommand // as it breaks our custom_extensions patch for some reason - let flags = args::Flags { + let flags = deno::args::Flags { permissions, - import_map_path: import_map_url, - unstable_config: args::UnstableConfig { + unstable_config: deno::args::UnstableConfig { features: DEFAULT_UNSTABLE_FLAGS .iter() .copied() @@ -620,12 +97,18 @@ pub async fn run( .collect(), ..Default::default() }, + config_flag: if let Some(config_file) = config_file { + deno::args::ConfigFlag::Path(config_file) + } else { + Default::default() + }, ..Default::default() }; let flags = Arc::new(flags); - let cli_factory = factory::CliFactory::from_flags(flags).with_custom_ext_cb(custom_extensions); + let cli_factory = + deno::factory::CliFactory::from_flags(flags).with_custom_ext_cb(custom_extensions); let worker_factory = cli_factory.create_cli_main_worker_factory().await?; @@ -640,12 +123,12 @@ pub async fn run( } pub fn test_sync( - files: deno_config::glob::FilePatterns, + files: deno::deno_config::glob::FilePatterns, config_file: PathBuf, - permissions: args::PermissionFlags, + permissions: deno::args::PermissionFlags, coverage_dir: Option, filter: Option, - custom_extensions: Arc, + custom_extensions: Arc, argv: Vec, ) { new_thread_builder() @@ -674,29 +157,31 @@ pub fn test_sync( } pub async fn test( - files: deno_config::glob::FilePatterns, + files: deno::deno_config::glob::FilePatterns, config_file: PathBuf, - permissions: args::PermissionFlags, + permissions: deno::args::PermissionFlags, coverage_dir: Option, filter: Option, - custom_extensions: Arc, + custom_extensions: Arc, argv: Vec, ) -> anyhow::Result<()> { use deno::tools::test::*; deno_permissions::set_prompt_callbacks( - Box::new(util::draw_thread::DrawThread::hide), - Box::new(util::draw_thread::DrawThread::show), + Box::new(deno::util::draw_thread::DrawThread::hide), + Box::new(deno::util::draw_thread::DrawThread::show), ); let pattern_to_str = |pattern| match pattern { - deno_config::glob::PathOrPattern::Path(path) => path.to_string_lossy().to_string(), - deno_config::glob::PathOrPattern::Pattern(pattern) => pattern.as_str().to_string(), - deno_config::glob::PathOrPattern::RemoteUrl(url) => url.as_str().to_owned(), - deno_config::glob::PathOrPattern::NegatedPath(path) => path.to_string_lossy().to_string(), + deno::deno_config::glob::PathOrPattern::Path(path) => path.to_string_lossy().to_string(), + deno::deno_config::glob::PathOrPattern::Pattern(pattern) => pattern.as_str().to_string(), + deno::deno_config::glob::PathOrPattern::RemoteUrl(url) => url.as_str().to_owned(), + deno::deno_config::glob::PathOrPattern::NegatedPath(path) => { + path.to_string_lossy().to_string() + } }; - let test_flags = args::TestFlags { - files: args::FileFlags { + let test_flags = deno::args::TestFlags { + files: deno::args::FileFlags { include: files .include .clone() @@ -719,9 +204,9 @@ pub async fn test( concurrent_jobs: std::thread::available_parallelism().ok(), ..Default::default() }; - let flags = args::Flags { + let flags = deno::args::Flags { permissions, - unstable_config: args::UnstableConfig { + unstable_config: deno::args::UnstableConfig { features: DEFAULT_UNSTABLE_FLAGS .iter() .copied() @@ -729,20 +214,21 @@ pub async fn test( .collect(), ..Default::default() }, - type_check_mode: args::TypeCheckMode::Local, - config_flag: args::ConfigFlag::Path(config_file.to_string_lossy().into()), + type_check_mode: deno::args::TypeCheckMode::Local, + config_flag: deno::args::ConfigFlag::Path(config_file.to_string_lossy().into()), argv, - subcommand: args::DenoSubcommand::Test(test_flags.clone()), + subcommand: deno::args::DenoSubcommand::Test(test_flags.clone()), ..Default::default() }; let flags = Arc::new(flags); - let cli_factory = factory::CliFactory::from_flags(flags).with_custom_ext_cb(custom_extensions); + let cli_factory = + deno::factory::CliFactory::from_flags(flags).with_custom_ext_cb(custom_extensions); let options = cli_factory.cli_options()?.clone(); - let test_options = args::WorkspaceTestOptions { + let test_options = deno::args::WorkspaceTestOptions { // files, ..options.resolve_workspace_test_options(&test_flags) }; diff --git a/src/denort/promises.rs b/src/denort/promises.rs index 7692575..ade0ae4 100644 --- a/src/denort/promises.rs +++ b/src/denort/promises.rs @@ -36,24 +36,25 @@ where .take() .unwrap() } - let on_fulfilled = v8::Function::builder( + let on_fulfilled = |scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, rv: v8::ReturnValue| { let data = v8::Local::::try_from(args.data()).unwrap(); let f = get_handler::(data); f(scope, rv, Ok(args.get(0))); - }, - ) - .data(external.into()) - .build(scope); - let on_rejected = v8::Function::builder( + }; + let on_fulfilled = v8::Function::builder(on_fulfilled) + .data(external.into()) + .build(scope); + + let on_rejected = |scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, rv: v8::ReturnValue| { let data = v8::Local::::try_from(args.data()).unwrap(); let f = get_handler::(data); f(scope, rv, Err(args.get(0))); - }, - ) - .data(external.into()) - .build(scope); + }; + let on_rejected = v8::Function::builder(on_rejected) + .data(external.into()) + .build(scope); // function builders will return None if the runtime is shutting down let (Some(on_fulfilled), Some(on_rejected)) = (on_fulfilled, on_rejected) else { _ = get_handler::(external); diff --git a/src/denort/unsync.rs b/src/denort/unsync.rs new file mode 100644 index 0000000..0a3acac --- /dev/null +++ b/src/denort/unsync.rs @@ -0,0 +1,280 @@ +// Modified from https://github.com/denoland/deno_unsync/blob/503a3fcb82235a591a98b497c8d26be5772c6dc9/src/tokio/task.rs +// Copyright 2018-2024 the Deno authors. MIT license. + +use core::pin::Pin; +use core::task::Context; +use core::task::Poll; +use std::future::Future; +use std::marker::PhantomData; +use tokio::runtime::Handle; +use tokio::runtime::RuntimeFlavor; + +/// Equivalent to [`tokio::task::JoinHandle`]. +#[repr(transparent)] +pub struct JoinHandle { + handle: tokio::task::JoinHandle>, + _r: PhantomData, +} + +impl JoinHandle { + /// Equivalent to [`tokio::task::JoinHandle::abort`]. + pub fn abort(&self) { + self.handle.abort() + } + + pub fn abort_handle(&self) -> tokio::task::AbortHandle { + self.handle.abort_handle() + } +} + +impl Future for JoinHandle { + type Output = Result; + + fn poll( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + // SAFETY: We are sure that handle is valid here + unsafe { + let me: &mut Self = Pin::into_inner_unchecked(self); + let handle = Pin::new_unchecked(&mut me.handle); + match handle.poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(Ok(r)) => Poll::Ready(Ok(r.into_inner())), + Poll::Ready(Err(e)) => Poll::Ready(Err(e)), + } + } + } +} + +/// Equivalent to [`tokio::task::spawn`], but does not require the future to be [`Send`]. Must only be +/// used on a [`RuntimeFlavor::CurrentThread`] executor, though this is only checked when running with +/// debug assertions. +#[inline(always)] +pub fn spawn + 'static, R: 'static>(name: &str, f: F) -> JoinHandle { + debug_assert!(Handle::current().runtime_flavor() == RuntimeFlavor::CurrentThread); + // SAFETY: we know this is a current-thread executor + let future = unsafe { MaskFutureAsSend::new(f) }; + JoinHandle { + handle: tokio::task::Builder::new() + .name(name) + .spawn(future) + .expect("tokio error"), + _r: Default::default(), + } +} + +/// Equivalent to [`tokio::task::spawn_blocking`]. Currently a thin wrapper around the tokio API, but this +/// may change in the future. +#[inline(always)] +pub fn spawn_blocking R) + Send + 'static, R: Send + 'static>( + name: &str, + f: F, +) -> JoinHandle { + let handle = tokio::task::Builder::new() + .name(name) + .spawn_blocking(|| MaskResultAsSend { result: f() }) + .expect("tokio error"); + JoinHandle { + handle, + _r: Default::default(), + } +} + +#[repr(transparent)] +#[doc(hidden)] +pub struct MaskResultAsSend { + result: R, +} + +/// SAFETY: We ensure that Send bounds are only faked when tokio is running on a current-thread executor +unsafe impl Send for MaskResultAsSend {} + +impl MaskResultAsSend { + #[inline(always)] + pub fn into_inner(self) -> R { + self.result + } +} + +#[repr(transparent)] +pub struct MaskFutureAsSend { + future: F, +} + +impl MaskFutureAsSend { + /// Mark a non-`Send` future as `Send`. This is a trick to be able to use + /// `tokio::spawn()` (which requires `Send` futures) in a current thread + /// runtime. + /// + /// # Safety + /// + /// You must ensure that the future is actually used on the same + /// thread, ie. always use current thread runtime flavor from Tokio. + #[inline(always)] + pub unsafe fn new(future: F) -> Self { + Self { future } + } +} + +// SAFETY: we are cheating here - this struct is NOT really Send, +// but we need to mark it Send so that we can use `spawn()` in Tokio. +unsafe impl Send for MaskFutureAsSend {} + +impl Future for MaskFutureAsSend { + type Output = MaskResultAsSend; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + // SAFETY: We are sure that future is valid here + unsafe { + let me: &mut MaskFutureAsSend = Pin::into_inner_unchecked(self); + let future = Pin::new_unchecked(&mut me.future); + match future.poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(result) => Poll::Ready(MaskResultAsSend { result }), + } + } + } +} + +// Copied from https://github.com/denoland/deno_unsync/blob/503a3fcb82235a591a98b497c8d26be5772c6dc9/src/tokio/joinset.rs +// Copyright 2018-2024 the Deno authors. MIT license. +// Some code and comments under MIT license where adapted from Tokio code +// Copyright (c) 2023 Tokio Contributors + +use std::task::Waker; +use tokio::task::AbortHandle; +use tokio::task::JoinError; + +/// Wraps the tokio [`JoinSet`] to make it !Send-friendly and to make it easier and safer for us to +/// poll while empty. +pub struct JoinSet { + joinset: tokio::task::JoinSet>, + /// If join_next returns Ready(None), we stash the waker + waker: Option, +} + +impl Default for JoinSet { + fn default() -> Self { + Self { + joinset: Default::default(), + waker: None, + } + } +} + +impl JoinSet { + /// Spawn the provided task on the `JoinSet`, returning an [`AbortHandle`] + /// that can be used to remotely cancel the task. + /// + /// The provided future will start running in the background immediately + /// when this method is called, even if you don't await anything on this + /// `JoinSet`. + /// + /// # Panics + /// + /// This method panics if called outside of a Tokio runtime. + /// + /// [`AbortHandle`]: tokio::task::AbortHandle + #[track_caller] + pub fn spawn(&mut self, task: F) -> AbortHandle + where + F: Future, + F: 'static, + T: 'static, + { + // SAFETY: We only use this with the single-thread executor + let handle = self.joinset.spawn(unsafe { MaskFutureAsSend::new(task) }); + + // If someone had called poll_join_next while we were empty, ask them to poll again + // so we can properly register the waker with the underlying JoinSet. + if let Some(waker) = self.waker.take() { + waker.wake(); + } + handle + } + + #[track_caller] + pub fn spawn_named(&mut self, name: &str, task: F) -> AbortHandle + where + F: Future, + F: 'static, + T: 'static, + { + // SAFETY: We only use this with the single-thread executor + let handle = self + .joinset + .build_task() + .name(name) + .spawn(unsafe { MaskFutureAsSend::new(task) }) + .expect("tokio error"); + + // If someone had called poll_join_next while we were empty, ask them to poll again + // so we can properly register the waker with the underlying JoinSet. + if let Some(waker) = self.waker.take() { + waker.wake(); + } + handle + } + + /// Returns the number of tasks currently in the `JoinSet`. + pub fn len(&self) -> usize { + self.joinset.len() + } + + /// Returns whether the `JoinSet` is empty. + pub fn is_empty(&self) -> bool { + self.joinset.is_empty() + } + + /// Waits until one of the tasks in the set completes and returns its output. + /// + /// # Cancel Safety + /// + /// This method is cancel safe. If `join_next` is used as the event in a `tokio::select!` + /// statement and some other branch completes first, it is guaranteed that no tasks were + /// removed from this `JoinSet`. + pub fn poll_join_next(&mut self, cx: &mut Context) -> Poll> { + match self.joinset.poll_join_next(cx) { + Poll::Ready(Some(res)) => Poll::Ready(res.map(|res| res.into_inner())), + Poll::Ready(None) => { + // Stash waker + self.waker = Some(cx.waker().clone()); + Poll::Pending + } + Poll::Pending => Poll::Pending, + } + } + + /// Waits until one of the tasks in the set completes and returns its output. + /// + /// Returns `None` if the set is empty. + /// + /// # Cancel Safety + /// + /// This method is cancel safe. If `join_next` is used as the event in a `tokio::select!` + /// statement and some other branch completes first, it is guaranteed that no tasks were + /// removed from this `JoinSet`. + pub async fn join_next(&mut self) -> Option> { + self.joinset + .join_next() + .await + .map(|result| result.map(|res| res.into_inner())) + } + + /// Aborts all tasks on this `JoinSet`. + /// + /// This does not remove the tasks from the `JoinSet`. To wait for the tasks to complete + /// cancellation, you should call `join_next` in a loop until the `JoinSet` is empty. + pub fn abort_all(&mut self) { + self.joinset.abort_all(); + } + + /// Removes all tasks from this `JoinSet` without aborting them. + /// + /// The tasks removed by this call will continue to run in the background even if the `JoinSet` + /// is dropped. + pub fn detach_all(&mut self) { + self.joinset.detach_all(); + } +} diff --git a/src/denort/worker.rs b/src/denort/worker.rs new file mode 100644 index 0000000..ff877e7 --- /dev/null +++ b/src/denort/worker.rs @@ -0,0 +1,564 @@ +use crate::interlude::*; +use deno::{ + deno_runtime::{ + deno_core::{futures::FutureExt, ModuleSpecifier}, + deno_permissions, + }, + *, +}; + +// thread tag used for basic sanity checks +pub const WORKER_THREAD_NAME: &str = "denort-worker-thread"; + +/// This starts a new task to run all the work +/// that'll need to touch deno internals. +/// Deno is single threaded and this expects to run on single threaded runtimes. +/// +/// The returned handle will use channels internally to communicate to this worker. +pub async fn worker( + flags: deno::args::Flags, + custom_extensions_cb: Option>, +) -> Res { + let cx = WorkerContext::from_config(flags, custom_extensions_cb).await?; + + let (msg_tx, mut msg_rx) = tokio::sync::mpsc::channel::(32); + + let (term_signal_tx, term_signal_rx) = tokio::sync::watch::channel(false); + + let mut term_signal_rx2 = term_signal_rx.clone(); + let join_handle = crate::unsync::spawn( + "deno-worker", + async move { + let mut task_set = crate::unsync::JoinSet::default(); + trace!("starting deno worker"); + loop { + let msg = tokio::select! { + Some(msg) = msg_rx.recv() => { + msg + } + _ = term_signal_rx2.changed() => break, + else => break + }; + trace!(?msg, "deno worker msg"); + match msg { + DenoWorkerMsg::PrepareModule { + response_channel, + inner, + } => { + response_channel + .send( + module_worker(&cx, term_signal_rx2.clone(), inner, &mut task_set) + .await, + ) + .expect_or_log("channel error"); + } + } + } + // std::mem::forget(cx); + trace!("deno worker done"); + } + .instrument(tracing::trace_span!("deno-worker")), + ); + // let term_signal_tx = Arc::new(term_signal_tx); + let join_handle = Arc::new(std::sync::Mutex::new(Some(join_handle))); + Ok(DenoWorkerHandle { + sender: msg_tx, + term_signal_tx, + term_signal_rx, + join_handle, + }) +} + +type TermSignal = tokio::sync::watch::Receiver; + +async fn module_worker( + cx: &WorkerContext, + global_term_signal: TermSignal, + msg: PrepareModuleMsg, + task_set: &mut crate::unsync::JoinSet<()>, +) -> Res { + let mut module_cx = cx + .prepare_module( + msg.main_module.clone(), + &msg.permissions, + msg.mode, + msg.stdio, + msg.custom_extensions_cb, + ) + .await?; + + let (module_tx, mut module_rx) = tokio::sync::mpsc::channel::(1); + task_set.spawn_named( + &format!("deno-module-worker-{}", msg.main_module), + async move { + trace!("starting module worker"); + while let Some(msg) = module_rx.recv().await { + trace!(?msg, "module worker msg"); + match msg { + ModuleWorkerReq::Run { response_channel } => response_channel + .send( + module_cx + .run(global_term_signal.clone()) + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::DriveTillExit { + term_signal, + response_channel, + } => response_channel + .send( + module_cx + .drive_till_exit(global_term_signal.clone(), term_signal) + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::Execute { response_channel } => response_channel + .send( + module_cx + .execute_main_module() + .await + .map_err(|err| ferr!(Box::new(err))), + ) + .expect_or_log("channel error"), + ModuleWorkerReq::GetLoadedModules { response_channel } => response_channel + .send(module_cx.get_loaded_modules()) + .expect_or_log("channel error"), + } + } + // std::mem::forget(module_cx); + trace!("module worker done"); + } + .instrument(tracing::trace_span!( + "deno-module-worker", + main_module = %msg.main_module + )), + ); + Ok(ModuleWorkerHandle { sender: module_tx }) +} + +#[derive(educe::Educe)] +#[educe(Debug)] +struct WorkerContext { + #[educe(Debug(ignore))] + cli_factory: deno::factory::CliFactory, + #[educe(Debug(ignore))] + worker_factory: deno::worker::CliMainWorkerFactory, + #[educe(Debug(ignore))] + graph: Arc, +} + +impl WorkerContext { + async fn from_config( + flags: deno::args::Flags, + root_custom_extensions_cb: Option>, + ) -> Res { + deno_permissions::set_prompt_callbacks( + Box::new(util::draw_thread::DrawThread::hide), + Box::new(util::draw_thread::DrawThread::show), + ); + + let flags = args::Flags { ..flags }; + let flags = Arc::new(flags); + let cli_factory = factory::CliFactory::from_flags(flags); + let cli_factory = if let Some(custom_extensions_cb) = &root_custom_extensions_cb { + cli_factory.with_custom_ext_cb(custom_extensions_cb.clone()) + } else { + cli_factory + }; + let worker_factory = cli_factory + .create_cli_main_worker_factory() + .await + .map_err(|err| ferr!(Box::new(err)))?; + + let graph = cli_factory + .main_module_graph_container() + .await + .map_err(|err| ferr!(Box::new(err)))? + .clone(); + Ok(Self { + cli_factory, + worker_factory, + graph, + }) + } + + async fn prepare_module( + &self, + main_module: ModuleSpecifier, + permissions: &deno_permissions::PermissionsOptions, + mode: deno_runtime::WorkerExecutionMode, + stdio: deno_runtime::deno_io::Stdio, + custom_extensions_cb: Option>, + ) -> Res { + let desc_parser = self + .cli_factory + .permission_desc_parser() + .map_err(|err| ferr!(Box::new(err)))? + .clone(); + let permissions = + deno_permissions::Permissions::from_options(desc_parser.as_ref(), permissions)?; + let permissions = deno_permissions::PermissionsContainer::new(desc_parser, permissions); + let mut worker = self + .worker_factory + .create_custom_worker( + mode, + main_module.clone(), + permissions, + custom_extensions_cb, + stdio, + ) + .await + .map_err(|err| ferr!(Box::new(err)))?; + let maybe_coverage_collector = worker + .maybe_setup_coverage_collector() + .await + .map_err(|err| ferr!(Box::new(err)))?; + + // TODO: hot module support, expose shared worker contet from deno/cli/worker + // let maybe_hmr_runner = worker + // .maybe_setup_hmr_runner() + // .await + // .map_err(|err| ferr!(Box::new(err)))?; + + let worker = worker.into_main_worker(); + + Ok(ModuleWorkerContext { + main_module, + worker, + graph: self.graph.clone(), + maybe_coverage_collector, + // maybe_hmr_runner, + }) + } +} + +#[derive(educe::Educe)] +#[educe(Debug)] +struct PrepareModuleMsg { + main_module: ModuleSpecifier, + permissions: deno_permissions::PermissionsOptions, + #[educe(Debug(ignore))] + mode: deno_runtime::WorkerExecutionMode, + #[educe(Debug(ignore))] + stdio: deno_runtime::deno_io::Stdio, + #[educe(Debug(ignore))] + custom_extensions_cb: Option>, +} + +#[derive(educe::Educe)] +#[educe(Debug)] +enum DenoWorkerMsg { + PrepareModule { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + inner: PrepareModuleMsg, + }, +} + +#[derive(Clone, educe::Educe)] +#[educe(Debug)] +pub struct DenoWorkerHandle { + sender: tokio::sync::mpsc::Sender, + term_signal_tx: tokio::sync::watch::Sender, + #[educe(Debug(ignore))] + join_handle: Arc>>>, + term_signal_rx: tokio::sync::watch::Receiver, +} + +impl DenoWorkerHandle { + pub fn term_signal_watcher(&self) -> tokio::sync::watch::Receiver { + self.term_signal_rx.clone() + } + + pub async fn terminate(self) -> Res<()> { + let join_handle = { + let mut opt = self.join_handle.lock().expect_or_log("mutex error"); + opt.take() + }; + let Some(join_handle) = join_handle else { + return Ok(()); + }; + self.term_signal_tx.send(true)?; + let abort_handle = join_handle.abort_handle(); + match tokio::time::timeout(std::time::Duration::from_millis(100), join_handle).await { + Ok(val) => val.wrap_err("tokio error"), + Err(_) => { + trace!("timeout waiting for deno worker termination, aborting"); + abort_handle.abort(); + Ok(()) + } + } + //join_handle.await.wrap_err("tokio error") + } +} + +impl DenoWorkerHandle { + pub async fn prepare_module( + &self, + main_module: ModuleSpecifier, + permissions: deno_permissions::PermissionsOptions, + mode: deno_runtime::WorkerExecutionMode, + stdio: deno_runtime::deno_io::Stdio, + custom_extensions_cb: Option>, + ) -> Res { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(DenoWorkerMsg::PrepareModule { + response_channel: tx, + inner: PrepareModuleMsg { + main_module, + permissions, + mode, + stdio, + custom_extensions_cb, + }, + }) + .await + .expect_or_log("channel error"); + rx.await.expect_or_log("channel error") + } +} + +#[derive(educe::Educe)] +#[educe(Debug)] +struct ModuleWorkerContext { + main_module: deno_core::ModuleSpecifier, + #[educe(Debug(ignore))] + worker: deno_runtime::worker::MainWorker, + #[educe(Debug(ignore))] + graph: Arc, + #[educe(Debug(ignore))] + maybe_coverage_collector: Option>, + // maybe_hmr_runner: Option>, +} + +impl ModuleWorkerContext { + fn get_loaded_modules(&self) -> Vec { + use deno::graph_container::*; + self.graph + .graph() + .walk( + [&self.main_module].into_iter(), + deno::deno_graph::WalkOptions { + kind: deno::deno_graph::GraphKind::CodeOnly, + check_js: false, + follow_dynamic: true, + prefer_fast_check_graph: false, + }, + ) + .map(|(url, _)| url.clone()) + .collect() + } + + async fn run(&mut self, global_term_signal: TermSignal) -> anyhow::Result { + debug!("main_module {}", self.main_module); + self.execute_main_module().await?; + + let (_local_signal_tx, local_signal_rx) = tokio::sync::watch::channel(false); + self.drive_till_exit(global_term_signal, local_signal_rx) + .await + } + + async fn drive_till_exit( + &mut self, + mut global_term_signal: TermSignal, + mut term_signal: TermSignal, + ) -> anyhow::Result { + self.worker.dispatch_load_event()?; + loop { + /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { + let watcher_communicator = + self.shared.maybe_file_watcher_communicator.clone().unwrap(); + + let hmr_future = hmr_runner.run().boxed_local(); + let event_loop_future = self.worker.run_event_loop(false).boxed_local(); + + let result; + tokio::select! { + hmr_result = hmr_future => { + result = hmr_result; + }, + event_loop_result = event_loop_future => { + result = event_loop_result; + } + } + if let Err(e) = result { + watcher_communicator.change_restart_mode(WatcherRestartMode::Automatic); + return Err(e); + } + } else { + self.worker + .run_event_loop(self.maybe_coverage_collector.is_none()) + .await?; + } */ + + let event_loop_future = self + .worker + .run_event_loop(self.maybe_coverage_collector.is_none()) + .boxed_local(); + + trace!("running event loop"); + tokio::select! { + _ = global_term_signal.wait_for(|sig| *sig) => { + trace!("global term signal lit, shutting down event loop"); + break + }, + _ = term_signal.wait_for(|sig| *sig) => { + trace!("worker term signal lit, shutting down event loop"); + break + }, + event_loop_result = event_loop_future => { + event_loop_result? + } + }; + + let web_continue = self.worker.dispatch_beforeunload_event()?; + if !web_continue { + let node_continue = self.worker.dispatch_process_beforeexit_event()?; + if !node_continue { + trace!("beforeunload and beforeexit success, shutting down loop"); + break; + } + } + } + self.worker.dispatch_unload_event()?; + self.worker.dispatch_process_exit_event()?; + if let Some(coverage_collector) = self.maybe_coverage_collector.as_mut() { + self.worker + .js_runtime + .with_event_loop_future( + coverage_collector.stop_collecting().boxed_local(), + deno_core::PollEventLoopOptions::default(), + ) + .await?; + } + /* if let Some(hmr_runner) = self.maybe_hmr_runner.as_mut() { + self.worker + .js_runtime + .with_event_loop_future( + hmr_runner.stop().boxed_local(), + deno_core::PollEventLoopOptions::default(), + ) + .await?; + } */ + Ok(self.worker.exit_code()) + //.map_err(|err| ferr!(Box::new(err))) + } + + async fn execute_main_module(&mut self) -> anyhow::Result<()> { + let id = self.worker.preload_main_module(&self.main_module).await?; + self.worker.evaluate_module(id).await + } +} + +#[derive(educe::Educe)] +#[educe(Debug)] +enum ModuleWorkerReq { + Run { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, + DriveTillExit { + term_signal: TermSignal, + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, + Execute { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, + GetLoadedModules { + #[educe(Debug(ignore))] + response_channel: tokio::sync::oneshot::Sender>, + }, +} + +#[derive(Clone, Debug)] +pub struct ModuleWorkerHandle { + sender: tokio::sync::mpsc::Sender, +} + +#[derive(Clone, Debug)] +pub struct FinishedWorkerHandle { + sender: tokio::sync::mpsc::Sender, +} + +impl ModuleWorkerHandle { + /// Load and execute the main module + /// and drive the main loop until the program + /// exits. + pub async fn run(self) -> Res<(i32, FinishedWorkerHandle)> { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::Run { + response_channel: tx, + }) + .await + .expect_or_log("channel error"); + Ok(( + rx.await.expect_or_log("channel error")?, + FinishedWorkerHandle { + sender: self.sender, + }, + )) + } + + /// Load and execute the main module + /// but doesn't progress the main event + /// loop. + pub async fn execute(&mut self) -> Res<()> { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::Execute { + response_channel: tx, + }) + .await + .expect_or_log("channel error"); + rx.await.expect_or_log("channel error") + } + + /// Drive the event loop until exit and return + /// result in returned channel or the term signal + /// is lit. + /// Expects that [`execute`] was called first on the worker. + pub async fn drive_till_exit( + self, + ) -> Res<( + tokio::sync::oneshot::Receiver>, + tokio::sync::watch::Sender, + FinishedWorkerHandle, + )> { + let (term_signal_tx, term_signal_rx) = tokio::sync::watch::channel(false); + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::DriveTillExit { + term_signal: term_signal_rx, + response_channel: tx, + }) + .await + .expect_or_log("channel error"); + Ok(( + rx, + term_signal_tx, + FinishedWorkerHandle { + sender: self.sender, + }, + )) + } +} + +impl FinishedWorkerHandle { + pub async fn get_loaded_modules(&mut self) -> Vec { + let (tx, rx) = tokio::sync::oneshot::channel(); + self.sender + .send(ModuleWorkerReq::GetLoadedModules { + response_channel: tx, + }) + .await + .expect_or_log("channel error"); + // FIXME: can use sync oneshot here? + rx.await.expect_or_log("channel error") + } +} diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index 5335c17..1ff779e 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "ghjk" +description = "Program your development environments." version.workspace = true edition.workspace = true @@ -13,12 +14,17 @@ deno_core.workspace = true serde = "1" serde_json = "1" + ahash = { version = "0.8", features = ["serde"] } +indexmap = { version = "2.6.0", features = ["serde"] } # serde_repr = { version = "0.1" } regex = "1.10" + rand = "0.8" time = { version = "0.3", features = ["serde"] } +nix = { version = "0.29.0", features = ["signal"] } + once_cell = "1.19" parking_lot = "*" bitflags = "*" @@ -46,24 +52,30 @@ tracing-subscriber.workspace = true tracing-appender = "0.2" tracing-futures = "0.2" -tokio = { workspace = true, features = ["full", "parking_lot"] } +async-trait = "0.1.83" +futures-concurrency = "7.6.2" +futures = { version = "=0.3.30", default-features = false, features = ["std", "async-await"] } +tokio = { workspace = true, features = ["full", "parking_lot", "tracing"] } tokio-stream = "0.1" dashmap = { version = "5.5", features = ["serde"]} clap = { workspace = true, features = ["derive", "env"] } +clap_complete = "=4.5.24" shadow-rs.workspace = true -nix = { version = "0.29.0", features = ["signal"] } -indexmap = { version = "2.6.0", features = ["serde"] } -futures-concurrency = "7.6.2" -futures = { version = "=0.3.30", default-features = false, features = ["std", "async-await"] } +# TODO: support more config formats +config = { version = "0.14.1", default-features = false, features = ["async", "json5", "json"] } + multihash = "0.19.2" json-canon = "0.1.3" data-encoding = "2.6.0" sha2 = "0.10.8" + pathdiff = "0.2.2" directories = "5.0.1" -async-trait = "0.1.83" +dialoguer = "0.11.0" +console = "0.15.8" +console-subscriber = { version = "0.4.1", optional = true } [build-dependencies] shadow-rs.workspace = true diff --git a/src/ghjk/cli.rs b/src/ghjk/cli.rs new file mode 100644 index 0000000..f7a0df1 --- /dev/null +++ b/src/ghjk/cli.rs @@ -0,0 +1,441 @@ +use std::process::ExitCode; + +use clap::builder::styling::AnsiColor; + +use crate::config::Config; +use crate::interlude::*; + +use crate::systems::{CliCommandAction, SystemCliCommand}; +use crate::{host, systems}; + +const DENO_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; + +pub async fn cli() -> Res { + /* tokio::spawn({ + async { + loop { + println!("{:?}: thread is not blocked", std::thread::current().id()); + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + } + } + }); */ + + let cwd = std::env::current_dir()?; + + let config = Config::source().await?; + + debug!("config sourced: {config:?}"); + + let Some(quick_err) = try_quick_cli(&config).await? else { + return Ok(ExitCode::SUCCESS); + }; + + let Some(ghjkdir_path) = config.ghjkdir.clone() else { + quick_err.exit(); + }; + + let deno_cx = { + // TODO: DENO_FLAGS param simlar to V8_FLAGS + let flags = denort::deno::args::Flags { + unstable_config: denort::deno::args::UnstableConfig { + features: DENO_UNSTABLE_FLAGS + .iter() + .copied() + .map(String::from) + .collect(), + ..default() + }, + no_lock: config.deno_lockfile.is_none(), + lock: config + .deno_lockfile + .as_ref() + .map(|path| path.to_string_lossy().into()), + internal: deno::args::InternalFlags { + cache_path: Some(config.deno_dir.clone()), + ..default() + }, + ..default() + }; + denort::worker::worker(flags, Some(Arc::new(Vec::new))).await? + }; + + let gcx = GhjkCtx { + config, + deno: deno_cx.clone(), + }; + let gcx = Arc::new(gcx); + + let (systems_deno, deno_sys_cx) = systems::deno::systems_from_deno( + &gcx, + &gcx.config + .repo_root + .join("src/deno_systems/mod.ts") + .wrap_err("repo url error")?, + &ghjkdir_path, + ) + .await?; + + let hcx = host::HostCtx::new( + gcx.clone(), + host::Config { + re_resolve: false, + locked: false, + re_serialize: false, + env_vars: std::env::vars().collect(), + cwd, + }, + systems_deno, + ); + + let hcx = Arc::new(hcx); + + let Some(mut systems) = host::systems_from_ghjkfile(hcx, &ghjkdir_path).await? else { + warn!("no ghjkfile found"); + quick_err.exit() + }; + + // let conf_json = serde_json::to_string_pretty(&systems.config)?; + // info!(%conf_json); + + use clap::*; + + let mut root_cmd = Cli::command(); + + debug!("collecting system commands"); + + let (sys_cmds, sys_actions) = match commands_from_systems(&systems).await { + Ok(val) => val, + Err(err) => { + systems.write_lockfile_or_log().await; + return Err(err); + } + }; + + for cmd in sys_cmds { + root_cmd = root_cmd.subcommand(cmd); + } + + debug!("checking argv matches"); + + let matches = match root_cmd.try_get_matches() { + Ok(val) => val, + Err(err) => { + systems.write_lockfile_or_log().await; + err.exit(); + } + }; + + match QuickComands::from_arg_matches(&matches) { + Ok(QuickComands::Print { commands }) => { + _ = commands.action(&gcx.config, Some(&systems.config))?; + return Ok(ExitCode::SUCCESS); + } + Ok(QuickComands::Deno { .. }) => { + unreachable!("deno quick cli will prevent this") + } + Err(err) => { + let kind = err.kind(); + use clap::error::ErrorKind; + if !(kind == ErrorKind::InvalidSubcommand + || kind == ErrorKind::InvalidValue + || kind == ErrorKind::DisplayHelp + || kind == ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand) + { + systems.write_lockfile_or_log().await; + err.exit(); + } + } + } + + let (cmd_path, mut action, action_matches) = match action_for_match(sys_actions, &matches).await + { + Ok(val) => val, + Err(err) => { + systems.write_lockfile_or_log().await; + return Err(err); + } + }; + + debug!(?cmd_path, "system command found"); + let Some(action) = action.action else { + systems.write_lockfile_or_log().await; + action.clap.print_long_help()?; + return Ok(std::process::ExitCode::FAILURE); + }; + + let res = action(action_matches.clone()) + .await + .wrap_err_with(|| format!("error on system command at path {cmd_path:?}")); + + systems.write_lockfile_or_log().await; + + deno_sys_cx.terminate().await?; + deno_cx.terminate().await?; + + res.map(|()| ExitCode::SUCCESS) +} + +/// Sections of the CLI do not require loading a ghjkfile. +pub async fn try_quick_cli(config: &Config) -> Res> { + use clap::*; + + let cli = match Cli::try_parse() { + Ok(val) => val, + Err(err) => { + let kind = err.kind(); + use clap::error::ErrorKind; + if kind == ErrorKind::InvalidSubcommand + || kind == ErrorKind::InvalidValue + || kind == ErrorKind::DisplayHelp + || kind == ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand + { + return Ok(Some(err)); + } + err.exit(); + } + }; + + match cli.quick_commands { + QuickComands::Print { commands } => { + if !commands.action(config, None)? { + return Ok(Some(clap::error::Error::new( + clap::error::ErrorKind::DisplayHelp, + ))); + } + } + QuickComands::Deno { .. } => unreachable!("deno quick cli will have prevented this"), + } + + Ok(None) +} + +const CLAP_STYLE: clap::builder::Styles = clap::builder::Styles::styled() + .header(AnsiColor::Yellow.on_default()) + .usage(AnsiColor::BrightBlue.on_default()) + .literal(AnsiColor::BrightBlue.on_default()) + .placeholder(AnsiColor::BrightBlue.on_default()); + +#[derive(Debug, clap::Parser)] +#[clap( + version, + about, + styles = CLAP_STYLE +)] +struct Cli { + #[command(subcommand)] + quick_commands: QuickComands, +} + +#[derive(clap::Subcommand, Debug)] +enum QuickComands { + /// Print different discovored or built values to stdout. + Print { + #[command(subcommand)] + commands: PrintCommands, + }, + /// Access the deno cli + Deno { + #[arg(raw(true))] + args: String, + }, +} + +#[derive(clap::Subcommand, Debug)] +enum PrintCommands { + /// Print the path to the data dir used by ghjk. + DataDirPath, + /// Print the path to the dir of the currently active ghjk context. + GhjkdirPath, + /// Print the path of the ghjkfile used. + GhjkfilePath, + /// Print the extracted and serialized config from the ghjkfile. + Config { + /// Use json format when printing config. + #[arg(long)] + json: bool, + }, +} + +impl PrintCommands { + /// The return value specifies weather or not the CLI is done or + /// weather it should continue on with serialization if this + /// action was invoked as part of the quick cli + fn action( + self, + cli_config: &Config, + serialized_config: Option<&host::SerializedConfig>, + ) -> Res { + Ok(match self { + PrintCommands::DataDirPath => { + println!("{}", cli_config.data_dir.display()); + true + } + // TODO: rename GHJK_DIR to GHJKDIR + PrintCommands::GhjkdirPath => { + if let Some(path) = &cli_config.ghjkdir { + // TODO: graceful termination on SIGPIPE + println!("{}", path.display()); + true + } else { + eyre::bail!("no ghjkdir found."); + } + } + PrintCommands::GhjkfilePath => { + if let Some(path) = &cli_config.ghjkdir { + println!("{}", path.display()); + true + } else { + eyre::bail!("no ghjkfile found."); + } + } + PrintCommands::Config { .. } => match serialized_config { + Some(config) => { + let conf_json = serde_json::to_string_pretty(&config)?; + println!("{conf_json}"); + true + } + None => false, + }, + }) + } +} + +type SysCmdActions = IndexMap; +struct SysCmdAction { + name: CHeapStr, + clap: clap::Command, + action: Option, + sub_commands: SysCmdActions, +} + +async fn commands_from_systems( + systems: &host::GhjkfileSystems, +) -> Res<(Vec, SysCmdActions)> { + fn inner(cmd: SystemCliCommand) -> (SysCmdAction, clap::Command) { + // apply styles here due to propagation + // breaking for these dynamic subcommands for some reason + let mut clap_cmd = cmd.clap.styles(CLAP_STYLE); + let mut sub_commands = IndexMap::new(); + for (id, cmd) in cmd.sub_commands { + let (sub_sys_cmd, sub_cmd) = inner(cmd); + clap_cmd = clap_cmd.subcommand(sub_cmd); + sub_commands.insert(id, sub_sys_cmd); + } + ( + SysCmdAction { + clap: clap_cmd.clone(), + name: cmd.name, + action: cmd.action, + sub_commands, + }, + clap_cmd, + ) + } + let mut commands = vec![]; + let mut conflict_tracker = HashMap::new(); + let mut actions = SysCmdActions::new(); + for (id, sys_inst) in &systems.sys_instances { + let cmds = sys_inst + .commands() + .await + .wrap_err_with(|| format!("error getting commands for system: {id}"))?; + for cmd in cmds { + let (sys_cmd, clap_cmd) = inner(cmd); + + if let Some(conflict) = conflict_tracker.insert(sys_cmd.name.clone(), id) { + eyre::bail!( + "system commannd conflict under name {:?} for modules {conflict:?} and {id:?}", + sys_cmd.name.clone(), + ); + } + actions.insert(sys_cmd.name.clone(), sys_cmd); + commands.push(clap_cmd); + } + } + Ok((commands, actions)) +} + +async fn action_for_match( + mut actions: SysCmdActions, + matches: &clap::ArgMatches, +) -> Res<(Vec, SysCmdAction, &clap::ArgMatches)> { + fn inner<'a>( + mut current: SysCmdAction, + matches: &'a clap::ArgMatches, + cmd_path: &mut Vec, + ) -> Res<(SysCmdAction, &'a clap::ArgMatches)> { + match matches.subcommand() { + Some((cmd_name, matches)) => { + cmd_path.push(cmd_name.into()); + match current.sub_commands.swap_remove(cmd_name) { + Some(action) => inner(action, matches, cmd_path), + None => { + eyre::bail!("no match found for cmd {cmd_path:?}") + } + } + } + None => Ok((current, matches)), + } + } + let mut cmd_path = vec![]; + let Some((cmd_name, matches)) = matches.subcommand() else { + unreachable!("clap prevents this branch") + }; + cmd_path.push(cmd_name.into()); + let Some(action) = actions.swap_remove(cmd_name) else { + eyre::bail!("no match found for cmd {cmd_path:?}"); + }; + let (action, matches) = inner(action, matches, &mut cmd_path)?; + Ok((cmd_path, action, matches)) +} + +/// TODO: keep more of this in deno next time it's updated +pub fn deno_quick_cli() -> Option<()> { + let argv = std::env::args_os().skip(1).collect::>(); + let first = argv.first()?; + if first != "deno" { + return None; + } + deno::util::unix::raise_fd_limit(); + deno::util::windows::ensure_stdio_open(); + deno_runtime::deno_permissions::set_prompt_callbacks( + Box::new(deno::util::draw_thread::DrawThread::hide), + Box::new(deno::util::draw_thread::DrawThread::show), + ); + + let future = async move { + // NOTE(lucacasonato): due to new PKU feature introduced in V8 11.6 we need to + // initialize the V8 platform on a parent thread of all threads that will spawn + // V8 isolates. + let flags = deno::resolve_flags_and_init(argv)?; + deno::run_subcommand(Arc::new(flags)).await + }; + + let result = deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics(future); + + match result { + Ok(exit_code) => deno_runtime::exit(exit_code), + Err(err) => exit_for_error(err), + } +} + +fn exit_with_message(message: &str, code: i32) -> ! { + tracing::error!("error: {}", message.trim_start_matches("error: ")); + deno_runtime::exit(code); +} + +fn exit_for_error(error: anyhow::Error) -> ! { + let mut error_string = format!("{error:?}"); + let error_code = 1; + + if let Some(e) = error.downcast_ref::() { + error_string = deno_runtime::fmt_errors::format_js_error(e); + } /* else if let Some(SnapshotFromLockfileError::IntegrityCheckFailed(e)) = + error.downcast_ref::() + { + error_string = e.to_string(); + error_code = 10; + } */ + + exit_with_message(&error_string, error_code); +} diff --git a/src/ghjk/config.rs b/src/ghjk/config.rs new file mode 100644 index 0000000..5157c90 --- /dev/null +++ b/src/ghjk/config.rs @@ -0,0 +1,286 @@ +use crate::interlude::*; + +#[derive(Debug)] +pub struct Config { + pub ghjkfile: Option, + pub ghjkdir: Option, + pub data_dir: PathBuf, + pub deno_dir: PathBuf, + pub deno_lockfile: Option, + pub repo_root: url::Url, +} + +#[derive(Deserialize)] +struct GlobalConfigFile { + data_dir: Option, + deno_dir: Option, + repo_root: Option, +} + +#[derive(Deserialize)] +struct LocalConfigFile { + #[serde(flatten)] + global: GlobalConfigFile, + deno_lockfile: Option, +} + +impl Config { + pub async fn source() -> Res { + let cwd = std::env::current_dir()?; + let xdg_dirs = directories::ProjectDirs::from("", "", "ghjk") + .expect_or_log("unable to resolve home dir"); + + let ghjkdir_path = match path_from_env(&cwd, "GHJK_DIR")? { + Some(val) => Some(val), + None => crate::utils::find_entry_recursive(&cwd, ".ghjk") + .await + .wrap_err("error trying to locate a .ghjk dir")?, + }; + + let ghjkfile_path = match path_from_env(&cwd, "GHJKFILE")? { + Some(val) => Some(val), + None => { + // NOTE: look for typescript ghjkfile + let ghjkfile_name = "ghjk.ts"; + match &ghjkdir_path { + Some(ghjkfile_path) => { + crate::utils::find_entry_recursive( + ghjkfile_path + .parent() + .expect_or_log("invalid GHJK_DIR path"), + ghjkfile_name, + ) + .await? + } + None => crate::utils::find_entry_recursive(&cwd, ghjkfile_name) + .await + .wrap_err_with(|| { + format!("error trying to locate a ghjkfile of kind \"{ghjkfile_name}\"") + })?, + } + } + }; + + // if ghjkfile var is set, set the GHJK_DIR overriding + // any set by the user + let (ghjkfile_path, ghjkdir_path) = if let Some(path) = ghjkfile_path { + let file_path = tokio::fs::canonicalize(&path) + .await + .wrap_err_with(|| format!("error canonicalizing ghjkfile path at {path:?}"))?; + let dir_path = file_path.parent().unwrap().join(".ghjk"); + (Some(file_path), Some(dir_path)) + } else { + (None, ghjkdir_path) + }; + + if ghjkdir_path.is_none() && ghjkfile_path.is_none() { + warn!( + "ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.", + ); + } + + let mut config = Config { + ghjkfile: ghjkfile_path, + ghjkdir: ghjkdir_path.clone(), + data_dir: xdg_dirs.data_dir().to_owned(), + deno_dir: xdg_dirs.data_dir().join("deno"), + deno_lockfile: ghjkdir_path.as_ref().map(|path| path.join("deno.lock")), + repo_root: { + if cfg!(debug_assertions) { + url::Url::from_file_path(&cwd) + .expect_or_log("cwd error") + .join(&format!("{}/", cwd.file_name().unwrap().to_string_lossy())) + .wrap_err("repo url error")? + } else { + const BASE_URL: &str = + "https://raw.githubusercontent.com/metatypedev/metatype/"; + // repo root url must end in slash due to + // how Url::join works + let url = BASE_URL.to_owned() + crate::shadow::COMMIT_HASH + "/"; + url::Url::parse(&url).expect("repo url error") + } + }, + }; + + let global_config_path = match path_from_env(&cwd, "GHJK_CONFIG_DIR")? { + Some(val) => val, + None => xdg_dirs.config_dir().join("config"), + }; + + // we use builtin config-rs File implementation + // which relies on sync std + let config = tokio::task::spawn_blocking(move || { + { + config + .source_global_config(&global_config_path) + .wrap_err_with(|| { + format!("error sourcing global config from {global_config_path:?}") + })?; + } + + if let Some(ghjkdir_path) = &ghjkdir_path { + let file_path = ghjkdir_path.join("config"); + config + .source_local_config(&file_path) + .wrap_err_with(|| format!("error sourcing local config from {file_path:?}"))?; + }; + + config + .source_env_config(&cwd) + .wrap_err("error sourcing config from environment variables")?; + + if !config.repo_root.path().ends_with("/") { + config + .repo_root + .set_path(&format!("{}/", config.repo_root.path())); + } + + eyre::Ok(config) + }) + .await + .expect_or_log("tokio error")?; + + if let Some(path) = &config.ghjkdir { + let ignore_path = path.join(".gitignore"); + if !matches!(tokio::fs::try_exists(&ignore_path).await, Ok(true)) { + tokio::fs::create_dir_all(path) + .await + .wrap_err_with(|| format!("error creating ghjkdir at {path:?}"))?; + tokio::fs::write( + &ignore_path, + "envs +hash.json", + ) + .await + .wrap_err_with(|| format!("error writing ignore file at {ignore_path:?}"))?; + } + } + Ok(config) + } + + fn source_global_config(&mut self, file_path: &Path) -> Res<()> { + let GlobalConfigFile { + deno_dir, + data_dir, + repo_root, + } = config::Config::builder() + .add_source(config::File::with_name(&file_path.to_string_lossy()[..]).required(false)) + .build() + .wrap_err("error reading config file")? + .try_deserialize() + .wrap_err("error deserializing config file")?; + if let Some(path) = data_dir { + self.data_dir = + resolve_config_path(&path, file_path).wrap_err("error resolving data_dir")?; + } + if let Some(path) = deno_dir { + self.deno_dir = + resolve_config_path(&path, file_path).wrap_err("error resolving deno_dir")?; + } + if let Some(path) = repo_root { + self.repo_root = deno_core::resolve_url_or_path(&path, file_path) + .map_err(|err| ferr!(Box::new(err))) + .wrap_err("error resolving repo_root")?; + } + Ok(()) + } + + fn source_local_config(&mut self, file_path: &Path) -> Res<()> { + let LocalConfigFile { + global: + GlobalConfigFile { + data_dir, + deno_dir, + repo_root, + }, + deno_lockfile, + } = config::Config::builder() + .add_source(config::File::with_name(&file_path.to_string_lossy()).required(false)) + .build() + .wrap_err("error reading config file")? + .try_deserialize() + .wrap_err("error deserializing config file")?; + + if let Some(path) = data_dir { + self.data_dir = + resolve_config_path(&path, file_path).wrap_err("error resolving data_dir")?; + } + if let Some(path) = deno_dir { + self.deno_dir = + resolve_config_path(&path, file_path).wrap_err("error resolving deno_dir")?; + } + if let Some(path) = deno_lockfile { + self.deno_lockfile = Some( + resolve_config_path(&path, file_path).wrap_err("error resolving deno_lockfile")?, + ); + } + if let Some(path) = repo_root { + self.repo_root = deno_core::resolve_url_or_path(&path, file_path) + .map_err(|err| ferr!(Box::new(err))) + .wrap_err("error resolving repo_root")?; + } + Ok(()) + } + + fn source_env_config(&mut self, cwd: &Path) -> Res<()> { + let LocalConfigFile { + global: + GlobalConfigFile { + data_dir, + deno_dir, + repo_root, + }, + deno_lockfile, + } = config::Config::builder() + .add_source(config::Environment::with_prefix("GHJK")) + .build() + .wrap_err("error reading config file")? + .try_deserialize() + .wrap_err("error deserializing config file")?; + + if let Some(path) = data_dir { + self.data_dir = resolve_config_path(&path, cwd).wrap_err("error resolving data_dir")?; + } + if let Some(path) = deno_dir { + self.deno_dir = resolve_config_path(&path, cwd).wrap_err("error resolving deno_dir")?; + } + if let Some(path) = deno_lockfile { + self.deno_lockfile = if path != "off" { + Some(resolve_config_path(&path, cwd).wrap_err("error resolving deno_lockfile")?) + } else { + None + }; + } + if let Some(path) = repo_root { + self.repo_root = deno_core::resolve_url_or_path(&path, cwd) + .map_err(|err| ferr!(Box::new(err))) + .wrap_err("error resolving repo_root")?; + } + Ok(()) + } +} + +fn resolve_config_path(path: impl AsRef, config_path: &Path) -> Res { + let path = config_path.join(&path); + let path = std::path::absolute(&path) + .wrap_err_with(|| format!("error absolutizing path at {path:?}"))?; + Ok(path) +} + +fn path_from_env(cwd: &Path, env_name: &str) -> Res> { + let path = match std::env::var(env_name) { + Ok(path) => Some(PathBuf::from(path)), + Err(std::env::VarError::NotUnicode(os_str)) => Some(PathBuf::from(os_str)), + Err(std::env::VarError::NotPresent) => None, + }; + + if let Some(path) = path { + let path = cwd.join(&path); + + Ok(Some(std::path::absolute(&path).wrap_err_with(|| { + format!("error absolutizing path {path:?} from env ${env_name}") + })?)) + } else { + Ok(None) + } +} diff --git a/src/ghjk/ext.rs b/src/ghjk/ext.rs index c515700..706f1dd 100644 --- a/src/ghjk/ext.rs +++ b/src/ghjk/ext.rs @@ -34,19 +34,22 @@ impl ExtConfig { Self::default() } - pub fn callbacks_handle(&mut self) -> callbacks::CallbacksHandle { - let (line, handle) = callbacks::CallbackLine::new(); + pub fn callbacks_handle( + &mut self, + dworker: &denort::worker::DenoWorkerHandle, + ) -> callbacks::CallbacksHandle { + let (line, handle) = callbacks::CallbackLine::new(dworker); self.callbacks_rx = Arc::new(std::sync::Mutex::new(line)); handle } fn inject(self, state: &mut deno_core::OpState) { + let callbacks = callbacks::worker(&self); let ctx = ExtContext { config: self, - callbacks: default(), + callbacks, }; - callbacks::worker(ctx.clone()); state.put(ctx); } } @@ -74,7 +77,7 @@ fn customizer(ext: &mut deno_core::Extension) { #[derive(Clone)] struct ExtContext { - callbacks: callbacks::Callbacks, + callbacks: Option, config: ExtConfig, } diff --git a/src/ghjk/ext/callbacks.rs b/src/ghjk/ext/callbacks.rs index 2f63aa3..72507ad 100644 --- a/src/ghjk/ext/callbacks.rs +++ b/src/ghjk/ext/callbacks.rs @@ -9,6 +9,7 @@ use deno_core::OpState; use deno_core as deno_core; // necessary for re-exported macros to work use tokio::sync::{mpsc, oneshot}; +use super::ExtConfig; use super::ExtContext; #[derive(Debug, thiserror::Error)] @@ -23,37 +24,41 @@ pub enum CallbackError { V8Error(eyre::Report), } +struct CallbackCtx { + rx: tokio::sync::mpsc::Receiver, + term_signal: tokio::sync::watch::Receiver, +} + /// Line used by the callback_worker to receive /// invocations. #[derive(Default)] pub struct CallbackLine { - line: Option>, + cx: Option, was_set: bool, } impl CallbackLine { - pub fn new() -> (Self, CallbacksHandle) { + pub fn new(dworker: &denort::worker::DenoWorkerHandle) -> (Self, CallbacksHandle) { let (tx, rx) = tokio::sync::mpsc::channel(1); ( Self { was_set: true, - line: Some(rx), + cx: Some(CallbackCtx { + rx, + term_signal: dworker.term_signal_watcher(), + }), }, CallbacksHandle { sender: tx }, ) } - fn take(&mut self) -> Option> { + fn take(&mut self) -> Option { if !self.was_set { - warn!("callback line was not set"); + // debug!("callback line was not set, worker callbacks will noop"); return None; } - match self.line.take() { - Some(val) => Some(val), - None => { - panic!("extensions were injected twice") - } - } + // debug!("realm with callbacks just had a child, it won't inherit callback feature"); + self.cx.take() } } @@ -104,53 +109,67 @@ pub struct Callbacks { /// /// Stored callbacks are not Sync so this expects to be started /// on the same thread as deno. -pub fn worker(ctx: ExtContext) { - let mut line = { - let mut line = ctx.config.callbacks_rx.lock().expect_or_log("mutex err"); - let Some(line) = line.take() else { - return; - }; - line +/// This will return none if the callback line was set or +/// the callback line was already taken. This happens +/// with child WebWorkers for example which don't currently +/// support callbacks. +pub fn worker(config: &ExtConfig) -> Option { + let CallbackCtx { + mut rx, + term_signal, + } = { + let mut line = config.callbacks_rx.lock().expect_or_log("mutex err"); + line.take()? }; - assert_eq!( - std::thread::current().name(), - Some(denort::WORKER_THREAD_NAME), - "callback worker must be launched on deno worker started with a LocalSet" - ); - // assumes local set - tokio::task::spawn_local( + + let callbacks = Callbacks::default(); + let callbacks_2go = callbacks.clone(); + denort::unsync::spawn( + "callback-worker", async move { - debug!("callback worker starting"); - while let Some(msg) = line.recv().await { - debug!(?msg, "callback worker msg"); + trace!("callback worker starting"); + while let Some(msg) = rx.recv().await { + trace!(?msg, "msg"); match msg { CallbacksMsg::Exec { key: name, args, response_channel, } => response_channel - .send(ctx.exec_callback(name, args).await) + .send( + callbacks_2go + .exec_callback(name, args, term_signal.clone()) + .await, + ) .expect_or_log("channel error"), } } - debug!("callback worker done"); + trace!("callback worker done"); } - .instrument(tracing::debug_span!("callback-worker")), + .instrument(tracing::trace_span!("callback-worker")), ); + Some(callbacks) } -impl ExtContext { +impl Callbacks { + #[tracing::instrument(skip(self, args))] pub async fn exec_callback( &self, key: CHeapStr, args: serde_json::Value, + mut term_signal: tokio::sync::watch::Receiver, ) -> Result { - let Some(cb) = self.callbacks.store.get(&key[..]).map(|cb| cb.clone()) else { + let Some(cb) = self.store.get(&key[..]).map(|cb| cb.clone()) else { return Err(CallbackError::NotFound { key: key.to_string(), }); }; + if *term_signal.borrow_and_update() { + trace!("callback invoked on terminated runtime"); + return Err(CallbackError::V8Error(ferr!("deno is shutting down"))); + } + let (tx, rx) = oneshot::channel::>(); // we use the sender to spawn work on the v8 thread @@ -168,6 +187,7 @@ impl ExtContext { // and yet we're transmuting it to a Local here. // This is observed from the deno codebase // and I can't explain it + // SAFETY: cargo culted from deno codebase let func = unsafe { std::mem::transmute::, v8::Local>( cb.js_fn, @@ -195,27 +215,32 @@ impl ExtContext { if res.is_promise() { let promise = v8::Local::::try_from(res).unwrap(); - denort::promises::watch_promise(scope, promise, move |scope, _rf, res| { - let res = match res { - Ok(val) => serde_v8::from_v8(scope, val).map_err(|err| { - CallbackError::ProtocolError( - ferr!(err) - .wrap_err("error deserializaing promise result from v8"), - ) - }), - Err(err) => Err(CallbackError::JsError(ferr!( - "callback promise rejection: {}", - err.to_rust_string_lossy(scope) - ))), /* Err(err) => match serde_v8::from_v8(scope, err) { - Ok(json) => Err(CallbackError::JsError(json)), - Err(err) => Err(CallbackError::ProtocolError( - ferr!(err) - .wrap_err("error deserializaing promise rejection from v8"), - )), - }, */ - }; - tx.send(res).expect_or_log("channel error") - }); + let deno_shutting_down = + denort::promises::watch_promise(scope, promise, move |scope, _rf, res| { + let res = + match res { + Ok(val) => serde_v8::from_v8(scope, val).map_err(|err| { + CallbackError::ProtocolError(ferr!(err).wrap_err( + "error deserializaing promise result from v8", + )) + }), + Err(err) => Err(CallbackError::JsError(ferr!( + "callback promise rejection: {}", + err.to_rust_string_lossy(scope) + ))), /* Err(err) => match serde_v8::from_v8(scope, err) { + Ok(json) => Err(CallbackError::JsError(json)), + Err(err) => Err(CallbackError::ProtocolError( + ferr!(err) + .wrap_err("error deserializaing promise rejection from v8"), + )), + }, */ + }; + tx.send(res).expect_or_log("channel error") + }) + .is_none(); + if deno_shutting_down { + return Err(CallbackError::V8Error(ferr!("js runtime is shutting down"))); + }; Ok(None) } else { let res = serde_v8::from_v8(scope, res).map_err(|err| { @@ -228,11 +253,18 @@ impl ExtContext { }) }); - let res = match join_handle.await.expect_or_log("tokio error")? { - Some(res) => res, - None => { - debug!("waiting for callback proimse"); - rx.await.expect_or_log("channel error")? + // if the callback is not async, we recieve the value right away + if let Some(res) = join_handle.await.expect_or_log("tokio error")? { + return Ok(res); + }; + + let res = tokio::select! { + _ = term_signal.wait_for(|signal| *signal) => { + trace!("callback worker recieved term signal"); + return Err(CallbackError::V8Error(ferr!("deno terminated waiting on callback"))); + }, + res = rx => { + res.expect_or_log("channel error")? } }; @@ -269,6 +301,7 @@ unsafe impl Send for SendPtr {} } } */ +#[tracing::instrument(skip(state, cb))] #[deno_core::op2] pub fn op_callbacks_set( state: Rc>, @@ -282,7 +315,11 @@ pub fn op_callbacks_set( (ctx.clone(), sender.clone()) }; - ctx.callbacks.store.insert( + let Some(callbacks) = ctx.callbacks else { + warn!("callback set but callback feature is not enabled"); + anyhow::bail!("callbacks feature is not enabled"); + }; + callbacks.store.insert( name.into(), Callback { js_fn: SendPtr(cb.into_raw()), diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index 4ded93f..73ed645 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -1,10 +1,13 @@ +use std::io::IsTerminal; + use crate::interlude::*; use crate::systems::*; mod deno; mod hashfile; -use hashfile::*; + +use hashfile::HashObj; #[derive(Debug)] pub struct Config { @@ -26,7 +29,7 @@ pub struct HostCtx { pub config: Config, #[educe(Debug(ignore))] pub systems: HashMap, - pub file_hash_memo: DHashMap, + pub file_hash_memo: DHashMap, } impl HostCtx { @@ -45,12 +48,16 @@ impl HostCtx { } #[tracing::instrument(skip(hcx))] -pub async fn systems_from_ghjkfile(hcx: Arc) -> Res> { +pub async fn systems_from_ghjkfile( + hcx: Arc, + ghjkdir_path: &Path, +) -> Res> { let (hashfile_path, lockfile_path) = ( - hcx.gcx.ghjk_dir_path.join("hash.json"), - hcx.gcx.ghjk_dir_path.join("lock.json"), + ghjkdir_path.join("hash.json"), + ghjkdir_path.join("lock.json"), ); + // read both files concurrently let (hash_obj, lock_obj) = ( HashObj::from_file(&hashfile_path), LockObj::from_file(&lockfile_path), @@ -58,9 +65,38 @@ pub async fn systems_from_ghjkfile(hcx: Arc) -> Res val, + Err(hashfile::HashfileError::Serialization(_)) => { + error!("hashfile is corrupt, discarding"); + None + } + Err(hashfile::HashfileError::Other(err)) => return Err(err), + }, + match lock_obj { + Ok(val) => val, + Err(LockfileError::Serialization(err)) => { + // interactive discard of lockfile if in an interactive shell + if std::io::stderr().is_terminal() + && tokio::task::spawn_blocking(|| { + dialoguer::Confirm::new() + .with_prompt("lockfile is corrupt, discard?") + .default(false) + .interact() + }) + .await + .expect_or_log("tokio error") + .wrap_err("prompt error")? + { + None + } else { + return Err(ferr!(err).wrap_err("corrupt lockfile")); + } + } + Err(LockfileError::Other(err)) => return Err(err), + }, ); if hcx.config.locked { @@ -72,10 +108,14 @@ pub async fn systems_from_ghjkfile(hcx: Arc) -> Res) -> Res) -> Res) -> Res) -> Res, pub config: Arc, hash_obj: HashObj, - sys_instances: IndexMap, + pub sys_instances: IndexMap, old_lock_obj: Option, lockfile_path: PathBuf, hashfile_path: PathBuf, @@ -211,6 +260,12 @@ pub struct GhjkfileSystems { } impl GhjkfileSystems { + pub async fn write_lockfile_or_log(&mut self) { + if let Err(err) = self.write_lockfile().await { + error!("error writing lockfile: {err}"); + } + } + #[tracing::instrument(skip(self))] pub async fn write_lockfile(&mut self) -> Res<()> { let mut lock_obj = LockObj { @@ -235,13 +290,13 @@ impl GhjkfileSystems { if self.hcx.config.locked { warn!("locked flag set, changes to lockfile discarded"); } else { - debug!(lockfile_path = ?self.lockfile_path, ?lock_obj, "writing lock.json"); - /* tokio::fs::write( + trace!(lockfile_path = ?self.lockfile_path, /* ?lock_obj, */ "writing lock.json"); + tokio::fs::write( &self.lockfile_path, serde_json::to_vec_pretty(&lock_obj).expect_or_log("error jsonifying lockfile"), ) .await - .wrap_err("error writing to lockfile")?; */ + .wrap_err("error writing to lockfile")?; self.old_lock_obj.replace(lock_obj); } } @@ -252,14 +307,14 @@ impl GhjkfileSystems { if self.hcx.config.locked { unreachable!("code should have early exited"); } - debug!(hashfile_path = ?self.hashfile_path, hash_obj= ?self.hash_obj, "writing hash.json"); - /* tokio::fs::write( + trace!(hashfile_path = ?self.hashfile_path, /* hash_obj= ?self.hash_obj, */ "writing hash.json"); + tokio::fs::write( &self.hashfile_path, serde_json::to_vec_pretty(&self.hash_obj) .expect_or_log("error jsonifying hashfile"), ) .await - .wrap_err("error writing to lockfile")?; */ + .wrap_err("error writing to lockfile")?; self.hashfile_written = true; } Ok(()) @@ -273,32 +328,11 @@ async fn serialize_ghjkfile(hcx: &HostCtx, path: &Path) -> Res<(Arc, } +#[derive(Debug, thiserror::Error)] +pub enum LockfileError { + #[error("error parsing lockfile:{0}")] + Serialization(serde_json::Error), + #[error("{0}")] + Other(eyre::Report), +} + impl LockObj { /// The lock.json file stores the serialized config and some entries /// from systems. It's primary purpose is as a memo store to avoid /// re-serialization on each CLI invocation. - pub async fn from_file(path: &Path) -> Res { - let raw = tokio::fs::read(path) - .await - .wrap_err("error reading hash.json")?; - serde_json::from_slice(&raw).wrap_err("error parsing lock.json") + pub async fn from_file(path: &Path) -> Result, LockfileError> { + let raw = match tokio::fs::read(path).await { + Ok(val) => val, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(err) => return Err(LockfileError::Other(ferr!("error reading hashfile: {err}"))), + }; + serde_json::from_slice(&raw).map_err(LockfileError::Serialization) } } diff --git a/src/ghjk/host/deno.rs b/src/ghjk/host/deno.rs index 9703c6d..2ab871e 100644 --- a/src/ghjk/host/deno.rs +++ b/src/ghjk/host/deno.rs @@ -18,6 +18,7 @@ pub async fn serialize_deno_ghjkfile( ) -> Res { let main_module = hcx .gcx + .config .repo_root .join("files/deno/bindings.ts") .wrap_err("repo url error")?; diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs index 7c67d7f..aa5fb2b 100644 --- a/src/ghjk/host/hashfile.rs +++ b/src/ghjk/host/hashfile.rs @@ -16,20 +16,63 @@ pub struct HashObj { pub listed_files: Vec, } +#[derive(Debug, thiserror::Error)] +pub enum HashfileError { + #[error("error parsing hashfile: {0}")] + Serialization(serde_json::Error), + #[error("{0}")] + Other(eyre::Report), +} + impl HashObj { + #[tracing::instrument(skip(hcx, res))] + pub async fn from_result( + hcx: &super::HostCtx, + ghjkfile_path: &Path, + res: &super::SerializationResult, + ) -> Res { + Ok(HashObj { + version: "0".into(), + env_var_hashes: env_var_digests( + &hcx.config.env_vars, + res.accessed_env_keys.iter().map(|key| key.as_ref()), + ), + ghjkfile_hash: file_digest_hash(hcx, ghjkfile_path) + .await? + .expect_or_log("ghjkfile is gone"), + listed_files: res + .listed_file_paths + .iter() + .map(|path| pathdiff::diff_paths(path, &hcx.config.cwd).unwrap_or_log()) + .collect(), + read_file_hashes: file_digests( + hcx, + res.read_file_paths + .iter() + .map(|path| path.as_ref()) + .collect(), + ) + .await?, + }) + } + /// The hash.json file stores the digests of all external accesses /// of a ghjkfile during serialization. The primary purpose is to /// do "cache invalidation" on ghjkfiles, re-serializing them if /// any of the digests change. - pub async fn from_file(path: &Path) -> Res { - let raw = tokio::fs::read(path) - .await - .wrap_err("error reading hash.json")?; - serde_json::from_slice(&raw).wrap_err("error parsing hash.json") + pub async fn from_file(path: &Path) -> Result, HashfileError> { + let raw = match tokio::fs::read(path).await { + Ok(val) => val, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(err) => return Err(HashfileError::Other(ferr!("error reading hashfile: {err}"))), + }; + serde_json::from_slice(&raw).map_err(HashfileError::Serialization) } + #[tracing::instrument(skip(hcx))] pub async fn is_stale(&self, hcx: &HostCtx, ghjkfile_hash: &str) -> Res { if self.ghjkfile_hash != ghjkfile_hash { + trace!("stale ghjkfile hash"); return Ok(true); } { @@ -38,12 +81,14 @@ impl HashObj { self.env_var_hashes.keys().map(|key| &key[..]), ); if self.env_var_hashes != new_digest { + trace!("stale env var digests"); return Ok(true); } } { for path in &self.listed_files { if !matches!(tokio::fs::try_exists(path).await, Ok(true)) { + trace!("stale listed files"); return Ok(true); } } @@ -59,6 +104,7 @@ impl HashObj { ) .await? { + trace!("stale read files digest"); return Ok(true); } } @@ -66,7 +112,7 @@ impl HashObj { } } -pub fn env_var_digests<'a>( +fn env_var_digests<'a>( all: &IndexMap, accessed: impl Iterator, ) -> IndexMap> { @@ -80,11 +126,31 @@ pub fn env_var_digests<'a>( .collect() } -pub async fn file_digests( +async fn file_digests( hcx: &HostCtx, read_files: Vec<&Path>, ) -> Res>> { - let out = read_files + // FIXME: this will exhaust memory if the number of files is large + // ConcurrentStream supports limiting concurrency but has a bug + // tracked at https://github.com/yoshuawuyts/futures-concurrency/issues/203 + futures::future::join_all( + read_files + .into_iter() + .map(|path| { + async move { + let path = std::path::absolute(path)?; + let hash = file_digest_hash(hcx, &path).await?; + let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); + Ok((relative_path, hash)) + } + .boxed() + }) + .collect::>(), + ) + .await + .into_iter() + .collect() + /* let out = read_files .into_co_stream() .map(|path| async move { let path = tokio::fs::canonicalize(path).await?; @@ -94,17 +160,26 @@ pub async fn file_digests( }) .collect::>>() .await?; - Ok(out.into_iter().collect()) + Ok(out.into_iter().collect()) */ } pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> { - let path = tokio::fs::canonicalize(path) - .await - .wrap_err("error resolving realpath")?; + let path = match tokio::fs::canonicalize(path).await { + Ok(val) => val, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + return Ok(None); + } + Err(err) => return Err(err).wrap_err("error resolving realpath"), + }; match tokio::fs::metadata(&path).await { Ok(stat) => { let content_hash = if stat.file_type().is_file() || stat.file_type().is_symlink() { - Some(file_content_digest_hash(hcx, &path).await?) + Some( + file_content_digest_hash(hcx, &path) + .await? + .await + .map_err(|err| ferr!(err))?, + ) } else { None }; @@ -119,21 +194,36 @@ pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> } } -pub async fn file_content_digest_hash(hcx: &HostCtx, path: &Path) -> Res { - let path = tokio::fs::canonicalize(path) - .await - .wrap_err("error resolving realpath")?; +pub type SharedFileContentDigestFuture = + futures::future::Shared>>; + +async fn file_content_digest_hash( + hcx: &HostCtx, + path: &Path, +) -> Res { + let path = path.to_owned(); use dashmap::mapref::entry::*; match hcx.file_hash_memo.entry(path.clone()) { Entry::Occupied(occupied_entry) => Ok(occupied_entry.get().clone()), Entry::Vacant(vacant_entry) => { - // FIXME: optimize by stream hashing, this reads whole file into memory - let file = tokio::fs::read(path) - .await - .wrap_err("error reading file for")?; - let hash: CHeapStr = crate::utils::encode_base32_multibase(file).into(); - vacant_entry.insert(hash.clone()); - Ok(hash) + let shared = vacant_entry + .insert( + async { + let file = tokio::fs::File::open(path) + .await + .map_err(|err| format!("error opening file: {err}"))?; + let hash: CHeapStr = crate::utils::hash_reader(file) + .await + .map_err(|err| format!("error hashing file reader {err}"))? + .into(); + Ok(hash) + } + .boxed() + .shared(), + ) + .value() + .clone(); + Ok(shared) } } } diff --git a/src/ghjk/js/00_runtime.js b/src/ghjk/js/00_runtime.js index 70e342e..89498fa 100644 --- a/src/ghjk/js/00_runtime.js +++ b/src/ghjk/js/00_runtime.js @@ -26,7 +26,7 @@ const op_callbacks_set = getOp("op_callbacks_set"); /** * @type {import('./runtime.d.ts').GhjkNs} */ -const Ghjk = { +const ____GhjkHost = { blackboard: { get: getOp("op_blackboard_get"), set: getOp("op_blackboard_set"), @@ -40,4 +40,4 @@ const Ghjk = { hostcall: getOp("op_hostcall"), }; -globalThis.Ghjk = Ghjk; +globalThis.____GhjkHost = ____GhjkHost; diff --git a/src/ghjk/js/runtime.js b/src/ghjk/js/runtime.js index c7d977e..2931f83 100644 --- a/src/ghjk/js/runtime.js +++ b/src/ghjk/js/runtime.js @@ -3,7 +3,8 @@ //! This file provides the import point for types and values defined in: // - ./00_runtime.js: which is preloaded by the custom deno runtime // - ./runtime.d.ts: which types the objects from the preload -// -// The preload directly adds the Meta object the global scope but we can hide -// that implementation detail and users will "import" `Meta` from this file instead. -// Or at least that is what will appear to be happening to in the type system. + +/** + * @type {import('./runtime.d.ts').GhjkNs} + */ +export const Ghjk = globalThis.____GhjkHost; diff --git a/src/ghjk/log.rs b/src/ghjk/log.rs index 76ade7e..34279bb 100644 --- a/src/ghjk/log.rs +++ b/src/ghjk/log.rs @@ -25,9 +25,9 @@ Platform: {platform} Version: {version} Args: {args:?} "#, - platform = crate::build::BUILD_TARGET, + platform = crate::shadow::BUILD_TARGET, // TODO: include commit sha - version = crate::build::PKG_VERSION, + version = crate::shadow::PKG_VERSION, args = std::env::args().collect::>() )); @@ -49,16 +49,13 @@ Args: {args:?} eyre_panic_hook(panic_info); // - Tokio does not exit the process when a task panics, so we define a custom // panic hook to implement this behaviour. - // std::process::exit(1); + std::process::exit(1); })); - // FIXME: for some reason, the tests already have - // an eyre_hook - #[cfg(not(test))] _eyre_hook.install().unwrap(); if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info,actix_server=warn"); + std::env::set_var("RUST_LOG", "info"); } #[cfg(not(debug_assertions))] if std::env::var("RUST_SPANTRACE").is_err() { @@ -83,13 +80,21 @@ Args: {args:?} let filter = tracing_subscriber::EnvFilter::from_default_env(); - tracing_subscriber::registry() + let registry = tracing_subscriber::registry(); + + #[cfg(feature = "console-subscriber")] + // FIXME: this isn't being picked up by tokio-console + let registry = registry.with(console_subscriber::spawn()); + + let registry = registry // filter on values from RUST_LOG .with(filter) // subscriber that emits to stderr .with(fmt) // instrument errors with SpanTraces, used by color-eyre - .with(tracing_error::ErrorLayer::default()) - .init(); + .with(tracing_error::ErrorLayer::default()); + + registry.init(); + // console_subscriber::init(); }); } diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index 7427988..9c78c3e 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -31,7 +31,8 @@ mod interlude { mod host; -mod cli {} +mod cli; +mod config; mod ext; mod log; mod systems; @@ -39,177 +40,35 @@ mod utils; use crate::interlude::*; -fn main() -> Res<()> { +fn main() -> Res { + let None = cli::deno_quick_cli() else { + unreachable!(); + }; + // FIXME: change signal handler for children // FIXME: use unix_sigpipe once https://github.com/rust-lang/rust/issues/97889 lands unsafe { use nix::sys::signal::*; signal(Signal::SIGPIPE, SigHandler::SigDfl)?; } + std::env::set_var("DENO_NO_UPDATE_CHECK", "1"); + log::init(); denort::init(); + debug!(version = shadow::PKG_VERSION, "ghjk CLI"); + tokio::runtime::Builder::new_current_thread() .enable_all() .build()? - .block_on(cli())?; - Ok(()) + .block_on(cli::cli()) } use shadow_rs::shadow; -shadow!(build); - -const DENO_UNSTABLE_FLAGS: &[&str] = &["worker-options", "kv"]; - -async fn cli() -> Res<()> { - debug!(version = build::PKG_VERSION, "ghjk CLI"); - - let cwd = std::env::current_dir()?; - - let config = { - let ghjk_dir_path = match std::env::var("GHJK_DIR") { - Ok(path) => Some(PathBuf::from(path)), - Err(std::env::VarError::NotUnicode(os_str)) => Some(PathBuf::from(os_str)), - Err(std::env::VarError::NotPresent) => { - utils::find_entry_recursive(&cwd, ".ghjk").await? - } - }; - - let ghjk_dir_path = if let Some(path) = ghjk_dir_path { - Some(tokio::fs::canonicalize(path).await?) - } else { - None - }; - - let ghjkfile_path = match &ghjk_dir_path { - Some(ghjkfile_path) => { - utils::find_entry_recursive( - ghjkfile_path - .parent() - .expect_or_log("invalid GHJK_DIR path"), - "ghjk.ts", - ) - .await? - } - None => utils::find_entry_recursive(&cwd, "ghjk.ts").await?, - }; - - let ghjkfile_path = if let Some(path) = ghjkfile_path { - Some(tokio::fs::canonicalize(path).await?) - } else { - None - }; - - if ghjk_dir_path.is_none() && ghjkfile_path.is_none() { - warn!( - "ghjk could not find any ghjkfiles or ghjkdirs, try creating a `ghjk.ts` script.", - ); - } - - let share_dir_path = match std::env::var("GHJK_SHARE_DIR") { - Ok(path) => PathBuf::from(path), - Err(std::env::VarError::NotUnicode(os_str)) => PathBuf::from(os_str), - Err(std::env::VarError::NotPresent) => directories::BaseDirs::new() - .expect_or_log("unable to resolve home dir") - .data_local_dir() - .join("ghjk"), - }; - Config { - ghjkfile_path, - ghjk_dir_path, - share_dir_path, - } - }; - - let deno_cx = denort::worker( - denort::deno::args::Flags { - unstable_config: denort::deno::args::UnstableConfig { - features: DENO_UNSTABLE_FLAGS - .iter() - .copied() - .map(String::from) - .collect(), - ..default() - }, - ..default() - }, - Some(Arc::new(Vec::new)), - ) - .await?; - - if let Some(ghjk_dir_path) = config.ghjk_dir_path { - let gcx = GhjkCtx { - ghjk_dir_path, - ghjkfile_path: config.ghjkfile_path, - share_dir_path: config.share_dir_path, - repo_root: url::Url::from_file_path(&cwd) - .expect_or_log("cwd error") - // repo root url must end in slash due to - // how Url::join works - .join(&format!("{}/", cwd.file_name().unwrap().to_string_lossy())) - .wrap_err("repo url error")?, - deno: deno_cx.clone(), - }; - let gcx = Arc::new(gcx); - - let systems_deno = systems::deno::systems_from_deno( - &gcx, - &gcx.repo_root - .join("src/deno_systems/mod.ts") - .wrap_err("repo url error")?, - ) - .await?; - - let hcx = host::HostCtx::new( - gcx, - host::Config { - re_resolve: false, - locked: false, - re_serialize: false, - env_vars: std::env::vars().collect(), - cwd, - }, - systems_deno, - ); - - let hcx = Arc::new(hcx); - - if let Some(mut systems) = host::systems_from_ghjkfile(hcx).await? { - let conf_json = serde_json::to_string_pretty(&systems.config)?; - info!(%conf_json); - systems.write_lockfile().await?; - } else { - warn!("no ghjkfile found"); - } - } - - // tokio::task::spawn_blocking(|| deno_cx.terminate()); - - Ok(()) -} +shadow!(shadow); #[derive(Debug)] pub struct GhjkCtx { - deno: denort::DenoWorkerHandle, - repo_root: url::Url, - ghjkfile_path: Option, - ghjk_dir_path: PathBuf, - share_dir_path: PathBuf, -} - -#[derive(Debug)] -struct Config { - ghjkfile_path: Option, - ghjk_dir_path: Option, - share_dir_path: PathBuf, + deno: denort::worker::DenoWorkerHandle, + config: config::Config, } - -/* mod files { - mod deno {} -} - -mod modules { - mod envs {} - mod ports {} - mod tasks {} -} */ diff --git a/src/ghjk/systems.rs b/src/ghjk/systems.rs index 0795e70..c0b34f1 100644 --- a/src/ghjk/systems.rs +++ b/src/ghjk/systems.rs @@ -33,6 +33,8 @@ pub trait SystemInstance { async fn load_lock_entry(&self, raw: serde_json::Value) -> Res; async fn gen_lock_entry(&self) -> Res; + + async fn commands(&self) -> Res>; } type BoxAny = Box; @@ -44,6 +46,7 @@ pub struct ErasedSystemInstance { load_config_fn: Box< dyn Fn(serde_json::Value, ConfigBlackboard, Option) -> BoxFuture<'static, Res<()>>, >, + commands_fn: Box BoxFuture<'static, Res>>>, } impl ErasedSystemInstance { @@ -71,15 +74,25 @@ impl ErasedSystemInstance { async move { instance.gen_lock_entry().await }.boxed() }) }, - load_config_fn: Box::new(move |config, bb, state| { + load_config_fn: { + let instance = instance.clone(); + Box::new(move |config, bb, state| { + let instance = instance.clone(); + async move { + let state: Option> = + state.map(|st| st.downcast().expect_or_log("downcast error")); + instance.load_config(config, bb, state.map(|bx| *bx)).await + } + .boxed() + }) + }, + commands_fn: { let instance = instance.clone(); - async move { - let state: Option> = - state.map(|st| st.downcast().expect_or_log("downcast error")); - instance.load_config(config, bb, state.map(|bx| *bx)).await - } - .boxed() - }), + Box::new(move || { + let instance = instance.clone(); + async move { instance.commands().await }.boxed() + }) + }, } } @@ -99,6 +112,10 @@ impl ErasedSystemInstance { pub async fn gen_lock_entry(&self) -> Res { (self.gen_lock_entry_fn)().await } + + pub async fn commands(&self) -> Res> { + (self.commands_fn)().await + } } pub type SystemId = CHeapStr; @@ -109,4 +126,24 @@ pub struct SystemConfig { pub config: serde_json::Value, } +pub type CliCommandAction = + Box BoxFuture<'static, Res<()>> + Send + Sync>; + +pub struct SystemCliCommand { + pub name: CHeapStr, + pub clap: clap::Command, + pub sub_commands: IndexMap, + pub action: Option, +} + +impl std::fmt::Debug for SystemCliCommand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SystemCliCommand") + .field("name", &self.name) + .field("sub_commands", &self.sub_commands) + .field("actions", &self.action.is_some()) + .finish() + } +} + pub type ConfigBlackboard = Arc>; diff --git a/src/ghjk/systems/deno.rs b/src/ghjk/systems/deno.rs index 15ef2e3..79b488d 100644 --- a/src/ghjk/systems/deno.rs +++ b/src/ghjk/systems/deno.rs @@ -3,20 +3,22 @@ use crate::interlude::*; -use super::{SystemId, SystemInstance, SystemManifest}; +use super::{SystemCliCommand, SystemId, SystemInstance, SystemManifest}; + +mod cli; #[derive(Clone)] pub struct DenoSystemsContext { callbacks: crate::ext::CallbacksHandle, - exit_code_channel: Arc>>>, - term_signal: Arc, + exit_code_channel: Arc>>>>, + term_signal: tokio::sync::watch::Sender, #[allow(unused)] hostcalls: crate::ext::Hostcalls, } impl DenoSystemsContext { #[allow(unused)] - pub async fn terminate(&mut self) -> Res { + pub async fn terminate(mut self) -> Res<()> { let channel = { let mut opt = self.exit_code_channel.lock().expect_or_log("mutex error"); opt.take() @@ -24,9 +26,8 @@ impl DenoSystemsContext { let Some(channel) = channel else { eyre::bail!("already terminated") }; - self.term_signal - .store(true, std::sync::atomic::Ordering::Relaxed); - Ok(channel.await.expect_or_log("channel error")) + self.term_signal.send(true).expect_or_log("channel error"); + channel.await.expect_or_log("channel error") } } @@ -34,8 +35,10 @@ impl DenoSystemsContext { pub async fn systems_from_deno( gcx: &GhjkCtx, source_uri: &url::Url, -) -> Res> { + ghjkdir_path: &Path, +) -> Res<(HashMap, DenoSystemsContext)> { let main_module = gcx + .config .repo_root .join("src/deno_systems/bindings.ts") .wrap_err("repo url error")?; @@ -45,32 +48,38 @@ pub async fn systems_from_deno( let bb = ext_conf.blackboard.clone(); bb.insert("args".into(), { #[derive(Serialize)] - struct GhjkCtxBean<'a> { - ghjkfile_path: Option<&'a Path>, - ghjk_dir_path: &'a Path, - share_dir_path: &'a Path, + struct ConfigRef<'a> { + pub ghjkfile: Option<&'a Path>, + pub ghjkdir: &'a Path, + pub data_dir: &'a Path, + pub deno_dir: &'a Path, + pub deno_lockfile: Option<&'a Path>, + pub repo_root: &'a url::Url, } #[derive(Serialize)] struct BindingArgs<'a> { uri: url::Url, - gcx: GhjkCtxBean<'a>, + config: ConfigRef<'a>, } - let GhjkCtx { - deno, + let crate::config::Config { repo_root, - ghjkfile_path, - ghjk_dir_path, - share_dir_path, - } = gcx; - _ = (deno, repo_root); + ghjkdir: _, + data_dir, + deno_lockfile, + ghjkfile, + deno_dir, + } = &gcx.config; serde_json::json!(BindingArgs { uri: source_uri.clone(), - gcx: GhjkCtxBean { - ghjkfile_path: ghjkfile_path.as_ref().map(|path| path.as_path()), - ghjk_dir_path, - share_dir_path, + config: ConfigRef { + ghjkfile: ghjkfile.as_ref().map(|path| path.as_path()), + ghjkdir: ghjkdir_path, + data_dir, + deno_lockfile: deno_lockfile.as_ref().map(|path| path.as_path()), + deno_dir, + repo_root }, }) }); @@ -88,7 +97,7 @@ pub async fn systems_from_deno( .boxed() }), ); - let cb_line = ext_conf.callbacks_handle(); + let cb_line = ext_conf.callbacks_handle(&gcx.deno); let mut worker = gcx .deno @@ -113,22 +122,42 @@ pub async fn systems_from_deno( ) .await?; worker.execute().await?; - let (exit_code_channel, term_signal, _) = worker.drive_till_exit().await?; + let (mut exit_code_channel, term_signal, _) = worker.drive_till_exit().await?; + + let manifests = tokio::select! { + res = &mut exit_code_channel => { + let exit_code = res + .expect_or_log("channel error") + .wrap_err("deno systems error building manifests")?; + eyre::bail!("premature exit of deno systems before manifests were sent: exit code = {exit_code}"); + }, + manifests = manifests_rx.recv() => { + manifests.expect_or_log("channel error") + } + }; + + let manifests: Vec = + serde_json::from_value(manifests).wrap_err("protocol error")?; + let dcx = gcx.deno.clone(); let join_exit_code_watcher = tokio::spawn(async { - let exit_code = exit_code_channel + let err = match exit_code_channel.await { + Ok(Ok(0)) => return Ok(()), + Ok(Ok(exit_code)) => { + ferr!("deno systems died with non-zero exit code: {exit_code}") + } + Ok(Err(err)) => err.wrap_err("error on event loop for deno systems"), + Err(_) => { + ferr!("deno systems unexpected shutdown") + } + }; + error!("deno systems error: {err:?}"); + dcx.terminate() .await - .expect_or_log("channel error") - .wrap_err("error on event loop for deno systems") - .unwrap_or_log(); - if exit_code != 0 { - // TODO: exit signals - error!(%exit_code, "deno systems died with non-zero exit code"); - } else { - info!(%exit_code, "deno systems exit") - } - exit_code + .expect_or_log("error terminating deno worker"); + Err(err) }); + let exit_code_channel = Arc::new(std::sync::Mutex::new(Some(join_exit_code_watcher))); let scx = DenoSystemsContext { @@ -137,11 +166,7 @@ pub async fn systems_from_deno( term_signal, exit_code_channel, }; - let scx = Arc::new(scx); - let manifests = manifests_rx.recv().await.expect_or_log("channel error"); - let manifests: Vec = - serde_json::from_value(manifests).wrap_err("protocol error")?; let manifests = manifests .into_iter() .map(|desc| { @@ -155,7 +180,7 @@ pub async fn systems_from_deno( }) .collect(); - Ok(manifests) + Ok((manifests, scx)) } #[derive(Debug, Deserialize)] @@ -169,12 +194,13 @@ struct ManifestDesc { pub struct DenoSystemManifest { desc: ManifestDesc, #[educe(Debug(ignore))] - scx: Arc, + scx: DenoSystemsContext, } impl DenoSystemManifest { + #[tracing::instrument] pub async fn ctor(&self) -> Res { - debug!(id = %self.desc.id, "initializing deno system"); + trace!("initializing deno system"); let desc = self .scx .callbacks @@ -183,7 +209,7 @@ impl DenoSystemManifest { let desc = serde_json::from_value(desc).wrap_err("protocol error")?; - debug!(id = %self.desc.id, "deno system initialized"); + trace!("deno system initialized"); Ok(DenoSystemInstance { desc, @@ -198,11 +224,12 @@ struct InstanceDesc { load_lock_entry_cb_key: CHeapStr, gen_lock_entry_cb_key: CHeapStr, load_config_cb_key: CHeapStr, + cli_commands_cb_key: CHeapStr, } pub struct DenoSystemInstance { desc: InstanceDesc, - scx: Arc, + scx: DenoSystemsContext, } #[async_trait::async_trait] @@ -253,4 +280,23 @@ impl SystemInstance for DenoSystemInstance { .await .wrap_err("callback error") } + + async fn commands(&self) -> Res> { + let cmds = self + .scx + .callbacks + .exec(self.desc.cli_commands_cb_key.clone(), serde_json::json!({})) + .await + .wrap_err("callback error")?; + + let cmds: Vec = + serde_json::from_value(cmds).wrap_err("protocol error")?; + + let cmds = cmds + .into_iter() + .map(|cmd| cmd.convert(self.scx.clone())) + .collect(); + + Ok(cmds) + } } diff --git a/src/ghjk/systems/deno/cli.rs b/src/ghjk/systems/deno/cli.rs new file mode 100644 index 0000000..8820714 --- /dev/null +++ b/src/ghjk/systems/deno/cli.rs @@ -0,0 +1,400 @@ +//! Types and conversions for runtime specified CLI commands +//! from deno systems + +use crate::{interlude::*, systems::CliCommandAction}; + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CliCommandDesc { + pub name: String, + + pub hide: Option, + + pub aliases: Option>, + pub visible_aliases: Option>, + + pub about: Option, + pub before_help: Option, + pub before_long_help: Option, + + pub args: Option>, + pub flags: Option>, + pub sub_commands: Option>, + + pub disable_help_subcommand: Option, + + pub action_cb_key: Option, +} + +impl CliCommandDesc { + #[tracing::instrument(skip(scx))] + pub fn convert(self, scx: super::DenoSystemsContext) -> crate::systems::SystemCliCommand { + let name = self.name; + let mut cmd = clap::Command::new(name.clone()).name(name.clone()); + + if let Some(val) = self.hide { + cmd = cmd.hide(val) + } + if let Some(val) = self.aliases { + cmd = cmd.aliases(val) + } + if let Some(val) = self.visible_aliases { + cmd = cmd.visible_aliases(val) + } + if let Some(val) = &self.about { + cmd = cmd.about(val) + } + if let Some(val) = self.before_help { + cmd = cmd.before_help(val) + } + if let Some(val) = self.before_long_help { + cmd = cmd.before_long_help(val) + } + if let Some(val) = self.disable_help_subcommand { + cmd = cmd.disable_help_subcommand(val) + } + let flag_ids = if let Some(val) = &self.flags { + let mut ids = ahash::HashSet::default(); + for (id, desc) in val { + ids.insert(id.clone()); + let arg = desc.convert(id); + cmd = cmd.arg(arg); + } + ids + } else { + default() + }; + + if let Some(val) = &self.args { + for (id, desc) in val { + if flag_ids.contains(id) { + panic!("flag and arg id clash at {id}"); + } + let arg = desc.convert(id); + cmd = cmd.arg(arg); + } + } + let sub_commands = if let Some(val) = self.sub_commands { + let mut subcommands = IndexMap::new(); + for desc in val { + let id = desc.name.clone(); + let scmd = desc.convert(scx.clone()); + subcommands.insert(id.into(), scmd); + } + subcommands + } else { + default() + }; + + let action: Option = if let Some(val) = self.action_cb_key { + let cb_key = CHeapStr::from(val); + let flags = self.flags.unwrap_or_default(); + let flags = Arc::new(flags); + let args = self.args.unwrap_or_default(); + let args = Arc::new(args); + Some(Box::new(move |matches| { + let scx = scx.clone(); + let cb_key = cb_key.clone(); + let flags = flags.clone(); + let args = args.clone(); + deno_cb_action(matches, scx.clone(), cb_key, flags, args).boxed() + })) + } else { + /* if sub_commands.is_empty() { + error!("a system command has no action or subcommands attached"); + } */ + None + }; + + crate::systems::SystemCliCommand { + name: name.into(), + clap: cmd, + sub_commands, + action, + } + } +} + +async fn deno_cb_action( + mut matches: clap::ArgMatches, + scx: super::DenoSystemsContext, + cb_key: CHeapStr, + flag_descs: Arc>, + args_descs: Arc>, +) -> Res<()> { + let mut flags = IndexMap::new(); + let mut args = IndexMap::new(); + + let match_ids = matches + .ids() + .map(|id| id.as_str().to_owned()) + .collect::>() + .into_iter(); + for id in match_ids { + let Some(desc) = flag_descs + .get(&id) + .map(|flag| &flag.arg) + .or_else(|| args_descs.get(&id)) + else { + unreachable!("unspecified arg id found: {id}"); + }; + let value = match desc.action.unwrap_or(ArgActionSerde::Set) { + ArgActionSerde::Set => matches + .try_remove_one::(id.as_str()) + .wrap_err_with(|| format!("error extracting match string for {id}"))? + .map(|val| serde_json::json!(val)), + ArgActionSerde::Append => matches + .try_remove_many::(id.as_str()) + .wrap_err_with(|| format!("error extracting match bool for {id}"))? + .map(|vals| vals.collect::>()) + .map(|val| serde_json::json!(val)), + ArgActionSerde::SetTrue | ArgActionSerde::SetFalse => matches + .try_remove_one::(id.as_str()) + .wrap_err_with(|| format!("error extracting match bool for {id}"))? + .map(|val| serde_json::json!(val)), + ArgActionSerde::Count => matches + .try_remove_one::(id.as_str()) + .wrap_err_with(|| format!("error extracting match count for {id}"))? + .map(|val| serde_json::json!(val)), + ArgActionSerde::Help + | ArgActionSerde::HelpShort + | ArgActionSerde::HelpLong + | ArgActionSerde::Version => unreachable!(), + }; + let Some(value) = value else { + continue; + }; + + let bucket = if flag_descs.contains_key(id.as_str()) { + &mut flags + } else { + &mut args + }; + + bucket.insert(id.as_str().to_owned(), value); + } + let response = scx + .callbacks + .exec( + cb_key.clone(), + serde_json::json!({ + "flags": flags, + "args": args + }), + ) + .await + .wrap_err("callback error")?; + debug!(?response, "system command action response"); + Ok(()) +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CliArgDesc { + pub required: Option, + pub global: Option, + pub hide: Option, + pub exclusive: Option, + pub trailing_var_arg: Option, + pub allow_hyphen_values: Option, + + pub action: Option, + + pub value_name: Option, + pub value_hint: Option, + + pub long: Option, + pub long_aliases: Option>, + pub visible_long_aliases: Option>, + + pub short: Option, + pub short_aliases: Option>, + pub visible_short_aliases: Option>, + + pub env: Option, + + pub help: Option, + pub long_help: Option, +} + +impl CliArgDesc { + pub fn convert(&self, id: &str) -> clap::Arg { + let mut arg = clap::Arg::new(id.to_owned()); + + if let Some(val) = self.required { + arg = arg.required(val) + } + if let Some(val) = self.global { + arg = arg.global(val) + } + if let Some(val) = self.hide { + arg = arg.hide(val) + } + if let Some(val) = self.exclusive { + arg = arg.exclusive(val) + } + if let Some(val) = self.trailing_var_arg { + arg = arg.num_args(..).trailing_var_arg(val) + } + if let Some(val) = self.allow_hyphen_values { + arg = arg.allow_hyphen_values(val) + } + + if let Some(val) = self.action { + arg = arg.action(clap::ArgAction::from(val)) + } + + if let Some(val) = &self.value_name { + arg = arg.value_name(val) + } + + if let Some(val) = self.value_hint { + arg = arg.value_hint(clap::ValueHint::from(val)) + } + + if let Some(val) = &self.long { + arg = arg.long(val) + } + if let Some(val) = &self.long_aliases { + arg = arg.aliases(val) + }; + if let Some(val) = &self.visible_long_aliases { + arg = arg.visible_aliases(val) + }; + + if let Some(val) = self.short { + arg = arg.short(val) + }; + if let Some(val) = &self.short_aliases { + arg = arg.short_aliases(val.clone()) + }; + if let Some(val) = &self.visible_short_aliases { + arg = arg.short_aliases(val.clone()) + }; + + if let Some(val) = &self.env { + arg = arg.env(val) + }; + + if let Some(val) = &self.help { + arg = arg.help(val) + }; + + if let Some(val) = &self.long_help { + arg = arg.long_help(val) + }; + + arg + } +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct CliFlagDesc { + #[serde(flatten)] + pub arg: CliArgDesc, + + pub long: Option, + pub long_aliases: Option>, + pub visible_long_aliases: Option>, + + pub short: Option, + pub short_aliases: Option>, + pub visible_short_aliases: Option>, +} + +impl CliFlagDesc { + pub fn convert(&self, id: &str) -> clap::Arg { + let mut arg = self.arg.convert(id); + + if let Some(val) = &self.long { + arg = arg.long(val) + } + if let Some(val) = &self.long_aliases { + arg = arg.aliases(val) + }; + if let Some(val) = &self.visible_long_aliases { + arg = arg.visible_aliases(val) + }; + + if let Some(val) = self.short { + arg = arg.short(val) + }; + if let Some(val) = &self.short_aliases { + arg = arg.short_aliases(val.clone()) + }; + if let Some(val) = &self.visible_short_aliases { + arg = arg.short_aliases(val.clone()) + }; + + arg + } +} + +#[derive(Deserialize, Debug, Clone, Copy)] +pub enum ValueHintSerde { + Unknown, + Other, + AnyPath, + FilePath, + DirPath, + ExecutablePath, + CommandName, + CommandString, + CommandWithArguments, + Username, + Hostname, + Url, + EmailAddress, +} + +impl From for clap::ValueHint { + fn from(val: ValueHintSerde) -> Self { + use ValueHintSerde::*; + match val { + Unknown => clap::ValueHint::Unknown, + Other => clap::ValueHint::Unknown, + AnyPath => clap::ValueHint::Unknown, + FilePath => clap::ValueHint::Unknown, + DirPath => clap::ValueHint::Unknown, + ExecutablePath => clap::ValueHint::Unknown, + CommandName => clap::ValueHint::Unknown, + CommandString => clap::ValueHint::Unknown, + CommandWithArguments => clap::ValueHint::Unknown, + Username => clap::ValueHint::Unknown, + Hostname => clap::ValueHint::Unknown, + Url => clap::ValueHint::Unknown, + EmailAddress => clap::ValueHint::Unknown, + } + } +} + +#[derive(Deserialize, Debug, Clone, Copy)] +pub enum ArgActionSerde { + Set, + Append, + SetTrue, + SetFalse, + Count, + Help, + HelpShort, + HelpLong, + Version, +} + +impl From for clap::ArgAction { + fn from(val: ArgActionSerde) -> Self { + use ArgActionSerde::*; + match val { + Set => clap::ArgAction::Set, + Append => clap::ArgAction::Append, + SetTrue => clap::ArgAction::SetTrue, + SetFalse => clap::ArgAction::SetFalse, + Count => clap::ArgAction::Count, + Help => clap::ArgAction::Help, + HelpShort => clap::ArgAction::HelpShort, + HelpLong => clap::ArgAction::HelpLong, + Version => clap::ArgAction::Version, + } + } +} diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index 30e1201..c582840 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -19,7 +19,7 @@ mod cheapstr { }; // lifted from github.com/bevyengine/bevy 's bevy_core/Name struct // MIT/APACHE2 licence - #[derive(Debug, Clone, Serialize, Deserialize)] + #[derive(Clone, Serialize, Deserialize)] #[serde(crate = "serde", from = "String", into = "String")] pub struct CHeapStr { hash: u64, @@ -128,6 +128,12 @@ mod cheapstr { self.string.fmt(f) } } + + impl std::fmt::Debug for CHeapStr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.string.fmt(f) + } + } } const SHA2_256: u64 = 0x12; @@ -144,10 +150,13 @@ pub fn hash_obj(obj: &T) -> String { } pub fn hash_str(string: &str) -> String { + hash_bytes(string.as_bytes()) +} + +pub fn hash_bytes(bytes: &[u8]) -> String { use sha2::Digest; let mut hash = sha2::Sha256::new(); - hash.write(string.as_bytes()) - .expect_or_log("error writing to hasher"); + hash.write(bytes).expect_or_log("error writing to hasher"); let hash = hash.finalize(); let hash = @@ -155,6 +164,35 @@ pub fn hash_str(string: &str) -> String { encode_base32_multibase(hash.digest()) } +pub async fn hash_reader(reader: T) -> Res { + use sha2::Digest; + use tokio::io::*; + let mut hash = sha2::Sha256::new(); + let mut buf = vec![0u8; 65536]; + + let reader = tokio::io::BufReader::new(reader); + + let mut reader = std::pin::pin!(reader); + + loop { + // Read a chunk of data + let bytes_read = reader.read(&mut buf).await?; + + // Break the loop if we reached EOF + if bytes_read == 0 { + break; + } + hash.write(&buf[..bytes_read]) + .expect_or_log("error writing to hasher"); + } + let hash = hash.finalize(); + + let hash = + multihash::Multihash::<32>::wrap(SHA2_256, &hash[..]).expect_or_log("error multihashing"); + let hash = encode_base32_multibase(hash.digest()); + Ok(hash) +} + pub fn encode_base32_multibase>(source: T) -> String { format!( "b{}", @@ -206,18 +244,18 @@ pub async fn find_entry_recursive(from: &Path, name: &str) -> Res { + Ok(true) => { return Ok(Some(location)); } - Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + Err(err) if err.kind() != std::io::ErrorKind::NotFound => { + return Err(err).wrap_err("error on file stat"); + } + _ => { let Some(next_cur) = cur.parent() else { return Ok(None); }; cur = next_cur; } - Err(err) => { - return Err(err).wrap_err("error on file stat"); - } } } } diff --git a/src/play/Cargo.toml b/src/play/Cargo.toml new file mode 100644 index 0000000..f12e33a --- /dev/null +++ b/src/play/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "play" +version.workspace = true +edition.workspace = true + +[[bin]] +name = "play" +path = "main.rs" + +[dependencies] + +tracing-unwrap.workspace = true + +color-eyre.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +once_cell.workspace = true +clap = { workspace = true, features = ["derive", "env"] } +tokio = { workspace = true, features = ["full", "parking_lot"] } +data-encoding = "2.6.0" +sha2 = "0.10.8" +futures-concurrency = "7.6.2" diff --git a/src/play/main.rs b/src/play/main.rs new file mode 100644 index 0000000..6994e43 --- /dev/null +++ b/src/play/main.rs @@ -0,0 +1,20 @@ +#![allow(unused)] + +use futures_concurrency::prelude::*; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + +type BoxErr = Box; +type Res = Result; + +fn main() { + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + // playground + }); +} diff --git a/src/xtask/main.rs b/src/xtask/main.rs index 5baa34f..a1841ab 100644 --- a/src/xtask/main.rs +++ b/src/xtask/main.rs @@ -9,6 +9,8 @@ mod interlude { pub use tracing::{debug, error, info, trace, warn}; pub use tracing_unwrap::*; } +use clap::builder::styling::AnsiColor; + use crate::interlude::*; mod utils; @@ -48,13 +50,32 @@ fn main() -> Res<()> { Arc::new(std::vec::Vec::new), vec![], ) - } + } /* Commands::Run { argv } => denort::run_sync( + denort::deno::deno_runtime::deno_core::resolve_url_or_path("ghjk.ts", &cwd).unwrap(), + Some("deno.jsonc".into()), + denort::deno::args::PermissionFlags { + allow_all: true, + ..Default::default() + }, + Arc::new(std::vec::Vec::new), + ), */ } + Ok(()) } +const CLAP_STYLE: clap::builder::Styles = clap::builder::Styles::styled() + .header(AnsiColor::Yellow.on_default()) + .usage(AnsiColor::Green.on_default()) + .literal(AnsiColor::Green.on_default()) + .placeholder(AnsiColor::Green.on_default()); + #[derive(Debug, clap::Parser)] -#[clap(version, about)] +#[clap( + version, + about, + styles = CLAP_STYLE +)] struct Args { #[clap(subcommand)] command: Commands, diff --git a/tests/envHooks.ts b/tests/envHooks.ts index 963ea07..936984c 100644 --- a/tests/envHooks.ts +++ b/tests/envHooks.ts @@ -60,9 +60,7 @@ const cases: CustomE2eTestCase[] = [ // -s: read from stdin // -l: login mode // -i: make it interactive - ePoint: Deno.env.get("GHJK_TEST_E2E_TYPE") == "local" - ? `bash --rcfile $BASH_ENV -si` // we don't want to use the system rcfile - : `bash -sil`, + ePoint: `bash --rcfile $BASH_ENV -si`, // we don't want to use the system rcfile stdin: posixInteractiveScript, }, { diff --git a/tests/envs.ts b/tests/envs.ts index 05106a7..d684a40 100644 --- a/tests/envs.ts +++ b/tests/envs.ts @@ -47,6 +47,7 @@ const envVarTestEnvs: EnvDefArgs[] = [ ]; const envVarTestsPosix = ` set -ex +env # by default, we should be in main [ "$SONG" = "ditto" ] || exit 1010 [ "$GHJK_ENV" = "main" ] || exit 1011 @@ -57,6 +58,7 @@ ghjk_deactivate [ "$GHJK_ENV" = "main" ] && exit 1022 ghjk envs cook sss +echo $? . .ghjk/envs/sss/activate.sh # by default, envs should be based on main # so they should inherit it's env vars diff --git a/tests/ports.ts b/tests/ports.ts index 2d8b0a9..e4fe16f 100644 --- a/tests/ports.ts +++ b/tests/ports.ts @@ -150,14 +150,7 @@ const cases: CustomE2eTestCase[] = [ ports.meta_cli_ghrel({ full: true }), ports.wasmedge(), ], - ePoint: Deno.env.get("GHJK_TEST_E2E_TYPE") != "local" - // meta cli runs into segmentation error in the alpine - // image - // https://github.com/metatypedev/metatype/issues/584 - // just check that the shell's able to find the - // executrable - ? `which meta && wasmedge --version` - : `meta --version && wasmedge --version`, + ePoint: `which meta && wasmedge --version`, ignore: testTargetPlatform == "linux/aarch64", }, // 80 meg diff --git a/tests/reloadHooks.ts b/tests/reloadHooks.ts index fda6298..c9be1ba 100644 --- a/tests/reloadHooks.ts +++ b/tests/reloadHooks.ts @@ -208,9 +208,8 @@ type CustomE2eTestCase = Omit & { // -s: read from stdin // -l: login mode // -i: interactive mode -const bashInteractiveEpoint = Deno.env.get("GHJK_TEST_E2E_TYPE") == "local" - ? `bash --rcfile $BASH_ENV -si` // we don't want to use the system rcfile - : `bash -sil`; +// we don't want to use the system rcfile +const bashInteractiveEpoint = `bash --rcfile $BASH_ENV -si`; const cases: CustomE2eTestCase[] = [ { diff --git a/tests/test-alpine.Dockerfile b/tests/test-alpine.Dockerfile deleted file mode 100644 index e965518..0000000 --- a/tests/test-alpine.Dockerfile +++ /dev/null @@ -1,80 +0,0 @@ -ARG DENO_V=1.42.1 - -FROM docker.io/denoland/deno:alpine-${DENO_V} - -ARG BASH_V=5.2.21-r0 -ARG FISH_V=3.6.3-r0 -ARG ZSH_V=5.9-r2 -ARG GIT_V=2.43.0-r0 -ARG CURL_V=8.5.0-r0 -ARG XZ_V=5.4.5-r0 -ARG GTAR_V=1.35-r2 -ARG UNZIP_V=6.0-r14 -ARG ZSTD_V=1.5.5-r8 -ARG GCOMPAT_V=1.1.0-r4 -ARG BUILD_BASE_V=0.5-r3 - -RUN set -eux; \ - apk update; \ - apk add \ - # ambient deps \ - zstd=$ZSTD_V \ - tar=$GTAR_V \ - # test deps \ - bash=$BASH_V \ - fish=$FISH_V \ - zsh=$ZSH_V \ - # asdf deps \ - git=$GIT_V \ - curl=$CURL_V \ - xz=$XZ_V \ - unzip=$UNZIP_V \ - build-base=$BUILD_BASE_V \ - # gcompat=$GCOMPAT_V \ - ca-certificates \ - ; - -WORKDIR /ghjk - -COPY deno.lock deno.jsonc ./ -COPY deps/* ./deps/ -RUN deno task cache - -COPY . ./ - -RUN ln -s ./main.ts /bin/ghjk - -WORKDIR /app - -ENV GHJK_LOG=info -ENV GHJK_INSTALL_EXE_DIR=/usr/bin -ENV GHJK_INSTALL_HOOK_SHELLS=fish,bash,zsh -# share the module cache of the image -ENV GHJK_INSTALL_DENO_DIR=$DENO_DIR -RUN deno run -A /ghjk/install.ts - -ARG GITHUB_TOKEN -ENV GITHUB_TOKEN=$GITHUB_TOKEN - -# avoid variable expansion in the contents of the -# here-document by quoting the tag -COPY <<"EOT" /app/ghjk.ts -#{{CMD_ADD_CONFIG}} -EOT - -RUN <; - ePoints: { cmd: string | string[]; stdin?: string }[]; - timeout_ms?: number; - ignore?: boolean; - only?: boolean; -}; export const testTargetPlatform = Deno.env.get("DOCKER_PLATFORM") ?? (Deno.build.os + "/" + Deno.build.arch); @@ -28,78 +16,15 @@ if ( throw new Error(`unsupported test platform: ${testTargetPlatform}`); } -const dockerPlatform = `--platform=${ - testTargetPlatform - .replace("x86_64", "amd64") - .replace("aarch64", "arm64") -}`; - -const dockerCmd = (Deno.env.get("DOCKER_CMD") ?? "docker").split(/\s/); - -const dFileTemplate = await importRaw(import.meta.resolve("./test.Dockerfile")); -const templateStrings = { - addConfig: `#{{CMD_ADD_CONFIG}}`, +export type E2eTestCase = { + name: string; + tsGhjkfileStr: string; + envVars?: Record; + ePoints: { cmd: string | string[]; stdin?: string }[]; + timeout_ms?: number; + ignore?: boolean; + only?: boolean; }; -const noRmi = Deno.env.get("DOCKER_NO_RMI"); - -export async function dockerE2eTest(testCase: E2eTestCase) { - const { name, envVars: testEnvs, ePoints, tsGhjkfileStr } = testCase; - const tag = `ghjk_e2e_${name}`.toLowerCase(); - const env = { - ...testEnvs, - }; - if (Deno.env.get("GITHUB_TOKEN")) { - env.GITHUB_TOKEN = Deno.env.get("GITHUB_TOKEN")!; - } - const devGhjkPath = import.meta.resolve("../"); - - const configFile = tsGhjkfileStr - // replace all file urls that point to the ghjk - // repo in the host fs to point to the copy of the - // repo in the image - .replaceAll(devGhjkPath, "file://$ghjk/") - .replaceAll("$ghjk", "/ghjk"); - - const dFile = dbg(dFileTemplate - .replace( - templateStrings.addConfig, - configFile - // escape all dollars - .replaceAll("$", "$$$$"), - )); - - await $ - .raw`${dockerCmd} buildx build ${dockerPlatform} ${ - Object.entries(env).map(([key, val]) => ["--build-arg", `${key}=${val}`]) - } --tag '${tag}' --network=host --output type=docker -f- .` - .env(env) - .stdinText(dFile); - - for (const ePoint of ePoints) { - let cmd = $.raw`${dockerCmd} run ${dockerPlatform} --rm ${[ - /* we want to enable interactivity when piping in */ - ePoint.stdin ? "-i " : "", - ...Object.entries(env).map(([key, val]) => ["-e", `${key}=${val}`]) - .flat(), - tag, - ]} ${ePoint.cmd}` - .env(env); - if (ePoint.stdin) { - cmd = cmd.stdinText(ePoint.stdin!); - } - try { - await cmd; - } catch (err) { - logger(import.meta).error(err); - throw err; - } - } - if (!noRmi) { - await $ - .raw`${dockerCmd} rmi '${tag}'` - .env(env); - } -} export async function localE2eTest(testCase: E2eTestCase) { const { envVars: testEnvs, ePoints, tsGhjkfileStr } = testCase; @@ -108,7 +33,7 @@ export async function localE2eTest(testCase: E2eTestCase) { prefix: "ghjk_le2e_", }), ); - const ghjkShareDir = await tmpDir.join("ghjk").ensureDir(); + const ghjkDataDir = await tmpDir.join("ghjk").ensureDir(); await tmpDir.join("ghjk.ts").writeText( tsGhjkfileStr.replaceAll( @@ -116,41 +41,51 @@ export async function localE2eTest(testCase: E2eTestCase) { std_url.dirname(import.meta.resolve("../mod.ts")).href, ), ); - const env: Record = { + + const ghjkExePath = $.path(import.meta.resolve("../target/debug/ghjk")); + const ghjkShimPath = await ghjkDataDir + .join("ghjk") + .writeText( + `#!/bin/sh +exec ${ghjkExePath.resolve().toString()} "$@"`, + { mode: 0o700 }, + ); + + const env: Record = { GHJK_AUTO_HOOK: "true", - BASH_ENV: `${ghjkShareDir.toString()}/env.bash`, - ZDOTDIR: ghjkShareDir.toString(), - GHJK_SHARE_DIR: ghjkShareDir.toString(), - PATH: `${ghjkShareDir.toString()}:${Deno.env.get("PATH")}`, + BASH_ENV: `${ghjkDataDir.toString()}/env.bash`, + ZDOTDIR: ghjkDataDir.toString(), + GHJK_DATA_DIR: ghjkDataDir.toString(), + PATH: `${ghjkShimPath.parentOrThrow().toString()}:${Deno.env.get("PATH")}`, HOME: tmpDir.toString(), + GHJK_REPO_ROOT: import.meta.resolve("../"), + // share the system's deno cache + GHJK_DENO_DIR: Deno.env.get("DENO_DIR") ?? + $.path(Deno.env.get("HOME")!).join(".cache", "deno").toString(), + RUST_LOG: Deno.env.get("RUST_LOG"), + GHJK_LOG: Deno.env.get("GHJK_LOG"), ...testEnvs, }; // install ghjk await install({ ...defaultInstallArgs, - skipExecInstall: false, - ghjkExecInstallDir: ghjkShareDir.toString(), - // share the system's deno cache - ghjkDenoCacheDir: Deno.env.get("DENO_DIR") ?? - $.path(Deno.env.get("HOME")!).join(".cache", "deno").toString(), - ghjkShareDir: ghjkShareDir.toString(), - ghjkExecDenoExec: "deno", + ghjkDataDir: ghjkDataDir.toString(), // don't modify system shell configs shellsToHook: [], }); - await $`${ghjkShareDir.join("ghjk").toString()} print config` + /* await $`ghjk print config` .cwd(tmpDir.toString()) .clearEnv() - .env(env); - await $`${ghjkShareDir.join("ghjk").toString()} envs cook` + .env(env); */ + await $`ghjk envs cook` .cwd(tmpDir.toString()) .clearEnv() .env(env); /* // print the contents of the ghjk dir for debugging purposes const ghjkDirLen = ghjkDir.toString().length; - dbg((await Array.fromAsync(ghjkShareDir.walk())).map((entry) => [ + dbg((await Array.fromAsync(ghjkDataDir.walk())).map((entry) => [ entry.isDirectory ? "dir " : entry.isSymlink ? "ln " : "file", entry.path.toString().slice(ghjkDirLen), ])); @@ -159,7 +94,7 @@ export async function localE2eTest(testCase: E2eTestCase) { const confHome = await tmpDir.join(".config").ensureDir(); const fishConfDir = await confHome.join("fish").ensureDir(); await fishConfDir.join("config.fish").symlinkTo( - ghjkShareDir.join("env.fish").toString(), + ghjkDataDir.join("env.fish").toString(), ); env["XDG_CONFIG_HOME"] = confHome.toString(); } @@ -234,17 +169,11 @@ export function harness( cases: E2eTestCase[], ) { const e2eType = Deno.env.get("GHJK_TEST_E2E_TYPE"); - let runners = [[dockerE2eTest, "e2eDocker" as string] as const]; - if (e2eType == "both") { - runners.push([localE2eTest, "e2eLocal"]); - } else if (e2eType == "local") { - runners = [[localE2eTest, "e2eLocal"]]; - } else if ( - e2eType && e2eType != "docker" - ) { - throw new Error( - `unexpected GHJK_TEST_E2E_TYPE: ${e2eType}`, - ); + const runners = [ + [localE2eTest, "e2eLocal"] as const, + ]; + if (e2eType && e2eType != "local") { + throw new Error("docker test runner has been removed"); } for (const [runner, group] of runners) { for (const testCase of cases) { diff --git a/utils/mod.ts b/utils/mod.ts index 2e77256..ab0d689 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -43,7 +43,7 @@ export const jsonSchema: zod.ZodType = zod.lazy(() => ); export function dbg(val: T, ...more: unknown[]) { - logger().debug(() => val, ...more, "DBG"); + logger().debug("DBG", val, ...more); return val; } @@ -306,29 +306,6 @@ export async function findEntryRecursive(path: string | Path, name: string) { } } -export function homeDir() { - switch (Deno.build.os) { - case "linux": - case "darwin": - return Deno.env.get("HOME") ?? null; - case "windows": - return Deno.env.get("USERPROFILE") ?? null; - default: - return null; - } -} - -export function dirs() { - const home = homeDir(); - if (!home) { - throw new Error("cannot find home dir"); - } - return { - homeDir: home, - shareDir: $.path(home).resolve(".local", "share"), - }; -} - export const AVAIL_CONCURRENCY = Number.parseInt( Deno.env.get("DENO_JOBS") ?? "1", ); From e562883ef241f951a472160c3e4ac25effb2a84d Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 09:04:25 +0300 Subject: [PATCH 10/15] feat: track dynamic imports #74 --- .ghjk/lock.json | 405 +++++++++++++++++++---------------- Cargo.lock | 4 +- ghjk.ts | 11 +- modules/ports/sync.ts | 11 +- ports/asdf.ts | 2 + ports/cmake.ts | 46 ---- ports/dummy.ts | 2 +- ports/mod.ts | 1 - src/deno_systems/bindings.ts | 22 +- src/denort/lib.rs | 1 + src/denort/macros.rs | 16 ++ src/denort/worker.rs | 92 ++++---- src/ghjk/Cargo.toml | 6 +- src/ghjk/cli.rs | 5 +- src/ghjk/ext.rs | 39 +++- src/ghjk/ext/callbacks.rs | 157 ++++++++++---- src/ghjk/host.rs | 6 +- src/ghjk/host/hashfile.rs | 39 ++-- src/ghjk/js/00_runtime.js | 1 + src/ghjk/js/runtime.d.ts | 1 + src/ghjk/log.rs | 2 +- src/ghjk/systems/deno.rs | 60 ++++-- tests/envHooks.ts | 6 +- tests/envs.ts | 18 +- tests/hashfile.ts | 75 +++++++ tests/ports.ts | 39 ++-- tests/portsOutdated.ts | 22 +- tests/reloadHooks.ts | 32 +-- tests/tasks.ts | 22 +- tests/todo.ts | 1 - tests/utils.ts | 22 +- utils/logger.ts | 1 + utils/mod.ts | 5 +- 33 files changed, 714 insertions(+), 458 deletions(-) delete mode 100644 ports/cmake.ts create mode 100644 src/denort/macros.rs create mode 100644 tests/hashfile.ts diff --git a/.ghjk/lock.json b/.ghjk/lock.json index 7411cce..32181f4 100644 --- a/.ghjk/lock.json +++ b/.ghjk/lock.json @@ -4,14 +4,121 @@ "ports": { "version": "0", "configResolutions": { - "bciqjlw6cxddajjmznoemlmnu7mgbbm7a3hfmnd2x5oivwajmiqui5ey": { - "version": "v0.2.69", + "bciqeosxosr6ur7pu7gny33gy7dqubmxbcs4775xazb4zvaxavkd5rha": { + "version": "0.1.13", + "buildDepConfigs": { + "cargo_binstall_ghrel": { + "version": "v1.10.18", + "buildDepConfigs": {}, + "portRef": "cargo_binstall_ghrel@0.1.0", + "specifiedVersion": false + }, + "rust_rustup": { + "version": "1.82.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.1", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "default", + "components": [ + "rust-src" + ], + "specifiedVersion": true + } + }, + "portRef": "cargobi_cratesio@0.1.0", + "crateName": "tokio-console", + "specifiedVersion": false + }, + "bciqeal5okt5zj763vhgsmf3afr5thrkqaitv6pb3wwegcwyb74gdyjq": { + "version": "v1.10.18", "buildDepConfigs": {}, - "portRef": "act_ghrel@0.1.0", + "portRef": "cargo_binstall_ghrel@0.1.0", "specifiedVersion": false }, - "bciqao2s3r3r33ruox4qknfrxqrmemuccxn64dze2ylojrzp2bwvt4ji": { - "version": "4.0.1", + "bciqar6zz2xgxmu5i2jp5nuj4wsogcl7pxsqs3w55mibcsbks5iimsyy": { + "version": "1.82.0", + "buildDepConfigs": { + "rustup_rustlang": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.1", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rust_rustup@0.1.0", + "profile": "default", + "components": [ + "rust-src" + ], + "specifiedVersion": true + }, + "bciqay4m4kmzfduj5t2clgejxgpe5zwper6lyyaxt7rhbjalaqd32nhq": { + "version": "2.47.1", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + }, + "bciqewpyjyfnnk4rbd6bbu5who2w6ve7dyt3inal72zg23cs4qnln32q": { + "version": "1.27.1", + "buildDepConfigs": { + "git_aa": { + "version": "2.47.1", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "rustup_rustlang@0.1.0", + "specifiedVersion": false + }, + "bciqkv7foyoio4wpti4yf2qrw5nphkgk2din6ba7mjv2w7hmgrv725ja": { + "version": "v2.4.0", + "buildDepConfigs": { + "tar_aa": { + "version": "1.35", + "buildDepConfigs": {}, + "portRef": "tar_aa@0.1.0", + "specifiedVersion": false + } + }, + "portRef": "mold_ghrel@0.1.0", + "replaceLd": true, + "specifiedVersion": true + }, + "bciqj4p5hoqweghbuvz52rupja7sqze34z63dd62nz632c5zxikv6ezy": { + "version": "1.35", + "buildDepConfigs": {}, + "portRef": "tar_aa@0.1.0", + "specifiedVersion": false + }, + "bciqkpfuyqchouu5o3whigod3f5coscq2jdlwde6fztypy3x6fg6xb5q": { + "version": "v29.2", + "buildDepConfigs": {}, + "portRef": "protoc_ghrel@0.1.0", + "specifiedVersion": false + }, + "bciqe6tpdv6hffdbc7hql52w3ivpdls47lgpuhsa3hzsryrwx7ty5dgy": { + "version": "3.31.2", "buildDepConfigs": { "cpy_bs_ghrel": { "version": "3.13.1", @@ -34,10 +141,10 @@ } }, "portRef": "pipi_pypi@0.1.0", - "packageName": "pre-commit", + "packageName": "cmake", "specifiedVersion": false }, - "bciqh4dfyevkzzvmnhuz7lcfqttkg5neg4ewhoxzofyuicavgk6pb7ia": { + "bciqicl4snbxiu6ikns3zjrriwo3qpo4dv3ooxjkwnr35utnqshubdcq": { "version": "3.13.1", "buildDepConfigs": { "tar_aa": { @@ -56,20 +163,20 @@ "portRef": "cpy_bs_ghrel@0.1.0", "specifiedVersion": true }, - "bciqj4p5hoqweghbuvz52rupja7sqze34z63dd62nz632c5zxikv6ezy": { - "version": "1.35", - "buildDepConfigs": {}, - "portRef": "tar_aa@0.1.0", - "specifiedVersion": false - }, "bciqe6fwheayositrdk7rkr2ngdr4wizldakex23tgivss7w6z7g3q3y": { "version": "v1.5.6", "buildDepConfigs": {}, "portRef": "zstd_aa@0.1.0", "specifiedVersion": false }, - "bciqoawx3omfmmhaw25mgrujoxl5wkdwfzbmidfqah2zst7cildtcpeq": { - "version": "3.9.0.0", + "bciqjlw6cxddajjmznoemlmnu7mgbbm7a3hfmnd2x5oivwajmiqui5ey": { + "version": "v0.2.71", + "buildDepConfigs": {}, + "portRef": "act_ghrel@0.1.0", + "specifiedVersion": false + }, + "bciqao2s3r3r33ruox4qknfrxqrmemuccxn64dze2ylojrzp2bwvt4ji": { + "version": "4.0.1", "buildDepConfigs": { "cpy_bs_ghrel": { "version": "3.13.1", @@ -92,29 +199,11 @@ } }, "portRef": "pipi_pypi@0.1.0", - "packageName": "vale", - "specifiedVersion": false - }, - "bciqfvlwwndlfuqibybkgee3fgt7cst5ltpztmm3by6hib5veial5spy": { - "version": "v1.44.2", - "buildDepConfigs": {}, - "portRef": "deno_ghrel@0.1.0", - "specifiedVersion": true - }, - "bciqg5gzspxjw7zvrubuyyqskh2244x6mkoxfwugnrx3clyadlegvidi": { - "version": "v2.0.6", - "buildDepConfigs": {}, - "portRef": "deno_ghrel@0.1.0", - "specifiedVersion": true - }, - "bciqkpfuyqchouu5o3whigod3f5coscq2jdlwde6fztypy3x6fg6xb5q": { - "version": "v28.3", - "buildDepConfigs": {}, - "portRef": "protoc_ghrel@0.1.0", + "packageName": "pre-commit", "specifiedVersion": false }, - "bciqe6tpdv6hffdbc7hql52w3ivpdls47lgpuhsa3hzsryrwx7ty5dgy": { - "version": "3.31.0.1", + "bciqoawx3omfmmhaw25mgrujoxl5wkdwfzbmidfqah2zst7cildtcpeq": { + "version": "3.9.1.0", "buildDepConfigs": { "cpy_bs_ghrel": { "version": "3.13.1", @@ -137,184 +226,75 @@ } }, "portRef": "pipi_pypi@0.1.0", - "packageName": "cmake", + "packageName": "vale", "specifiedVersion": false }, - "bciqado5fpguhzyhrxmxqdgutm4i5zgpjhezjoqs5tqrlqqdj5453vhi": { - "version": "1.82.0", - "buildDepConfigs": { - "rustup_rustlang": { - "version": "1.27.1", - "buildDepConfigs": { - "git_aa": { - "version": "2.47.0", - "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rustup_rustlang@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rust_rustup@0.1.0", - "profile": "default", - "components": [ - "rustfmt", - "clippy" - ], + "bciqe7g5m4v5jkg3ubqhogjjntsduyrwxcirqcp6tc3jmjr5af7ojq6a": { + "version": "v2.1.2", + "buildDepConfigs": {}, + "portRef": "deno_ghrel@0.1.0", "specifiedVersion": true }, - "bciqay4m4kmzfduj5t2clgejxgpe5zwper6lyyaxt7rhbjalaqd32nhq": { - "version": "2.47.0", + "bciqmpujkkyxmzdz7sxpvi2pmajzfmg6gofplyqn43av2styxu2ng7sy": { + "version": "8.9.1", "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", + "portRef": "curl_aa@0.1.0", "specifiedVersion": false }, - "bciqewpyjyfnnk4rbd6bbu5who2w6ve7dyt3inal72zg23cs4qnln32q": { - "version": "1.27.1", + "bciqldq3d5ozrnh64liohwl5epkckja37mokbbjiddhsco6yh2n2ppda": { + "version": "1.7.1", "buildDepConfigs": { - "git_aa": { - "version": "2.47.0", + "curl_aa": { + "version": "8.9.1", "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", + "portRef": "curl_aa@0.1.0", "specifiedVersion": false - } - }, - "portRef": "rustup_rustlang@0.1.0", - "specifiedVersion": false - }, - "bciqkv7foyoio4wpti4yf2qrw5nphkgk2din6ba7mjv2w7hmgrv725ja": { - "version": "v2.4.0", - "buildDepConfigs": { - "tar_aa": { - "version": "1.35", + }, + "git_aa": { + "version": "2.47.1", "buildDepConfigs": {}, - "portRef": "tar_aa@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "mold_ghrel@0.1.0", - "replaceLd": true, - "specifiedVersion": true - }, - "bciqftx76ntu7mbgpvp3btywb7ivtdpbaqi4f43ljbilgdgc6ziljlhq": { - "version": "1.82.0", - "buildDepConfigs": { - "rustup_rustlang": { - "version": "1.27.1", - "buildDepConfigs": { - "git_aa": { - "version": "2.47.0", - "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rustup_rustlang@0.1.0", + "portRef": "git_aa@0.1.0", "specifiedVersion": false - } - }, - "portRef": "rust_rustup@0.1.0", - "profile": "default", - "components": [ - "rustfmt", - "clippy", - "rust-src" - ], - "specifiedVersion": true - }, - "bciqar6zz2xgxmu5i2jp5nuj4wsogcl7pxsqs3w55mibcsbks5iimsyy": { - "version": "1.82.0", - "buildDepConfigs": { - "rustup_rustlang": { - "version": "1.27.1", + }, + "asdf_plugin_git": { + "version": "addae51180", "buildDepConfigs": { "git_aa": { - "version": "2.47.0", + "version": "2.47.1", "buildDepConfigs": {}, "portRef": "git_aa@0.1.0", "specifiedVersion": false } }, - "portRef": "rustup_rustlang@0.1.0", + "portRef": "asdf_plugin_git@0.1.0", + "pluginRepo": "https://github.com/lsanwick/asdf-jq", "specifiedVersion": false } }, - "portRef": "rust_rustup@0.1.0", - "profile": "default", - "components": [ - "rust-src" - ], - "specifiedVersion": true - }, - "bciqeosxosr6ur7pu7gny33gy7dqubmxbcs4775xazb4zvaxavkd5rha": { - "version": "0.1.13", - "buildDepConfigs": { - "cargo_binstall_ghrel": { - "version": "v1.10.17", - "buildDepConfigs": {}, - "portRef": "cargo_binstall_ghrel@0.1.0", - "specifiedVersion": false - }, - "rust_rustup": { - "version": "1.83.0", - "buildDepConfigs": { - "rustup_rustlang": { - "version": "1.27.1", - "buildDepConfigs": { - "git_aa": { - "version": "2.47.0", - "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rustup_rustlang@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rust_rustup@0.1.0", - "profile": "minimal", - "specifiedVersion": false + "resolutionDepConfigs": { + "asdf_plugin_git": { + "pluginRepo": "https://github.com/lsanwick/asdf-jq", + "portRef": "asdf_plugin_git@0.1.0" } }, - "portRef": "cargobi_cratesio@0.1.0", - "crateName": "tokio-console", + "portRef": "asdf@0.1.0", + "pluginRepo": "https://github.com/lsanwick/asdf-jq", + "installType": "version", "specifiedVersion": false }, - "bciqeal5okt5zj763vhgsmf3afr5thrkqaitv6pb3wwegcwyb74gdyjq": { - "version": "v1.10.17", - "buildDepConfigs": {}, - "portRef": "cargo_binstall_ghrel@0.1.0", - "specifiedVersion": false - }, - "bciqeub366wrduva4y3rxegdjkhlebwsud56e5orgcpbkdrbhuxmvuxa": { - "version": "1.83.0", + "bciqjatixpjgnlwlrdxmz2r5g2werxjkkvs4wsw4c57fbipdza4qexua": { + "version": "addae51180", "buildDepConfigs": { - "rustup_rustlang": { - "version": "1.27.1", - "buildDepConfigs": { - "git_aa": { - "version": "2.47.0", - "buildDepConfigs": {}, - "portRef": "git_aa@0.1.0", - "specifiedVersion": false - } - }, - "portRef": "rustup_rustlang@0.1.0", + "git_aa": { + "version": "2.47.1", + "buildDepConfigs": {}, + "portRef": "git_aa@0.1.0", "specifiedVersion": false } }, - "portRef": "rust_rustup@0.1.0", - "profile": "minimal", + "portRef": "asdf_plugin_git@0.1.0", + "pluginRepo": "https://github.com/lsanwick/asdf-jq", "specifiedVersion": false - }, - "bciqe7g5m4v5jkg3ubqhogjjntsduyrwxcirqcp6tc3jmjr5af7ojq6a": { - "version": "v2.1.2", - "buildDepConfigs": {}, - "portRef": "deno_ghrel@0.1.0", - "specifiedVersion": true } } }, @@ -333,6 +313,7 @@ "sets": { "ghjkEnvProvInstSet___main": { "installs": [ + "bciqjucge6yrzcawqzcljvrpmtwrocecsww6pcjwipzn5j2hfwjof7za", "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", @@ -345,6 +326,7 @@ "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", "bciqgkc6fegmxehj4whmusfuurxyp4ayeysn6qa2t6q64baac5is7uui", + "bciqjucge6yrzcawqzcljvrpmtwrocecsww6pcjwipzn5j2hfwjof7za", "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", @@ -359,6 +341,7 @@ "bciqikjfnbntvagpghawbzlfp2es6lnqzhba3qx5de7tdrmvhuzhsjqa", "bciqfrfun7z7soj7yxzziyvmt2jnebqvneeoozk5vynmg5pa6wqynhvi", "bciqgkc6fegmxehj4whmusfuurxyp4ayeysn6qa2t6q64baac5is7uui", + "bciqjucge6yrzcawqzcljvrpmtwrocecsww6pcjwipzn5j2hfwjof7za", "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi", "bciqe4zlekl4uqqbhxunac7br24mrf6cdpfrfblahqa4vrgaqjujcl4i", "bciqpu4klxr3hl6ujhmflrlfd3dxp47ijq26mnathb26ojzwkeggy5ii", @@ -447,7 +430,7 @@ } ] }, - "bciqnerbswitlqt27ado74puxt3faxea6jaxe4wvytnzwjpupig25kky": { + "bciqgcwltl3sbuyrqlhxz2spihe2asdzrgt3axosw3mre7ived23syhy": { "provides": [ { "ty": "posix.envVar", @@ -457,7 +440,7 @@ { "ty": "posix.envVar", "key": "RUSTY_V8_MIRROR", - "val": "/home/yohe/ghjk/.dev/rusty_v8" + "val": "/var/home/asdf/repos/ecma/ghjk/.dev/rusty_v8" }, { "ty": "ghjk.ports.InstallSetRef", @@ -470,12 +453,62 @@ "envsNamed": { "main": "bciqfnku2tswsz4gapwhys5ox5uiyzcb5r7bmuwzljjeziljcu7efroi", "_rust": "bciqex5g2cetqvfipwhu6fb3mmyke3y6jvrscjrykf2zl7wfwupiqhca", - "dev": "bciqnerbswitlqt27ado74puxt3faxea6jaxe4wvytnzwjpupig25kky" + "dev": "bciqgcwltl3sbuyrqlhxz2spihe2asdzrgt3axosw3mre7ived23syhy" } } } ], "blackboard": { + "bciqjucge6yrzcawqzcljvrpmtwrocecsww6pcjwipzn5j2hfwjof7za": { + "buildDepConfigs": { + "asdf_plugin_git": { + "pluginRepo": "https://github.com/lsanwick/asdf-jq", + "portRef": "asdf_plugin_git@0.1.0" + } + }, + "resolutionDepConfigs": { + "asdf_plugin_git": { + "pluginRepo": "https://github.com/lsanwick/asdf-jq", + "portRef": "asdf_plugin_git@0.1.0" + } + }, + "port": { + "ty": "denoWorker@v1", + "name": "asdf", + "platforms": [ + "x86_64-linux", + "aarch64-linux", + "x86_64-darwin", + "aarch64-darwin" + ], + "version": "0.1.0", + "buildDeps": [ + { + "name": "curl_aa" + }, + { + "name": "git_aa" + }, + { + "name": "asdf_plugin_git" + } + ], + "resolutionDeps": [ + { + "name": "curl_aa" + }, + { + "name": "git_aa" + }, + { + "name": "asdf_plugin_git" + } + ], + "moduleSpecifier": "file:///ports/asdf.ts" + }, + "pluginRepo": "https://github.com/lsanwick/asdf-jq", + "installType": "version" + }, "bciqe72molvtvcuj3tuh47ziue2oqd6t4qetxn3rsoa764ofup6uwjmi": { "port": { "ty": "denoWorker@v1", diff --git a/Cargo.lock b/Cargo.lock index 622add8..3bcd8a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3608,7 +3608,7 @@ dependencies = [ "ahash", "anyhow", "async-trait", - "bitflags 1.3.2", + "bitflags 2.6.0", "clap", "clap_complete", "color-eyre", @@ -3625,7 +3625,7 @@ dependencies = [ "futures", "futures-concurrency", "indexmap 2.6.0", - "itertools 0.10.5", + "itertools 0.13.0", "json-canon", "multihash", "nix 0.29.0", diff --git a/ghjk.ts b/ghjk.ts index 54b207f..79e8be0 100644 --- a/ghjk.ts +++ b/ghjk.ts @@ -7,6 +7,7 @@ import * as ports from "./ports/mod.ts"; import { sedLock } from "./std.ts"; import { downloadFile, DownloadFileArgs } from "./utils/mod.ts"; import { unarchive } from "./utils/unarchive.ts"; +import dummy from "./ports/dummy.ts"; // keep in sync with the deno repo's ./rust-toolchain.toml const RUST_VERSION = "1.82.0"; @@ -55,7 +56,6 @@ env("main").vars({ env("_rust") .install( - // TODO: cmake ports.protoc(), ports.pipi({ packageName: "cmake" })[0], installs.rust, @@ -79,8 +79,13 @@ if (Deno.build.os == "linux" && !Deno.env.has("NO_MOLD")) { env("dev").install(mold); } -// these are just for quick testing -install(); +// these are just for quick testing +install( + ports.asdf({ + pluginRepo: "https://github.com/lsanwick/asdf-jq", + installType: "version", + }), +); const DENO_VERSION = "2.1.2"; diff --git a/modules/ports/sync.ts b/modules/ports/sync.ts index 9a0ad98..becd443 100644 --- a/modules/ports/sync.ts +++ b/modules/ports/sync.ts @@ -518,9 +518,14 @@ function resolveConfig( version.match(new RegExp(`^v?${config.version}$`)) ); if (!match) { - throw new Error(`error resolving verison: not found`, { - cause: { config, manifest, allVersions }, - }); + throw new Error( + `error resolving verison ${config.version}: not found, available versions: [${ + allVersions.join(", ") + }]`, + { + cause: { config, manifest, allVersions }, + }, + ); } version = match; } else { diff --git a/ports/asdf.ts b/ports/asdf.ts index c0bfd14..dff7a47 100644 --- a/ports/asdf.ts +++ b/ports/asdf.ts @@ -124,6 +124,7 @@ export class Port extends PortBase { return; } const conf = confValidator.parse(args.config); + await $.path(args.downloadPath).ensureDir(); await $`${binPath}` .env({ ...pathsWithDepArts(args.depArts, args.platform.os), @@ -136,6 +137,7 @@ export class Port extends PortBase { } override async install(args: InstallArgs) { const conf = confValidator.parse(args.config); + await $.path(args.installPath).ensureDir(); await $`${ depExecShimPath(std_ports.asdf_plugin_git, "install", args.depArts) }` diff --git a/ports/cmake.ts b/ports/cmake.ts deleted file mode 100644 index 979bc72..0000000 --- a/ports/cmake.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { InstallConfigFat, InstallConfigSimple } from "../port.ts"; -import { AsdfInstallConf } from "./asdf.ts"; -import { PipiInstallConf } from "./pipi.ts"; -import * as ports from "./mod.ts"; - -/** - * Port to install cmake - * - * For macOS users, you need to add python as allowed build dependencies - * as cmake is downladed via pip install. - * - * For other platforms, the `asdf_plugin_git` build dependency is required. - * - * Set the `enableRuntimes` flag to setup both cases. - * - * ```typescript - * ghjk.config({ - * enableRuntimes: true, - * }); - * - * ghjk.install(ports.cmake()); - * ``` - */ -export default function conf( - config: InstallConfigSimple = {}, -): InstallConfigFat[] { - /* - The universal macOS cmake build downloaded by asdf crashes - due to security restrictions in macOS, so it's installed using pipi port instead, which runs with no problems. - */ - if (Deno.build.os === "darwin") { - const pipiConfig: PipiInstallConf = { - packageName: "cmake", - version: config.version, - }; - return ports.pipi(pipiConfig); - } - const asdfConfig: AsdfInstallConf = { - ...config, - pluginRepo: "https://github.com/asdf-community/asdf-cmake", - installType: "version", - version: config.version, - }; - - return [ports.asdf(asdfConfig)]; -} diff --git a/ports/dummy.ts b/ports/dummy.ts index 8ea5c9c..20248d2 100644 --- a/ports/dummy.ts +++ b/ports/dummy.ts @@ -46,7 +46,7 @@ export class Port extends PortBase { } listAll() { - return ["dummy"]; + return []; } override async download(args: DownloadArgs) { diff --git a/ports/mod.ts b/ports/mod.ts index 4b23bed..b978241 100644 --- a/ports/mod.ts +++ b/ports/mod.ts @@ -3,7 +3,6 @@ export { default as asdf } from "./asdf.ts"; export { default as asdf_plugin_git } from "./asdf_plugin_git.ts"; export { default as cargo_binstall } from "./cargo-binstall.ts"; export { default as cargobi } from "./cargobi.ts"; -export { default as cmake } from "./cmake.ts"; export { default as cpy_bs } from "./cpy_bs.ts"; export { default as curl } from "./curl.ts"; export { default as deno_ghrel } from "./deno_ghrel.ts"; diff --git a/src/deno_systems/bindings.ts b/src/deno_systems/bindings.ts index 496d2cd..d1f58b7 100644 --- a/src/deno_systems/bindings.ts +++ b/src/deno_systems/bindings.ts @@ -1,3 +1,22 @@ +// NOTE: this mechanism is currently offline for deno systems +// we just +// +// we catch all rejections and explicityly dispatch them to the host +// to avoid shutting down the event loop on uncaught errors +globalThis.addEventListener("unhandledrejection", (evt) => { + let reason = evt.reason; + if (reason instanceof Error) { + reason = reason.stack; + } + if (Ghjk.dispatchException(reason)) { + evt.preventDefault(); + } +}); + +// start an interval to prevent the event loop exiting +// after loading systems +setInterval(() => {/* beat */}, 1000); + // import "../../src/ghjk/js/mock.sfx.ts"; import { zod } from "../../deps/common.ts"; import { $, unwrapZodRes } from "../../utils/mod.ts"; @@ -13,9 +32,6 @@ import type { } from "./types.ts"; import bindingTypes from "./types.ts"; -// start an interval to prevent the event loop exiting -// after loading systems -setInterval(() => {/* beat */}, 1000); // FIXME: better means of exit detection, keep alive as long // as callbacks are registered? // globalThis.onbeforeunload = (evt) => { diff --git a/src/denort/lib.rs b/src/denort/lib.rs index 22c7a94..3706ef1 100644 --- a/src/denort/lib.rs +++ b/src/denort/lib.rs @@ -2,6 +2,7 @@ pub use deno; +pub mod macros; pub mod promises; pub mod unsync; pub mod worker; diff --git a/src/denort/macros.rs b/src/denort/macros.rs new file mode 100644 index 0000000..a798aa4 --- /dev/null +++ b/src/denort/macros.rs @@ -0,0 +1,16 @@ +// Conversion that preserves source chain +// but not backtraces. +// This can be made a funciton but we have to +// depend on anyhow directly to be able to refer +// to it's Error type. +// https://github.com/eyre-rs/eyre/issues/31 +#[macro_export] +macro_rules! anyhow_to_eyre { + () => { + |err| { + eyre::format_err!(Box::::from( + err + )) + } + }; +} diff --git a/src/denort/worker.rs b/src/denort/worker.rs index ff877e7..c58fa85 100644 --- a/src/denort/worker.rs +++ b/src/denort/worker.rs @@ -96,12 +96,7 @@ async fn module_worker( trace!(?msg, "module worker msg"); match msg { ModuleWorkerReq::Run { response_channel } => response_channel - .send( - module_cx - .run(global_term_signal.clone()) - .await - .map_err(|err| ferr!(Box::new(err))), - ) + .send(module_cx.run(global_term_signal.clone()).await) .expect_or_log("channel error"), ModuleWorkerReq::DriveTillExit { term_signal, @@ -111,7 +106,7 @@ async fn module_worker( module_cx .drive_till_exit(global_term_signal.clone(), term_signal) .await - .map_err(|err| ferr!(Box::new(err))), + .map_err(crate::anyhow_to_eyre!()), ) .expect_or_log("channel error"), ModuleWorkerReq::Execute { response_channel } => response_channel @@ -119,7 +114,7 @@ async fn module_worker( module_cx .execute_main_module() .await - .map_err(|err| ferr!(Box::new(err))), + .map_err(crate::anyhow_to_eyre!()), ) .expect_or_log("channel error"), ModuleWorkerReq::GetLoadedModules { response_channel } => response_channel @@ -175,7 +170,7 @@ impl WorkerContext { let graph = cli_factory .main_module_graph_container() .await - .map_err(|err| ferr!(Box::new(err)))? + .map_err(crate::anyhow_to_eyre!())? .clone(); Ok(Self { cli_factory, @@ -195,7 +190,7 @@ impl WorkerContext { let desc_parser = self .cli_factory .permission_desc_parser() - .map_err(|err| ferr!(Box::new(err)))? + .map_err(crate::anyhow_to_eyre!())? .clone(); let permissions = deno_permissions::Permissions::from_options(desc_parser.as_ref(), permissions)?; @@ -210,11 +205,11 @@ impl WorkerContext { stdio, ) .await - .map_err(|err| ferr!(Box::new(err)))?; + .map_err(crate::anyhow_to_eyre!())?; let maybe_coverage_collector = worker .maybe_setup_coverage_collector() .await - .map_err(|err| ferr!(Box::new(err)))?; + .map_err(crate::anyhow_to_eyre!())?; // TODO: hot module support, expose shared worker contet from deno/cli/worker // let maybe_hmr_runner = worker @@ -339,26 +334,33 @@ impl ModuleWorkerContext { use deno::graph_container::*; self.graph .graph() - .walk( - [&self.main_module].into_iter(), - deno::deno_graph::WalkOptions { - kind: deno::deno_graph::GraphKind::CodeOnly, - check_js: false, - follow_dynamic: true, - prefer_fast_check_graph: false, - }, - ) - .map(|(url, _)| url.clone()) + .modules() + .map(|module| match module { + deno_graph::Module::Js(js_module) => js_module.specifier.clone(), + deno_graph::Module::Json(json_module) => json_module.specifier.clone(), + deno_graph::Module::Wasm(wasm_module) => wasm_module.specifier.clone(), + deno_graph::Module::Npm(npm_module) => npm_module.specifier.clone(), + deno_graph::Module::Node(built_in_node_module) => { + built_in_node_module.specifier.clone() + } + deno_graph::Module::External(external_module) => external_module.specifier.clone(), + }) .collect() } - async fn run(&mut self, global_term_signal: TermSignal) -> anyhow::Result { + async fn run(&mut self, global_term_signal: TermSignal) -> Res { debug!("main_module {}", self.main_module); - self.execute_main_module().await?; + self.execute_main_module() + .await + .map_err(crate::anyhow_to_eyre!())?; - let (_local_signal_tx, local_signal_rx) = tokio::sync::watch::channel(false); - self.drive_till_exit(global_term_signal, local_signal_rx) + let (_term_signal_tx, term_signal_rx) = tokio::sync::watch::channel(false); + let exit_code = self + .drive_till_exit(global_term_signal, term_signal_rx) .await + .map_err(crate::anyhow_to_eyre!())?; + + Ok(exit_code) } async fn drive_till_exit( @@ -410,9 +412,9 @@ impl ModuleWorkerContext { break }, event_loop_result = event_loop_future => { - event_loop_result? + anyhow::Context::context(event_loop_result, "event loop error")?; } - }; + } let web_continue = self.worker.dispatch_beforeunload_event()?; if !web_continue { @@ -444,7 +446,6 @@ impl ModuleWorkerContext { .await?; } */ Ok(self.worker.exit_code()) - //.map_err(|err| ferr!(Box::new(err))) } async fn execute_main_module(&mut self) -> anyhow::Result<()> { @@ -485,20 +486,27 @@ pub struct FinishedWorkerHandle { sender: tokio::sync::mpsc::Sender, } +#[derive(Debug)] +pub struct ActiveWorkerHandle { + pub exit_code_rx: tokio::sync::oneshot::Receiver>, + pub term_signal_tx: tokio::sync::watch::Sender, + pub finished: FinishedWorkerHandle, +} + impl ModuleWorkerHandle { /// Load and execute the main module /// and drive the main loop until the program /// exits. pub async fn run(self) -> Res<(i32, FinishedWorkerHandle)> { - let (tx, rx) = tokio::sync::oneshot::channel(); + let (result_tx, result_rx) = tokio::sync::oneshot::channel(); self.sender .send(ModuleWorkerReq::Run { - response_channel: tx, + response_channel: result_tx, }) .await .expect_or_log("channel error"); Ok(( - rx.await.expect_or_log("channel error")?, + result_rx.await.expect_or_log("channel error")?, FinishedWorkerHandle { sender: self.sender, }, @@ -523,29 +531,23 @@ impl ModuleWorkerHandle { /// result in returned channel or the term signal /// is lit. /// Expects that [`execute`] was called first on the worker. - pub async fn drive_till_exit( - self, - ) -> Res<( - tokio::sync::oneshot::Receiver>, - tokio::sync::watch::Sender, - FinishedWorkerHandle, - )> { + pub async fn drive_till_exit(self) -> Res { let (term_signal_tx, term_signal_rx) = tokio::sync::watch::channel(false); - let (tx, rx) = tokio::sync::oneshot::channel(); + let (exit_code_tx, exit_code_rx) = tokio::sync::oneshot::channel(); self.sender .send(ModuleWorkerReq::DriveTillExit { term_signal: term_signal_rx, - response_channel: tx, + response_channel: exit_code_tx, }) .await .expect_or_log("channel error"); - Ok(( - rx, + Ok(ActiveWorkerHandle { + exit_code_rx, term_signal_tx, - FinishedWorkerHandle { + finished: FinishedWorkerHandle { sender: self.sender, }, - )) + }) } } diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index 1ff779e..093db3e 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -26,9 +26,9 @@ time = { version = "0.3", features = ["serde"] } nix = { version = "0.29.0", features = ["signal"] } once_cell = "1.19" -parking_lot = "*" -bitflags = "*" -itertools = "*" +parking_lot = "0.12" +bitflags = "2.6" +itertools = "0.13" smallvec = { version = "1", features = [ "serde", diff --git a/src/ghjk/cli.rs b/src/ghjk/cli.rs index f7a0df1..75692e1 100644 --- a/src/ghjk/cli.rs +++ b/src/ghjk/cli.rs @@ -78,11 +78,12 @@ pub async fn cli() -> Res { let hcx = host::HostCtx::new( gcx.clone(), host::Config { + env_vars: std::env::vars().collect(), + cwd, + // TODO: env vars, flags and tests for the following re_resolve: false, locked: false, re_serialize: false, - env_vars: std::env::vars().collect(), - cwd, }, systems_deno, ); diff --git a/src/ghjk/ext.rs b/src/ghjk/ext.rs index 706f1dd..6f79729 100644 --- a/src/ghjk/ext.rs +++ b/src/ghjk/ext.rs @@ -1,8 +1,10 @@ -use std::{cell::RefCell, rc::Rc}; - use crate::interlude::*; +use std::{cell::RefCell, rc::Rc}; + +use deno_core::v8; use deno_core::OpState; +use tokio::sync::mpsc; #[rustfmt::skip] use deno_core as deno_core; // necessary for re-exported macros to work @@ -26,6 +28,7 @@ pub fn extensions(config: ExtConfig) -> Arc>, callbacks_rx: Arc>, + exception_tx: Option>, pub hostcalls: Hostcalls, } @@ -44,6 +47,12 @@ impl ExtConfig { handle } + pub fn exceptions_rx(&mut self) -> mpsc::UnboundedReceiver { + let (tx, rx) = mpsc::unbounded_channel(); + self.exception_tx = Some(tx); + rx + } + fn inject(self, state: &mut deno_core::OpState) { let callbacks = callbacks::worker(&self); let ctx = ExtContext { @@ -56,7 +65,13 @@ impl ExtConfig { deno_core::extension!( ghjk_deno_ext, - ops = [op_blackboard_get, op_blackboard_set, callbacks::op_callbacks_set, op_hostcall], + ops = [ + op_blackboard_get, + op_blackboard_set, + callbacks::op_callbacks_set, + op_hostcall, + op_dispatch_exception2 + ], options = { config: ExtConfig }, state = |state, opt| { opt.config.inject(state); @@ -126,3 +141,21 @@ pub async fn op_hostcall( }; func(args).await.map_err(|err| anyhow::anyhow!(err)) } + +#[deno_core::op2(fast)] +pub fn op_dispatch_exception2( + scope: &mut v8::HandleScope, + #[state] ctx: &ExtContext, + exception: v8::Local, +) -> bool { + if let Some(tx) = &ctx.config.exception_tx { + tx.send(ferr!( + "unhandledrejection: {}", + exception.to_rust_string_lossy(scope) + )) + .expect_or_log("channel error"); + true + } else { + false + } +} diff --git a/src/ghjk/ext/callbacks.rs b/src/ghjk/ext/callbacks.rs index 72507ad..ad21a0a 100644 --- a/src/ghjk/ext/callbacks.rs +++ b/src/ghjk/ext/callbacks.rs @@ -5,8 +5,9 @@ use crate::interlude::*; use deno_core::serde_v8; use deno_core::v8; use deno_core::OpState; +// necessary for re-exported macros to work #[rustfmt::skip] -use deno_core as deno_core; // necessary for re-exported macros to work +use deno_core as deno_core; use tokio::sync::{mpsc, oneshot}; use super::ExtConfig; @@ -16,16 +17,16 @@ use super::ExtContext; pub enum CallbackError { #[error("no callback found under {key}")] NotFound { key: String }, - #[error("callback protocol error {0:?}")] - ProtocolError(eyre::Report), - #[error("error executing callback {0:?}")] - JsError(eyre::Report), - #[error("v8 error {0:?}")] - V8Error(eyre::Report), + #[error("callback protocol error")] + ProtocolError(#[source] eyre::Report), + #[error("error executing callback")] + JsError(#[source] eyre::Report), + #[error("v8 error")] + V8Error(#[source] eyre::Report), } struct CallbackCtx { - rx: tokio::sync::mpsc::Receiver, + rx: mpsc::Receiver, term_signal: tokio::sync::watch::Receiver, } @@ -39,16 +40,16 @@ pub struct CallbackLine { impl CallbackLine { pub fn new(dworker: &denort::worker::DenoWorkerHandle) -> (Self, CallbacksHandle) { - let (tx, rx) = tokio::sync::mpsc::channel(1); + let (msg_tx, msg_rx) = mpsc::channel(1); ( Self { was_set: true, cx: Some(CallbackCtx { - rx, + rx: msg_rx, term_signal: dworker.term_signal_watcher(), }), }, - CallbacksHandle { sender: tx }, + CallbacksHandle { msg_tx }, ) } @@ -65,7 +66,7 @@ impl CallbackLine { /// Line used to invoke callbacks registered by js code. #[derive(Clone)] pub struct CallbacksHandle { - sender: mpsc::Sender, + msg_tx: mpsc::Sender, } impl CallbacksHandle { @@ -75,7 +76,7 @@ impl CallbacksHandle { args: serde_json::Value, ) -> Result { let (tx, rx) = tokio::sync::oneshot::channel(); - self.sender + self.msg_tx .send(CallbacksMsg::Exec { response_channel: tx, key, @@ -212,44 +213,41 @@ impl Callbacks { } res }; - if res.is_promise() { - let promise = v8::Local::::try_from(res).unwrap(); - - let deno_shutting_down = - denort::promises::watch_promise(scope, promise, move |scope, _rf, res| { - let res = - match res { - Ok(val) => serde_v8::from_v8(scope, val).map_err(|err| { - CallbackError::ProtocolError(ferr!(err).wrap_err( - "error deserializaing promise result from v8", - )) - }), - Err(err) => Err(CallbackError::JsError(ferr!( - "callback promise rejection: {}", - err.to_rust_string_lossy(scope) - ))), /* Err(err) => match serde_v8::from_v8(scope, err) { - Ok(json) => Err(CallbackError::JsError(json)), - Err(err) => Err(CallbackError::ProtocolError( - ferr!(err) - .wrap_err("error deserializaing promise rejection from v8"), - )), - }, */ - }; - tx.send(res).expect_or_log("channel error") - }) - .is_none(); - if deno_shutting_down { - return Err(CallbackError::V8Error(ferr!("js runtime is shutting down"))); - }; - Ok(None) - } else { + if !res.is_promise() { let res = serde_v8::from_v8(scope, res).map_err(|err| { CallbackError::ProtocolError( ferr!(err).wrap_err("error deserializaing result from v8"), ) })?; - Ok(Some(res)) + return Ok(Some(res)); } + let promise = v8::Local::::try_from(res).unwrap(); + let deno_shutting_down = + denort::promises::watch_promise(scope, promise, move |scope, _rf, res| { + let res = match res { + Ok(val) => serde_v8::from_v8(scope, val).map_err(|err| { + CallbackError::ProtocolError( + ferr!(err) + .wrap_err("error deserializaing promise result from v8"), + ) + }), + // FIXME: this is a bit of a mess and a bunch of workaround + // for private deno_core functionality as discussed at + // https://github.com/denoland/deno/discussions/27504 + Err(err) => Err(CallbackError::JsError( + ferr!(js_error_message(scope, err)) + .wrap_err("callback promise rejection"), + )), + }; + if let Err(res) = tx.send(res) { + debug!(?res, "callback response after abortion"); + } + }) + .is_none(); + if deno_shutting_down { + return Err(CallbackError::V8Error(ferr!("js runtime is shutting down"))); + }; + Ok(None) }) }); @@ -272,6 +270,75 @@ impl Callbacks { } } +fn js_error_message(scope: &mut v8::HandleScope, err: v8::Local) -> String { + let Some(obj) = err.to_object(scope) else { + return err.to_rust_string_lossy(scope); + }; + let evt_err_class = { + let name = v8::String::new(scope, "ErrorEvent") + .expect_or_log("v8 error") + .into(); + scope + .get_current_context() + // classes are stored on the global obj + .global(scope) + .get(scope, name) + .expect_or_log("v8 error") + .to_object(scope) + .expect_or_log("v8 error") + }; + if !obj + .instance_of(scope, evt_err_class) + .expect_or_log("v8 error") + { + for key in &["stack", "message"] { + let key = v8::String::new(scope, key).expect_or_log("v8 error"); + if let Some(inner) = obj.get(scope, key.into()) { + if inner.boolean_value(scope) { + return inner.to_rust_string_lossy(scope); + } + } + } + return err.to_rust_string_lossy(scope); + } + // ErrorEvents are recieved here for some reason + // https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent + { + // if it has an error value attached, prefer that + let key = v8::String::new(scope, "error") + .expect_or_log("v8 error") + .into(); + if let Some(inner) = obj.get(scope, key) { + // check if it's not null or undefined + if inner.boolean_value(scope) { + // stack messages are preferred if it has one + let Some(inner) = inner.to_object(scope) else { + return inner.to_rust_string_lossy(scope); + }; + let key = v8::String::new(scope, "stack").expect_or_log("v8 error"); + if let Some(stack) = inner.get(scope, key.into()) { + if stack.boolean_value(scope) { + return stack.to_rust_string_lossy(scope); + } + } + return inner.to_rust_string_lossy(scope); + } + } + } + #[derive(Deserialize)] + struct ErrorEvt { + lineno: i64, + colno: i64, + filename: String, + message: String, + } + let evt: ErrorEvt = serde_v8::from_v8(scope, err).unwrap(); + format!( + "{} ({}:{}:{})", + evt.message, evt.filename, evt.lineno, evt.colno + ) +} + struct Callback { js_fn: SendPtr, async_work_sender: deno_core::V8CrossThreadTaskSpawner, diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index 73ed645..d25e8b3 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -133,7 +133,7 @@ pub async fn systems_from_ghjkfile( // no longer exists || ghjkfile_hash.is_none() || obj - .is_stale(hcx.as_ref(), ghjkfile_hash.as_ref().unwrap()) + .is_stale(hcx.as_ref()) .await .inspect(|is_stale| { if *is_stale { @@ -360,8 +360,8 @@ pub struct LockObj { pub enum LockfileError { #[error("error parsing lockfile:{0}")] Serialization(serde_json::Error), - #[error("{0}")] - Other(eyre::Report), + #[error(transparent)] + Other(#[from] eyre::Report), } impl LockObj { diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs index aa5fb2b..c42205b 100644 --- a/src/ghjk/host/hashfile.rs +++ b/src/ghjk/host/hashfile.rs @@ -5,8 +5,6 @@ use super::HostCtx; #[derive(Debug, Serialize, Deserialize)] pub struct HashObj { pub version: String, - /// Hash of the ghjkfile contents. - pub ghjkfile_hash: String, /// Hashes of all env vars that were read. pub env_var_hashes: indexmap::IndexMap>, /// Hashes of all files that were read. @@ -21,7 +19,7 @@ pub enum HashfileError { #[error("error parsing hashfile: {0}")] Serialization(serde_json::Error), #[error("{0}")] - Other(eyre::Report), + Other(#[source] eyre::Report), } impl HashObj { @@ -37,13 +35,16 @@ impl HashObj { &hcx.config.env_vars, res.accessed_env_keys.iter().map(|key| key.as_ref()), ), - ghjkfile_hash: file_digest_hash(hcx, ghjkfile_path) - .await? - .expect_or_log("ghjkfile is gone"), listed_files: res .listed_file_paths .iter() - .map(|path| pathdiff::diff_paths(path, &hcx.config.cwd).unwrap_or_log()) + .map(|path| { + pathdiff::diff_paths( + std::path::absolute(path).expect_or_log("error absolutizing path"), + &hcx.config.cwd, + ) + .unwrap_or_log() + }) .collect(), read_file_hashes: file_digests( hcx, @@ -70,11 +71,7 @@ impl HashObj { } #[tracing::instrument(skip(hcx))] - pub async fn is_stale(&self, hcx: &HostCtx, ghjkfile_hash: &str) -> Res { - if self.ghjkfile_hash != ghjkfile_hash { - trace!("stale ghjkfile hash"); - return Ok(true); - } + pub async fn is_stale(&self, hcx: &HostCtx) -> Res { { let new_digest = env_var_digests( &hcx.config.env_vars, @@ -133,7 +130,7 @@ async fn file_digests( // FIXME: this will exhaust memory if the number of files is large // ConcurrentStream supports limiting concurrency but has a bug // tracked at https://github.com/yoshuawuyts/futures-concurrency/issues/203 - futures::future::join_all( + let mut map = futures::future::join_all( read_files .into_iter() .map(|path| { @@ -149,7 +146,9 @@ async fn file_digests( ) .await .into_iter() - .collect() + .collect::>>()?; + map.sort_unstable_keys(); + Ok(map) /* let out = read_files .into_co_stream() .map(|path| async move { @@ -184,10 +183,16 @@ pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> None }; - Ok(Some(crate::utils::hash_obj(&serde_json::json!({ + let stat = StatMeta { + // we're not going to invalidate on access + accessed: None, + ..StatMeta::from(stat) + }; + let json = serde_json::json!({ "content_hash": content_hash, - "stat": StatMeta::from(stat) - })))) + "stat": stat + }); + Ok(Some(crate::utils::hash_obj(&json))) } Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(None), Err(err) => Err(err).wrap_err("error on file stat"), diff --git a/src/ghjk/js/00_runtime.js b/src/ghjk/js/00_runtime.js index 89498fa..2870e5d 100644 --- a/src/ghjk/js/00_runtime.js +++ b/src/ghjk/js/00_runtime.js @@ -38,6 +38,7 @@ const ____GhjkHost = { }, }, hostcall: getOp("op_hostcall"), + dispatchException: getOp("op_dispatch_exception2"), }; globalThis.____GhjkHost = ____GhjkHost; diff --git a/src/ghjk/js/runtime.d.ts b/src/ghjk/js/runtime.d.ts index 8d4e664..d0bc53e 100644 --- a/src/ghjk/js/runtime.d.ts +++ b/src/ghjk/js/runtime.d.ts @@ -12,5 +12,6 @@ type GhjkNs = { set: (key: string, fn: (arg: Json) => Json | Promise) => string; }; hostcall: (key: string, args: Json) => Promise; + dispatchException: (exception: any) => boolean; }; export const Ghjk: GhjkNs; diff --git a/src/ghjk/log.rs b/src/ghjk/log.rs index 34279bb..4aa0f03 100644 --- a/src/ghjk/log.rs +++ b/src/ghjk/log.rs @@ -49,7 +49,7 @@ Args: {args:?} eyre_panic_hook(panic_info); // - Tokio does not exit the process when a task panics, so we define a custom // panic hook to implement this behaviour. - std::process::exit(1); + // std::process::exit(1); })); _eyre_hook.install().unwrap(); diff --git a/src/ghjk/systems/deno.rs b/src/ghjk/systems/deno.rs index 79b488d..84bb2a0 100644 --- a/src/ghjk/systems/deno.rs +++ b/src/ghjk/systems/deno.rs @@ -98,6 +98,7 @@ pub async fn systems_from_deno( }), ); let cb_line = ext_conf.callbacks_handle(&gcx.deno); + let mut exception_line = ext_conf.exceptions_rx(); let mut worker = gcx .deno @@ -122,10 +123,10 @@ pub async fn systems_from_deno( ) .await?; worker.execute().await?; - let (mut exit_code_channel, term_signal, _) = worker.drive_till_exit().await?; + let mut active_worker = worker.drive_till_exit().await?; let manifests = tokio::select! { - res = &mut exit_code_channel => { + res = &mut active_worker.exit_code_rx => { let exit_code = res .expect_or_log("channel error") .wrap_err("deno systems error building manifests")?; @@ -139,24 +140,45 @@ pub async fn systems_from_deno( let manifests: Vec = serde_json::from_value(manifests).wrap_err("protocol error")?; - let dcx = gcx.deno.clone(); - let join_exit_code_watcher = tokio::spawn(async { - let err = match exit_code_channel.await { - Ok(Ok(0)) => return Ok(()), - Ok(Ok(exit_code)) => { - ferr!("deno systems died with non-zero exit code: {exit_code}") + let term_signal = active_worker.term_signal_tx.clone(); + let join_exit_code_watcher = { + let dcx = gcx.deno.clone(); + tokio::spawn(async move { + let res; + loop { + res = tokio::select! { + res = &mut active_worker.exit_code_rx => { + match res { + Ok(res) => res.wrap_err("error on deno worker for deno systems"), + Err(_) => Err(ferr!("deno systems unexpected shutdown")) + } + } + Some(err) = exception_line.recv() => { + // NOTE: we only log the error here + // this assumes that the systems are processing + // a callback and that they will recieve an EventError + // when the event loop continues + // mostly relevant for Worker errors + error!("event loop error caught: {err}"); + continue; + } + }; + break; } - Ok(Err(err)) => err.wrap_err("error on event loop for deno systems"), - Err(_) => { - ferr!("deno systems unexpected shutdown") - } - }; - error!("deno systems error: {err:?}"); - dcx.terminate() - .await - .expect_or_log("error terminating deno worker"); - Err(err) - }); + let err = match res { + Ok(0) => return Ok(()), + Ok(exit_code) => { + ferr!("deno systems died with non-zero exit code: {exit_code}") + } + Err(err) => err, + }; + error!("deno systems error: {err:?}"); + dcx.terminate() + .await + .expect_or_log("error terminating deno worker"); + Err(err) + }) + }; let exit_code_channel = Arc::new(std::sync::Mutex::new(Some(join_exit_code_watcher))); diff --git a/tests/envHooks.ts b/tests/envHooks.ts index 936984c..f62ac73 100644 --- a/tests/envHooks.ts +++ b/tests/envHooks.ts @@ -49,7 +49,7 @@ const fishInteractiveScript = [ ] .join("\n"); -type CustomE2eTestCase = Omit & { +type CustomE2eTestCase = Omit & { ePoint: string; stdin: string; }; @@ -78,7 +78,8 @@ const cases: CustomE2eTestCase[] = [ harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: ` + fs: { + "ghjk.ts": ` export { sophon } from "$ghjk/hack.ts"; import { task, env } from "$ghjk/hack.ts"; @@ -86,6 +87,7 @@ env("main") .onEnter(task($ => $\`/bin/sh -c 'echo remark > marker'\`)) .onExit(task($ => $\`/bin/sh -c 'rm marker'\`)) `, + }, ePoints: [{ cmd: testCase.ePoint, stdin: testCase.stdin }], name: `envHooks/${testCase.name}`, }))); diff --git a/tests/envs.ts b/tests/envs.ts index d684a40..b7f1900 100644 --- a/tests/envs.ts +++ b/tests/envs.ts @@ -9,7 +9,7 @@ import dummy from "../ports/dummy.ts"; import type { FileArgs } from "../mod.ts"; type CustomE2eTestCase = - & Omit + & Omit & { ePoint: string; stdin: string; @@ -335,14 +335,16 @@ test (dummy) = "e1"; or exit 105 harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: "ghjkTs" in testCase ? testCase.ghjkTs : genTsGhjkFile( - { - secureConf: { - ...testCase.secureConfig, - envs: [...testCase.envs, ...(testCase.secureConfig?.envs ?? [])], + fs: { + "ghjk.ts": "ghjkTs" in testCase ? testCase.ghjkTs : genTsGhjkFile( + { + secureConf: { + ...testCase.secureConfig, + envs: [...testCase.envs, ...(testCase.secureConfig?.envs ?? [])], + }, }, - }, - ), + ), + }, ePoints: [{ cmd: testCase.ePoint, stdin: testCase.stdin }], name: `envs/${testCase.name}`, }))); diff --git a/tests/hashfile.ts b/tests/hashfile.ts new file mode 100644 index 0000000..a722737 --- /dev/null +++ b/tests/hashfile.ts @@ -0,0 +1,75 @@ +import "../setup_logger.ts"; +import { E2eTestCase, harness } from "./utils.ts"; + +type CustomE2eTestCase = Omit & { + stdin: string; +}; + +const cases: CustomE2eTestCase[] = [ + { + name: "invalidated_control", + stdin: ` +__ghjk_get_mtime_ts .ghjk/hash.json > tstamp +ghjk sync +test (cat tstamp) = (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +ghjk sync +test (cat tstamp) = (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +`, + }, + { + name: "invalidated_ghjk_modified", + stdin: ` +__ghjk_get_mtime_ts .ghjk/hash.json > tstamp +echo '// hey' >> ghjk.ts +ghjk sync +test (cat tstamp) -lt (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +`, + }, + { + name: "invalidated_dep_script_modified", + stdin: ` +__ghjk_get_mtime_ts .ghjk/hash.json > tstamp +echo '// hey' >> extra.ts +ghjk sync +test (cat tstamp) -lt (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +`, + }, + { + name: "invalidated_env_modified", + stdin: ` +__ghjk_get_mtime_ts .ghjk/hash.json > tstamp +MY_ENV=changed ghjk sync +test (cat tstamp) -lt (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +`, + }, + { + name: "invalidated_listed_file_removed", + stdin: ` +__ghjk_get_mtime_ts .ghjk/hash.json > tstamp +rm dir/one +ghjk sync +test (cat tstamp) -lt (__ghjk_get_mtime_ts .ghjk/hash.json); or exit 101 +`, + }, +]; + +harness(cases.map((testCase) => ({ + ...testCase, + fs: { + "ghjk.ts": ` +export { sophon } from "$ghjk/hack.ts"; +import { task, env } from "$ghjk/hack.ts"; +import {stuff} from "./extra.ts" + +await Array.fromAsync(Deno.readDir("dir")) + +env("main") + .vars({ hello: Deno.env.get("MY_ENV") ?? "world" }) +`, + "extra.ts": `export const stuff = "hello"`, + "dir/one": "1", + "dir/two": "2", + }, + ePoints: [{ cmd: "fish", stdin: testCase.stdin }], + name: `hashfile/${testCase.name}`, +}))); diff --git a/tests/ports.ts b/tests/ports.ts index e4fe16f..f1a8cae 100644 --- a/tests/ports.ts +++ b/tests/ports.ts @@ -6,7 +6,7 @@ import dummy from "../ports/dummy.ts"; import type { InstallConfigFat } from "../modules/ports/types.ts"; import { testTargetPlatform } from "./utils.ts"; -type CustomE2eTestCase = Omit & { +type CustomE2eTestCase = Omit & { ePoint: string; installConf: InstallConfigFat | InstallConfigFat[]; secureConf?: FileArgs; @@ -28,6 +28,14 @@ const cases: CustomE2eTestCase[] = [ installConf: ports.jq_ghrel(), ePoint: `jq --version`, }, + { + name: "jq", + installConf: ports.asdf({ + pluginRepo: "https://github.com/lsanwick/asdf-jq", + installType: "version", + }), + ePoint: `jq --version`, + }, // 3 megs { name: "protoc", @@ -159,15 +167,6 @@ const cases: CustomE2eTestCase[] = [ installConf: ports.cpy_bs(), ePoint: `python3 --version`, }, - // 77 meg +, depends on "cpy_bs" on darwin/macos - { - name: "cmake", - installConf: ports.cmake({}), - ePoint: `cmake --version`, - secureConf: { - enableRuntimes: true, - }, - }, // 80 meg + { name: "pipi-poetry", @@ -220,16 +219,18 @@ const cases: CustomE2eTestCase[] = [ harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: genTsGhjkFile( - { - secureConf: { - ...testCase.secureConf, - installs: Array.isArray(testCase.installConf) - ? testCase.installConf - : [testCase.installConf], + fs: { + "ghjk.ts": genTsGhjkFile( + { + secureConf: { + ...testCase.secureConf, + installs: Array.isArray(testCase.installConf) + ? testCase.installConf + : [testCase.installConf], + }, }, - }, - ), + ), + }, ePoints: [ ...["bash -c", "fish -c", "zsh -c"].map((sh) => ({ cmd: [...`env ${sh}`.split(" "), `"${testCase.ePoint}"`], diff --git a/tests/portsOutdated.ts b/tests/portsOutdated.ts index 2519ccd..4e4b013 100644 --- a/tests/portsOutdated.ts +++ b/tests/portsOutdated.ts @@ -4,7 +4,7 @@ import * as ports from "../ports/mod.ts"; import type { InstallConfigFat } from "../modules/ports/types.ts"; import { FileArgs } from "../mod.ts"; -type CustomE2eTestCase = Omit & { +type CustomE2eTestCase = Omit & { ePoint: string; installConf: InstallConfigFat | InstallConfigFat[]; secureConf?: FileArgs; @@ -37,16 +37,18 @@ const cases: CustomE2eTestCase[] = [ harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: genTsGhjkFile( - { - secureConf: { - ...testCase.secureConf, - installs: Array.isArray(testCase.installConf) - ? testCase.installConf - : [testCase.installConf], + fs: { + "ghjk.ts": genTsGhjkFile( + { + secureConf: { + ...testCase.secureConf, + installs: Array.isArray(testCase.installConf) + ? testCase.installConf + : [testCase.installConf], + }, }, - }, - ), + ), + }, ePoints: [ ...["bash -c", "fish -c", "zsh -c"].map((sh) => ({ cmd: [...`env ${sh}`.split(" "), `"${testCase.ePoint}"`], diff --git a/tests/reloadHooks.ts b/tests/reloadHooks.ts index c9be1ba..a29fa5d 100644 --- a/tests/reloadHooks.ts +++ b/tests/reloadHooks.ts @@ -199,7 +199,7 @@ test "$GHJK_ENV" = "test"; or exit 112 ]) .join("\n"); -type CustomE2eTestCase = Omit & { +type CustomE2eTestCase = Omit & { installConf?: InstallConfigFat[]; ePoint: string; stdin: string; @@ -296,21 +296,23 @@ const cases: CustomE2eTestCase[] = [ harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: genTsGhjkFile( - { - secureConf: { - envs: [ - { - name: "main", - installs: testCase.installConf ? testCase.installConf : [dummy()], - }, - { - name: "test", - }, - ], + fs: { + "ghjk.ts": genTsGhjkFile( + { + secureConf: { + envs: [ + { + name: "main", + installs: testCase.installConf ? testCase.installConf : [dummy()], + }, + { + name: "test", + }, + ], + }, }, - }, - ), + ), + }, ePoints: [{ cmd: testCase.ePoint, stdin: testCase.stdin }], name: `reloadHooks/${testCase.name}`, }))); diff --git a/tests/tasks.ts b/tests/tasks.ts index d704094..00b19ea 100644 --- a/tests/tasks.ts +++ b/tests/tasks.ts @@ -4,7 +4,7 @@ import * as ghjk from "../mod.ts"; import * as ports from "../ports/mod.ts"; type CustomE2eTestCase = - & Omit + & Omit & { ePoint: string; stdin: string; @@ -171,16 +171,18 @@ test (cat output.txt) = 'A#STATIC, B#DYNAMIC' harness(cases.map((testCase) => ({ ...testCase, - tsGhjkfileStr: "ghjkTs" in testCase ? testCase.ghjkTs : genTsGhjkFile( - { - secureConf: { - tasks: Object.fromEntries( - testCase.tasks.map((def) => [def.name!, def]), - ), - enableRuntimes: testCase.enableRuntimesOnMasterPDAL, + fs: { + "ghjk.ts": "ghjkTs" in testCase ? testCase.ghjkTs : genTsGhjkFile( + { + secureConf: { + tasks: Object.fromEntries( + testCase.tasks.map((def) => [def.name!, def]), + ), + enableRuntimes: testCase.enableRuntimesOnMasterPDAL, + }, }, - }, - ), + ), + }, ePoints: [{ cmd: testCase.ePoint, stdin: testCase.stdin }], name: `tasks/${testCase.name}`, }))); diff --git a/tests/todo.ts b/tests/todo.ts index df68f0e..53f57f2 100644 --- a/tests/todo.ts +++ b/tests/todo.ts @@ -1,2 +1 @@ -// TODO: tests for hashfile invalidation // TODO: tests for lockfile impl diff --git a/tests/utils.ts b/tests/utils.ts index f02d6a7..1171a8d 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -18,7 +18,7 @@ if ( export type E2eTestCase = { name: string; - tsGhjkfileStr: string; + fs: Record; envVars?: Record; ePoints: { cmd: string | string[]; stdin?: string }[]; timeout_ms?: number; @@ -27,7 +27,7 @@ export type E2eTestCase = { }; export async function localE2eTest(testCase: E2eTestCase) { - const { envVars: testEnvs, ePoints, tsGhjkfileStr } = testCase; + const { envVars: testEnvs, ePoints, fs } = testCase; const tmpDir = $.path( await Deno.makeTempDir({ prefix: "ghjk_le2e_", @@ -35,13 +35,19 @@ export async function localE2eTest(testCase: E2eTestCase) { ); const ghjkDataDir = await tmpDir.join("ghjk").ensureDir(); - await tmpDir.join("ghjk.ts").writeText( - tsGhjkfileStr.replaceAll( - "$ghjk", - std_url.dirname(import.meta.resolve("../mod.ts")).href, - ), + await $.co( + Object.entries(fs) + .map( + ([path, content]) => + tmpDir.join(path) + .writeText( + content.replaceAll( + "$ghjk", + std_url.dirname(import.meta.resolve("../mod.ts")).href, + ), + ), + ), ); - const ghjkExePath = $.path(import.meta.resolve("../target/debug/ghjk")); const ghjkShimPath = await ghjkDataDir .join("ghjk") diff --git a/utils/logger.ts b/utils/logger.ts index 49b5344..6415647 100644 --- a/utils/logger.ts +++ b/utils/logger.ts @@ -142,6 +142,7 @@ export default function logger( logger = new std_log.Logger(name, level, { handlers: [consoleHandler], }); + loggers.set(name, logger); } return logger; } diff --git a/utils/mod.ts b/utils/mod.ts index ab0d689..464a43d 100644 --- a/utils/mod.ts +++ b/utils/mod.ts @@ -250,11 +250,12 @@ export const $ = dax.build$( depth: 10, }); }, - co( + co: ((values: any[]) => Promise.all(values)) as typeof Promise.all, + /* co( values: T, ): Promise<{ -readonly [P in keyof T]: Awaited }> { return Promise.all(values); - }, + }, */ // coIter( // items: Iterable, // fn: (item:T) => PromiseLike, From 83780d893c50f4b421a6cb88da05a6386fd5037b Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 10:49:08 +0300 Subject: [PATCH 11/15] ci: release jobs --- .github/workflows/release.yml | 90 +++++++++++++++++++++++++++++++++++ deno.jsonc | 4 +- ports/dummy.ts | 2 +- src/ghjk/ext/callbacks.rs | 8 ---- src/ghjk/host.rs | 4 ++ src/ghjk/host/deno.rs | 2 +- src/ghjk/host/hashfile.rs | 2 +- src/ghjk/main.rs | 1 - src/ghjk/systems/deno.rs | 13 ++--- src/ghjk/systems/deno/cli.rs | 10 ++-- {scripts => tools}/check.ts | 0 {scripts => tools}/dev.ts | 0 12 files changed, 109 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/release.yml rename {scripts => tools}/check.ts (100%) rename {scripts => tools}/dev.ts (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..383e77f --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,90 @@ +name: release jobs +run-name: release jobs for ${{ github.ref }} +on: + workflow_dispatch: + inputs: + ovewriteArtifacts: + description: Ovewrite artifacts on the release. Some will only be skipped. + required: true + type: boolean + default: true + checkBump: + description: check-bump adds a release entry to github so it's disabled by default. + required: true + type: boolean + default: false + push: + tags: + - v* + +jobs: + check-bump: + runs-on: ubuntu-latest + if: github.ref_type == 'tag' || ( github.event_name == 'workflow_dispatch' && inputs.checkBump ) + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: WyriHaximus/github-action-get-previous-tag@v1.4.0 + id: latest-tag + - uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.latest-tag.outputs.tag }} + allowUpdates: ${{ github.event_name == 'workflow_dispatch' }} + generateReleaseNotes: true + discussionCategory: "Announcements" + prerelease: ${{ contains(steps.latest-tag.outputs.tag, 'rc') || contains(steps.latest-tag.outputs.tag, 'dev') }} + + pub-cli: + needs: + - check-bump + # using `always()` makes the job evaulte despite + # status of check-bump + # we combine that with our own conditions + if: | + always() + && ( + needs.check-bump.result == 'success' + || github.event_name == 'workflow_dispatch' + ) + runs-on: "${{ matrix.os }}" + strategy: + fail-fast: false + matrix: + include: + - os: macos-13 + target: x86_64-apple-darwin + - os: macos-14 + target: aarch64-apple-darwin + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + # FIXME: deno doesn't support musl today https://github.com/denoland/deno/issues/3711 + # - os: ubuntu-latest + # target: x86_64-unknown-linux-musl + - os: custom-arm + target: aarch64-unknown-linux-gnu + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + # some targets don't use cross so will require the deps in the host + - uses: WyriHaximus/github-action-get-previous-tag@v1.4.0 + id: latest-tag + - uses: dsherret/rust-toolchain-file@v1 + with: + targets: ${{ matrix.target }} + - uses: mozilla-actions/sccache-action@v0.0.6 + - run: | + rustup target add ${{ matrix.target }} + - shell: bash + run: | + cargo build --release --locked --package ghjk --target ${{ matrix.target }} + cd target/${{ matrix.target }}/release/ + tar czvf ../../../ghjk-${{ steps.latest-tag.outputs.tag }}-${{ matrix.target }}.tar.gz ghjk + cd ../../../ + - uses: svenstaro/upload-release-action@v2 + with: + tag: ${{ steps.latest-tag.outputs.tag }} + file: "ghjk-${{ steps.latest-tag.outputs.tag }}-${{ matrix.target }}.tar.gz" + asset_name: "ghjk-${{ steps.latest-tag.outputs.tag }}-${{ matrix.target }}.tar.gz" + overwrite: ${{ inputs.ovewriteArtifacts }} diff --git a/deno.jsonc b/deno.jsonc index ce5a3f9..b2f858e 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -3,8 +3,8 @@ "test": "cargo build -p ghjk && deno test --unstable-worker-options --unstable-kv -A tests/*", "self": "cargo run -p ghjk", "cache": "deno cache deps/*", - "check": "deno run -A ./scripts/check.ts", - "dev": "deno run -A ./scripts/dev.ts" + "check": "deno run -A ./tools/check.ts", + "dev": "deno run -A ./tools/dev.ts" }, "fmt": { "exclude": [ diff --git a/ports/dummy.ts b/ports/dummy.ts index 20248d2..8ea5c9c 100644 --- a/ports/dummy.ts +++ b/ports/dummy.ts @@ -46,7 +46,7 @@ export class Port extends PortBase { } listAll() { - return []; + return ["dummy"]; } override async download(args: DownloadArgs) { diff --git a/src/ghjk/ext/callbacks.rs b/src/ghjk/ext/callbacks.rs index ad21a0a..e41ff24 100644 --- a/src/ghjk/ext/callbacks.rs +++ b/src/ghjk/ext/callbacks.rs @@ -360,14 +360,6 @@ struct SendPtr(std::ptr::NonNull); // as deno unsafe impl Send for SendPtr {} -/* impl Callback { - fn drop(self, scope: &mut v8::HandleScope) { - unsafe { - _ = v8::Global::from_raw(scope, self.js_fn.0); - } - } -} */ - #[tracing::instrument(skip(state, cb))] #[deno_core::op2] pub fn op_callbacks_set( diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index d25e8b3..3303fc0 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -29,6 +29,10 @@ pub struct HostCtx { pub config: Config, #[educe(Debug(ignore))] pub systems: HashMap, + // NOTE: only use this for hashfile usage which is invalidated and generated + // anew around the serialization process which is expected to take a reasonably + // short amount of time. Any code, like system impls, afterwards might take + // an unkown amount of time possibly making the hashes in this memo stale pub file_hash_memo: DHashMap, } diff --git a/src/ghjk/host/deno.rs b/src/ghjk/host/deno.rs index 2ab871e..35bbdbd 100644 --- a/src/ghjk/host/deno.rs +++ b/src/ghjk/host/deno.rs @@ -30,7 +30,7 @@ pub async fn serialize_deno_ghjkfile( // with the deno side of the code ( "args".into(), - serde_json::json!({ + json!({ "uri": url::Url::from_file_path(path).unwrap_or_log(), }), ), diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs index c42205b..b8fc461 100644 --- a/src/ghjk/host/hashfile.rs +++ b/src/ghjk/host/hashfile.rs @@ -188,7 +188,7 @@ pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> accessed: None, ..StatMeta::from(stat) }; - let json = serde_json::json!({ + let json = json!({ "content_hash": content_hash, "stat": stat }); diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index 9c78c3e..bb59ac3 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -3,7 +3,6 @@ mod interlude { pub use crate::utils::{default, CHeapStr, DHashMap}; pub use std::collections::HashMap; - pub use std::future::Future; pub use std::path::{Path, PathBuf}; pub use std::sync::Arc; diff --git a/src/ghjk/systems/deno.rs b/src/ghjk/systems/deno.rs index 84bb2a0..bee5aa8 100644 --- a/src/ghjk/systems/deno.rs +++ b/src/ghjk/systems/deno.rs @@ -71,7 +71,7 @@ pub async fn systems_from_deno( deno_dir, } = &gcx.config; - serde_json::json!(BindingArgs { + json!(BindingArgs { uri: source_uri.clone(), config: ConfigRef { ghjkfile: ghjkfile.as_ref().map(|path| path.as_path()), @@ -268,7 +268,7 @@ impl SystemInstance for DenoSystemInstance { .callbacks .exec( self.desc.load_config_cb_key.clone(), - serde_json::json!({ + json!({ "config": config, "bb": bb, "state": state @@ -284,7 +284,7 @@ impl SystemInstance for DenoSystemInstance { .callbacks .exec( self.desc.load_lock_entry_cb_key.clone(), - serde_json::json!({ + json!({ "raw": raw }), ) @@ -295,10 +295,7 @@ impl SystemInstance for DenoSystemInstance { async fn gen_lock_entry(&self) -> Res { self.scx .callbacks - .exec( - self.desc.gen_lock_entry_cb_key.clone(), - serde_json::json!({}), - ) + .exec(self.desc.gen_lock_entry_cb_key.clone(), json!({})) .await .wrap_err("callback error") } @@ -307,7 +304,7 @@ impl SystemInstance for DenoSystemInstance { let cmds = self .scx .callbacks - .exec(self.desc.cli_commands_cb_key.clone(), serde_json::json!({})) + .exec(self.desc.cli_commands_cb_key.clone(), json!({})) .await .wrap_err("callback error")?; diff --git a/src/ghjk/systems/deno/cli.rs b/src/ghjk/systems/deno/cli.rs index 8820714..78dff72 100644 --- a/src/ghjk/systems/deno/cli.rs +++ b/src/ghjk/systems/deno/cli.rs @@ -142,20 +142,20 @@ async fn deno_cb_action( ArgActionSerde::Set => matches .try_remove_one::(id.as_str()) .wrap_err_with(|| format!("error extracting match string for {id}"))? - .map(|val| serde_json::json!(val)), + .map(|val| json!(val)), ArgActionSerde::Append => matches .try_remove_many::(id.as_str()) .wrap_err_with(|| format!("error extracting match bool for {id}"))? .map(|vals| vals.collect::>()) - .map(|val| serde_json::json!(val)), + .map(|val| json!(val)), ArgActionSerde::SetTrue | ArgActionSerde::SetFalse => matches .try_remove_one::(id.as_str()) .wrap_err_with(|| format!("error extracting match bool for {id}"))? - .map(|val| serde_json::json!(val)), + .map(|val| json!(val)), ArgActionSerde::Count => matches .try_remove_one::(id.as_str()) .wrap_err_with(|| format!("error extracting match count for {id}"))? - .map(|val| serde_json::json!(val)), + .map(|val| json!(val)), ArgActionSerde::Help | ArgActionSerde::HelpShort | ArgActionSerde::HelpLong @@ -177,7 +177,7 @@ async fn deno_cb_action( .callbacks .exec( cb_key.clone(), - serde_json::json!({ + json!({ "flags": flags, "args": args }), diff --git a/scripts/check.ts b/tools/check.ts similarity index 100% rename from scripts/check.ts rename to tools/check.ts diff --git a/scripts/dev.ts b/tools/dev.ts similarity index 100% rename from scripts/dev.ts rename to tools/dev.ts From b9a0679054d4c7d7354526d664f3ccfd19195e64 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 12:17:31 +0300 Subject: [PATCH 12/15] fix: address feedback --- .github/workflows/tests.yml | 28 ++++++++-------- Cargo.lock | 1 - install/hook.fish | 2 +- modules/envs/posix.ts | 2 +- src/deno_systems/types.ts | 4 +-- src/ghjk/Cargo.toml | 1 - src/ghjk/ext/callbacks.rs | 23 +++++++------ src/ghjk/host.rs | 11 ++----- src/ghjk/host/hashfile.rs | 63 +++++++++++++++++------------------- src/ghjk/log.rs | 12 +++---- src/ghjk/main.rs | 1 - src/ghjk/systems/deno/cli.rs | 24 +++++++------- src/ghjk/utils.rs | 2 +- tests/ports.ts | 7 ++-- 14 files changed, 85 insertions(+), 96 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 51aed6c..1517cff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -86,17 +86,17 @@ jobs: run: brew install fish zsh coreutils cmake - run: deno task test - test-action: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dsherret/rust-toolchain-file@v1 - - uses: metatypedev/setup-ghjk@318209a9d215f70716a4ac89dbeb9653a2deb8bc - with: - installer-url: ./install.ts - env: - GHJKFILE: ./examples/protoc/ghjk.ts - - run: | - cd examples/tasks - . $(ghjk print share-dir-path)/env.sh - ghjk x hey + # test-action: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - uses: dsherret/rust-toolchain-file@v1 + # - uses: metatypedev/setup-ghjk@318209a9d215f70716a4ac89dbeb9653a2deb8bc + # with: + # installer-url: ./install.ts + # env: + # GHJKFILE: ./examples/protoc/ghjk.ts + # - run: | + # cd examples/tasks + # . $(ghjk print share-dir-path)/env.sh + # ghjk x hey diff --git a/Cargo.lock b/Cargo.lock index 3bcd8a2..6b1776b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3623,7 +3623,6 @@ dependencies = [ "directories", "educe", "futures", - "futures-concurrency", "indexmap 2.6.0", "itertools 0.13.0", "json-canon", diff --git a/install/hook.fish b/install/hook.fish index 0d0d714..775063f 100644 --- a/install/hook.fish +++ b/install/hook.fish @@ -109,7 +109,7 @@ function __ghjk_preexec --on-event fish_preexec # activate script has reloaded else if set --query GHJK_LAST_ENV_DIR; - and test -e $next_env_dir/activate.fish; + and test -e $GHJK_LAST_ENV_DIR/activate.fish; and test (__ghjk_get_mtime_ts $GHJK_LAST_ENV_DIR/activate.fish) -gt $GHJK_LAST_ENV_DIR_MTIME; ghjk_hook end diff --git a/modules/envs/posix.ts b/modules/envs/posix.ts index d7466dd..323fa05 100644 --- a/modules/envs/posix.ts +++ b/modules/envs/posix.ts @@ -302,7 +302,7 @@ async function writeActivators( }), ``, `# hooks that want to invoke ghjk are made to rely`, - `# on this shim to improve to improve reliablity`, + `# on this shim to improve reliablity`, ghjk_sh(gcx, ghjkShimName), ``, `# only run the hooks in interactive mode`, diff --git a/src/deno_systems/types.ts b/src/deno_systems/types.ts index 0f887fc..85b0e17 100644 --- a/src/deno_systems/types.ts +++ b/src/deno_systems/types.ts @@ -73,8 +73,8 @@ const cliCommandBase = zod.object({ before_help: zod.string().optional(), before_long_help: zod.string().optional(), - args: zod.record(cliArg).optional().optional(), - flags: zod.record(cliFlag).optional().optional(), + args: zod.record(cliArg).optional(), + flags: zod.record(cliFlag).optional(), }); const flagsAndArgs = zod.record( diff --git a/src/ghjk/Cargo.toml b/src/ghjk/Cargo.toml index 093db3e..c6b652e 100644 --- a/src/ghjk/Cargo.toml +++ b/src/ghjk/Cargo.toml @@ -53,7 +53,6 @@ tracing-appender = "0.2" tracing-futures = "0.2" async-trait = "0.1.83" -futures-concurrency = "7.6.2" futures = { version = "=0.3.30", default-features = false, features = ["std", "async-await"] } tokio = { workspace = true, features = ["full", "parking_lot", "tracing"] } tokio-stream = "0.1" diff --git a/src/ghjk/ext/callbacks.rs b/src/ghjk/ext/callbacks.rs index e41ff24..804a28e 100644 --- a/src/ghjk/ext/callbacks.rs +++ b/src/ghjk/ext/callbacks.rs @@ -26,7 +26,7 @@ pub enum CallbackError { } struct CallbackCtx { - rx: mpsc::Receiver, + msg_rx: mpsc::Receiver, term_signal: tokio::sync::watch::Receiver, } @@ -34,7 +34,10 @@ struct CallbackCtx { /// invocations. #[derive(Default)] pub struct CallbackLine { + /// This would be None if the callback line was already + /// taken or if the callback line was not initially set cx: Option, + /// Indicates weather the callback line was initially set was_set: bool, } @@ -45,7 +48,7 @@ impl CallbackLine { Self { was_set: true, cx: Some(CallbackCtx { - rx: msg_rx, + msg_rx, term_signal: dworker.term_signal_watcher(), }), }, @@ -116,7 +119,7 @@ pub struct Callbacks { /// support callbacks. pub fn worker(config: &ExtConfig) -> Option { let CallbackCtx { - mut rx, + msg_rx: mut rx, term_signal, } = { let mut line = config.callbacks_rx.lock().expect_or_log("mutex err"); @@ -201,15 +204,10 @@ impl Callbacks { .expect_or_log("got None from callback call"); if tc_scope.has_caught() { let exception = tc_scope.exception().unwrap(); - let exception = exception.to_rust_string_lossy(tc_scope); - /* let exception = serde_v8::from_v8(tc_scope, exception).map_err(|err| { - CallbackError::ProtocolError( - ferr!(err).wrap_err("error deserializaing exception from v8"), - ) - })?; */ - return Err(CallbackError::JsError(ferr!( - "callback exception: {exception}" - ))); + return Err(CallbackError::JsError( + ferr!(js_error_message(tc_scope, exception)) + .wrap_err("callback exception"), + )); } res }; @@ -378,6 +376,7 @@ pub fn op_callbacks_set( warn!("callback set but callback feature is not enabled"); anyhow::bail!("callbacks feature is not enabled"); }; + debug!(%name, "registering callback"); callbacks.store.insert( name.into(), Callback { diff --git a/src/ghjk/host.rs b/src/ghjk/host.rs index 3303fc0..4cbcb10 100644 --- a/src/ghjk/host.rs +++ b/src/ghjk/host.rs @@ -62,12 +62,10 @@ pub async fn systems_from_ghjkfile( ); // read both files concurrently - let (hash_obj, lock_obj) = ( + let (hash_obj, lock_obj) = futures::join!( HashObj::from_file(&hashfile_path), LockObj::from_file(&lockfile_path), - ) - .join() - .await; + ); // discard corrupt files if needed let (mut hash_obj, mut lock_obj) = ( @@ -127,7 +125,7 @@ pub async fn systems_from_ghjkfile( // check if we need to discard the hashfile if let Some(obj) = &mut hash_obj { - // TODO: version migrator + // NOTE: version migrator would go here if obj.version != "0" { eyre::bail!("unsupported hashfile version: {:?}", obj.version); } @@ -154,9 +152,6 @@ pub async fn systems_from_ghjkfile( if obj.version != "0" { eyre::bail!("unsupported hashfile version: {:?}", obj.version); } - // if obj.version != "0" { - // hash_obj = None; - // } } // TODO: // if hcx.re_resolve {} diff --git a/src/ghjk/host/hashfile.rs b/src/ghjk/host/hashfile.rs index b8fc461..5ec14e0 100644 --- a/src/ghjk/host/hashfile.rs +++ b/src/ghjk/host/hashfile.rs @@ -127,41 +127,26 @@ async fn file_digests( hcx: &HostCtx, read_files: Vec<&Path>, ) -> Res>> { - // FIXME: this will exhaust memory if the number of files is large - // ConcurrentStream supports limiting concurrency but has a bug - // tracked at https://github.com/yoshuawuyts/futures-concurrency/issues/203 - let mut map = futures::future::join_all( - read_files - .into_iter() - .map(|path| { - async move { - let path = std::path::absolute(path)?; - let hash = file_digest_hash(hcx, &path).await?; - let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); - Ok((relative_path, hash)) - } - .boxed() - }) - .collect::>(), - ) + use futures::StreamExt; + let mut map = futures::stream::iter(read_files.into_iter().map(|path| { + async move { + let path = std::path::absolute(path)?; + let hash = file_digest_hash(hcx, &path).await?; + let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); + Ok((relative_path, hash)) + } + .boxed() + })) + .buffer_unordered(16) + .collect::>() .await .into_iter() .collect::>>()?; map.sort_unstable_keys(); Ok(map) - /* let out = read_files - .into_co_stream() - .map(|path| async move { - let path = tokio::fs::canonicalize(path).await?; - let hash = file_digest_hash(hcx, &path).await?; - let relative_path = pathdiff::diff_paths(path, &hcx.config.cwd).unwrap(); - Ok((relative_path, hash)) - }) - .collect::>>() - .await?; - Ok(out.into_iter().collect()) */ } +#[tracing::instrument(skip(hcx))] pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> { let path = match tokio::fs::canonicalize(path).await { Ok(val) => val, @@ -172,13 +157,23 @@ pub async fn file_digest_hash(hcx: &HostCtx, path: &Path) -> Res> }; match tokio::fs::metadata(&path).await { Ok(stat) => { + const LARGE_FILE_THRESHOLD: u64 = 100 * 1024 * 1024; // 100MB + let content_hash = if stat.file_type().is_file() || stat.file_type().is_symlink() { - Some( - file_content_digest_hash(hcx, &path) - .await? - .await - .map_err(|err| ferr!(err))?, - ) + if stat.len() > LARGE_FILE_THRESHOLD { + warn!( + len = stat.len(), + "large file detected, skippin content hash" + ); + None + } else { + Some( + file_content_digest_hash(hcx, &path) + .await? + .await + .map_err(|err| ferr!(err))?, + ) + } } else { None }; diff --git a/src/ghjk/log.rs b/src/ghjk/log.rs index 4aa0f03..5aba03c 100644 --- a/src/ghjk/log.rs +++ b/src/ghjk/log.rs @@ -35,12 +35,12 @@ Args: {args:?} let eyre_panic_hook = eyre_panic_hook.into_panic_hook(); std::panic::set_hook(Box::new(move |panic_info| { - if let Some(msg) = panic_info.payload().downcast_ref::<&str>() { - if msg.contains("A Tokio 1.x context was found, but it is being shutdown.") { - warn!("improper shutdown, make sure to terminate all workers first"); - return; - } - } else if let Some(msg) = panic_info.payload().downcast_ref::() { + if let Some(msg) = panic_info + .payload() + .downcast_ref::() + .map(|val| val.as_str()) + .or_else(|| panic_info.payload().downcast_ref::<&str>().cloned()) + { if msg.contains("A Tokio 1.x context was found, but it is being shutdown.") { warn!("improper shutdown, make sure to terminate all workers first"); return; diff --git a/src/ghjk/main.rs b/src/ghjk/main.rs index bb59ac3..95c41ad 100644 --- a/src/ghjk/main.rs +++ b/src/ghjk/main.rs @@ -18,7 +18,6 @@ mod interlude { }; pub use eyre::{format_err as ferr, Context, Result as Res, WrapErr}; pub use futures::{future::BoxFuture, FutureExt}; - pub use futures_concurrency::{future::Join, prelude::*}; pub use indexmap::IndexMap; pub use serde::{Deserialize, Serialize}; pub use serde_json::json; diff --git a/src/ghjk/systems/deno/cli.rs b/src/ghjk/systems/deno/cli.rs index 78dff72..668d47d 100644 --- a/src/ghjk/systems/deno/cli.rs +++ b/src/ghjk/systems/deno/cli.rs @@ -353,18 +353,18 @@ impl From for clap::ValueHint { use ValueHintSerde::*; match val { Unknown => clap::ValueHint::Unknown, - Other => clap::ValueHint::Unknown, - AnyPath => clap::ValueHint::Unknown, - FilePath => clap::ValueHint::Unknown, - DirPath => clap::ValueHint::Unknown, - ExecutablePath => clap::ValueHint::Unknown, - CommandName => clap::ValueHint::Unknown, - CommandString => clap::ValueHint::Unknown, - CommandWithArguments => clap::ValueHint::Unknown, - Username => clap::ValueHint::Unknown, - Hostname => clap::ValueHint::Unknown, - Url => clap::ValueHint::Unknown, - EmailAddress => clap::ValueHint::Unknown, + Other => clap::ValueHint::Other, + AnyPath => clap::ValueHint::AnyPath, + FilePath => clap::ValueHint::FilePath, + DirPath => clap::ValueHint::DirPath, + ExecutablePath => clap::ValueHint::ExecutablePath, + CommandName => clap::ValueHint::CommandName, + CommandString => clap::ValueHint::CommandString, + CommandWithArguments => clap::ValueHint::CommandWithArguments, + Username => clap::ValueHint::Username, + Hostname => clap::ValueHint::Hostname, + Url => clap::ValueHint::Url, + EmailAddress => clap::ValueHint::EmailAddress, } } } diff --git a/src/ghjk/utils.rs b/src/ghjk/utils.rs index c582840..f3d7422 100644 --- a/src/ghjk/utils.rs +++ b/src/ghjk/utils.rs @@ -4,7 +4,7 @@ use std::io::Write; #[inline] pub fn default() -> T { - std::default::Default::default() + T::default() } pub type DHashMap = dashmap::DashMap; diff --git a/tests/ports.ts b/tests/ports.ts index f1a8cae..8487bba 100644 --- a/tests/ports.ts +++ b/tests/ports.ts @@ -29,12 +29,15 @@ const cases: CustomE2eTestCase[] = [ ePoint: `jq --version`, }, { - name: "jq", + name: "asdf-jq", + ePoint: `jq --version`, installConf: ports.asdf({ pluginRepo: "https://github.com/lsanwick/asdf-jq", installType: "version", }), - ePoint: `jq --version`, + secureConf: { + enableRuntimes: true, + }, }, // 3 megs { From 1689473555144055055df7e13c8ffba84be9a10f Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 16:22:02 +0300 Subject: [PATCH 13/15] fix: high resolution time for mtime --- docs/known-issues.md | 5 ----- install/hook.fish | 8 +++++--- install/hook.sh | 4 +++- tests/utils.ts | 5 +++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/known-issues.md b/docs/known-issues.md index 9560e6c..22e06a6 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -1,10 +1,5 @@ # Known issues -## Cache invalidation of imported scripts - -Currently, ghjk is unable to track changes to local typescript files imported by the ghjk.ts file. -You can force re-serialization of the ghjkfile by deleting the `.ghjk/hash.json` file. - ## GitHub API rate-limit The GitHub API is rate-limited to 60 calls per hour for unauthenticated requests. diff --git a/install/hook.fish b/install/hook.fish index 775063f..0de6ecd 100644 --- a/install/hook.fish +++ b/install/hook.fish @@ -1,11 +1,13 @@ function __ghjk_get_mtime_ts switch (uname -s | tr '[:upper:]' '[:lower:]') case "linux" - stat -c "%Y" $argv + stat -c "%.Y" $argv case "darwin" - stat -f "%Sm" -t "%s" $argv + # darwin stat doesn't support ms since epoch so we bring out the big guns + deno eval 'console.log((await Deno.stat(Deno.args[0])).mtime.getTime())' $argv + # stat -f "%Sm" -t "%s" $argv case "*" - stat -c "%Y" $argv + stat -c "%.Y" $argv end end diff --git a/install/hook.sh b/install/hook.sh index 2038bde..f943e46 100644 --- a/install/hook.sh +++ b/install/hook.sh @@ -7,7 +7,9 @@ __ghjk_get_mtime_ts () { stat -c "%Y" "$1" ;; "darwin") - stat -f "%Sm" -t "%s" "$1" + # darwin stat doesn't support ms since epoch so we bring out the big guns + deno eval 'console.log((await Deno.stat(Deno.args[0])).mtime.getTime())' "$1" + # stat -f "%Sm" -t "%s" "$1" ;; "*") stat -c "%Y" "$1" diff --git a/tests/utils.ts b/tests/utils.ts index 1171a8d..91d434d 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -66,8 +66,9 @@ exec ${ghjkExePath.resolve().toString()} "$@"`, HOME: tmpDir.toString(), GHJK_REPO_ROOT: import.meta.resolve("../"), // share the system's deno cache - GHJK_DENO_DIR: Deno.env.get("DENO_DIR") ?? - $.path(Deno.env.get("HOME")!).join(".cache", "deno").toString(), + GHJK_DENO_DIR: Deno.env.get("DENO_DIR") + ? $.path(Deno.env.get("DENO_DIR")!).resolve().toString() + : $.path(Deno.env.get("HOME")!).resolve(".cache", "deno").toString(), RUST_LOG: Deno.env.get("RUST_LOG"), GHJK_LOG: Deno.env.get("GHJK_LOG"), ...testEnvs, From 901487f1a1e7c77de2f35ceda413261217fcd9cd Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 16:26:11 +0300 Subject: [PATCH 14/15] fix: nightly jobs --- .github/workflows/nightly.yml | 74 +++++++++++++++++------------------ 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0380726..c4fac1b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,3 +1,4 @@ +name: nightly jobs on: schedule: - cron: "0 2 * * *" @@ -5,67 +6,62 @@ on: env: DENO_VERSION: "2.1.2" - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GHJK_LOG: debug GHJK_LOG_PANIC_LEVEL: error DENO_DIR: .deno-dir - DOCKER_NO_RMI: 1 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: test-e2e: + timeout-minutes: 60 runs-on: "${{ matrix.os }}" strategy: fail-fast: false matrix: include: - os: ubuntu-latest - e2eType: "local" + platform: linux/x86_64 + - os: custom-arm + platform: linux/aarch64 - os: macos-latest - e2eType: "local" + platform: darwin/x86_64 - os: macos-14 - e2eType: "local" + platform: darwin/aarch64 # - os: windows-latest - # e2eType: "local" - env: - GHJK_TEST_E2E_TYPE: ${{ matrix.e2eType }} steps: - uses: actions/checkout@v4 + - uses: dsherret/rust-toolchain-file@v1 - uses: denoland/setup-deno@v1 with: deno-version: ${{ env.DENO_VERSION }} - - if: "${{ matrix.os == 'ubuntu-latest' || matrix.os == 'custom-arm' }}" - run: | - # we need coreutils on max for the `timeout` command - sudo apt update - sudo apt install -y --no-install-recommends fish zsh - - if: "${{ matrix.os == 'macos-latest' || matrix.os == 'macos-14' }}" - # we need coreutils on max for the `timeout` command - run: brew install fish zsh coreutils - name: Cache deno dir - if: "${{ matrix.os == 'macos-latest' || matrix.os == 'macos-14' }}" uses: actions/cache@v4 with: path: ${{ env.DENO_DIR }} - key: deno-mac-${{ hashFiles('**/deno.lock') }} - - - if: "${{ matrix.e2eType == 'docker' }}" - uses: docker/setup-buildx-action@v3 - - if: "${{ matrix.e2eType == 'docker' }}" - uses: actions-hub/docker/cli@master - env: - SKIP_LOGIN: true - + key: deno-${{ hashFiles('**/deno.lock') }} + - if: "${{ matrix.os == 'ubuntu-latest' || matrix.os == 'custom-arm' }}" + # need coreutils on max for the `timeout` command + # need cmake to build the rust deps + run: | + sudo apt update + sudo apt install -y --no-install-recommends fish zsh cmake + - if: "${{ matrix.os == 'macos-latest' || matrix.os == 'macos-14' }}" + # need cmake to build the rust deps + # need coreutils on max for the `timeout` command + run: brew install fish zsh coreutils cmake - run: deno task test - test-action: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: metatypedev/setup-ghjk@318209a9d215f70716a4ac89dbeb9653a2deb8bc - with: - installer-url: ./install.ts - env: - GHJKFILE: ./examples/protoc/ghjk.ts - - run: | - cd examples/tasks - . $(ghjk print share-dir-path)/env.sh - ghjk x hey + + # test-action: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - uses: metatypedev/setup-ghjk@318209a9d215f70716a4ac89dbeb9653a2deb8bc + # with: + # installer-url: ./install.ts + # env: + # GHJKFILE: ./examples/protoc/ghjk.ts + # - run: | + # cd examples/tasks + # . $(ghjk print share-dir-path)/env.sh + # ghjk x hey From 6827827938aa0c349b3e717de2705e8e3ce18c63 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 1 Jan 2025 16:45:41 +0300 Subject: [PATCH 15/15] fix: formatting --- .github/workflows/nightly.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index c4fac1b..7d50999 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -51,7 +51,6 @@ jobs: run: brew install fish zsh coreutils cmake - run: deno task test - # test-action: # runs-on: ubuntu-latest # steps: