diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1b80771 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,309 @@ +name: CI +env: + DEBUG: napi:* + APP_NAME: bum + MACOSX_DEPLOYMENT_TARGET: "10.13" +permissions: + contents: write + id-token: write +"on": + push: + branches: + - main + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + pull_request: + paths-ignore: + - "**/*.md" + - LICENSE + - "**/*.gitignore" + - .editorconfig + - docs/** + pull_request: null +jobs: + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + - name: Cache cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: test-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Run tests + run: cargo test --lib + - name: Run clippy + run: cargo clippy -- -D warnings + - name: Check formatting + run: cargo fmt --check + + build: + needs: test + strategy: + fail-fast: false + matrix: + settings: + - host: macos-13 + target: x86_64-apple-darwin + build: | + bun run build:napi --target x86_64-apple-darwin + bun run build:bin + strip -x *.node + - host: windows-latest + build: bun run build + target: x86_64-pc-windows-msvc + - host: macos-latest + target: aarch64-apple-darwin + build: | + bun run build:napi --target aarch64-apple-darwin + bun run build:bin + strip -x *.node + - host: ubuntu-latest + target: x86_64-unknown-linux-gnu + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian + build: |- + set -e && + corepack enable && + npm install -g bun && + bun install && + bun run build:napi --target x86_64-unknown-linux-gnu && + bun run build:bin && + strip *.node + - host: ubuntu-latest + target: x86_64-unknown-linux-musl + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine + build: |- + set -e && + corepack enable && + npm install -g bun && + bun install && + bun run build && + strip *.node + - host: ubuntu-latest + target: aarch64-unknown-linux-gnu + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64 + build: |- + set -e && + corepack enable && + npm install -g bun && + bun install && + bun run build:napi --target aarch64-unknown-linux-gnu && + bun run build:bin && + aarch64-unknown-linux-gnu-strip *.node + - host: ubuntu-latest + target: aarch64-unknown-linux-musl + docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine + build: |- + set -e && + rustup target add aarch64-unknown-linux-musl && + corepack enable && + npm install -g bun && + bun install && + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc CC_aarch64_unknown_linux_musl=/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc bun run build:napi --target aarch64-unknown-linux-musl && + bun run build:bin && + /aarch64-linux-musl-cross/bin/aarch64-linux-musl-strip *.node + name: stable - ${{ matrix.settings.target }} - node@22 + runs-on: ${{ matrix.settings.host }} + steps: + - uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + if: ${{ !matrix.settings.docker }} + with: + node-version: 22 + - name: Install Bum (Unix) + if: ${{ !matrix.settings.docker && runner.os != 'Windows' }} + run: | + curl -fsSL https://github.com/owenizedd/bum/raw/main/install.sh | bash + echo "$HOME/.bum/bin" >> $GITHUB_PATH + echo "$HOME/.bun/bin" >> $GITHUB_PATH + shell: bash + - name: Setup Bun (Windows - fallback to official installer) + if: ${{ !matrix.settings.docker && runner.os == 'Windows' }} + uses: oven-sh/setup-bun@v2 + with: + bun-version: "1.3.0" + - name: Use Bun via Bum (Unix) + if: ${{ !matrix.settings.docker && runner.os != 'Windows' }} + run: | + export PATH="$HOME/.bum/bin:$PATH" + bum use 1.3.0 + shell: bash + - name: Install + uses: dtolnay/rust-toolchain@stable + if: ${{ !matrix.settings.docker }} + with: + toolchain: stable + targets: ${{ matrix.settings.target }} + - name: Cache cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + .cargo-cache + target/ + key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }} + - uses: goto-bus-stop/setup-zig@v2 + if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' }} + with: + version: 0.11.0 + - name: Setup toolchain + run: ${{ matrix.settings.setup }} + if: ${{ matrix.settings.setup }} + shell: bash + - name: Setup node x86 + if: matrix.settings.target == 'i686-pc-windows-msvc' + run: bun config set supportedArchitectures.cpu "ia32" + shell: bash + - name: Setup node x86 architecture + uses: actions/setup-node@v4 + if: matrix.settings.target == 'i686-pc-windows-msvc' + with: + node-version: 22 + architecture: x86 + - name: Install dependencies + run: bun install + if: ${{ !matrix.settings.docker }} + - name: Build in docker + uses: addnab/docker-run-action@v3 + if: ${{ matrix.settings.docker }} + with: + image: ${{ matrix.settings.docker }} + options: "--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build" + run: ${{ matrix.settings.build }} + - name: Build + run: ${{ matrix.settings.build }} + if: ${{ !matrix.settings.docker }} + shell: bash + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: bindings-${{ matrix.settings.target }} + path: ${{ env.APP_NAME }}.*.node + if-no-files-found: error + + universal-macOS: + name: Build universal macOS binary + needs: + - build + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 22 + - name: Install Bum + run: | + curl -fsSL https://github.com/owenizedd/bum/raw/main/install.sh | bash + echo "$HOME/.bum/bin" >> $GITHUB_PATH + echo "$HOME/.bun/bin" >> $GITHUB_PATH + shell: bash + - name: Use Bun via Bum + run: | + export PATH="$HOME/.bum/bin:$PATH" + bum use 1.3.0 + shell: bash + - name: Install dependencies + run: bun install + - name: Download macOS x64 artifact + uses: actions/download-artifact@v4 + with: + name: bindings-x86_64-apple-darwin + path: artifacts + - name: Download macOS arm64 artifact + uses: actions/download-artifact@v4 + with: + name: bindings-aarch64-apple-darwin + path: artifacts + - name: List downloaded files + run: | + echo "Current directory: $(pwd)" + ls -la artifacts/ + - name: Move artifacts to root + run: | + mv artifacts/*.node . + ls -la *.node + - name: Clean up hashed files + run: | + echo "Removing hashed files..." + rm -f bum.darwin-*-*.node + echo "Files after cleanup:" + ls -la *.node + - name: Combine binaries + run: | + bun run universal + ls -la *.node + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: bindings-universal-apple-darwin + path: ${{ env.APP_NAME }}.*.node + if-no-files-found: error + + publish: + name: Publish + runs-on: ubuntu-latest + needs: + - build + - universal-macOS + steps: + - uses: actions/checkout@v4 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: 22 + - name: Install Bum + run: | + curl -fsSL https://github.com/owenizedd/bum/raw/main/install.sh | bash + echo "$HOME/.bum/bin" >> $GITHUB_PATH + echo "$HOME/.bun/bin" >> $GITHUB_PATH + shell: bash + - name: Use Bun via Bum + run: | + export PATH="$HOME/.bum/bin:$PATH" + bum use 1.3.0 + shell: bash + - name: Install dependencies + run: bun install + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + - name: Clean up hashed files + run: | + echo "Removing hashed .node files..." + find artifacts -name "*.node" -name "*-*-*.node" -type f -delete + echo "Remaining files:" + find artifacts -name "*.node" -type f + - name: Move artifacts + run: bun run artifacts + - name: List packages + run: ls -R ./npm + shell: bash + - name: Publish + run: | + npm config set provenance true + if git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+$"; + then + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + npm publish --access public + elif git log -1 --pretty=%B | grep "^[0-9]\+\.[0-9]\+\.[0-9]\+"; + then + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + npm publish --tag next --access public + else + echo "Not a release, skipping publish" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index 0592392..2b7370f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,11 @@ /target .DS_Store + +# napi-rs +*.node +node_modules +.cargo-cache +dist + +# Generated from bin.ts +bin.js diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..7b07757 --- /dev/null +++ b/.npmignore @@ -0,0 +1,12 @@ +node_modules +*.node +target +.cargo-cache +dist +npm +*.log + +# Source files (ship compiled versions only) +bin.ts +tsconfig.json + diff --git a/Cargo.lock b/Cargo.lock index 14c72ad..b853401 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -18,14 +18,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "aes" -version = "0.8.4" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", + "memchr", ] [[package]] @@ -119,40 +117,29 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -[[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 = "bum" -version = "0.6.1" +version = "0.7.0" dependencies = [ "anyhow", "clap", + "futures", "lazy_static", - "openssl", + "napi", + "napi-build", + "napi-derive", "owo-colors", "reqwest", "resolve-path", "serde", "serde_json", + "tempfile", "tokio", "zip", ] @@ -163,49 +150,17 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[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 = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - [[package]] name = "cc" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" -dependencies = [ - "jobserver", - "libc", - "once_cell", -] [[package]] name = "cfg-if" @@ -213,16 +168,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[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 = "clap" version = "4.5.4" @@ -263,15 +208,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.1" @@ -279,51 +215,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[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 = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" +name = "convert_case" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" dependencies = [ - "crc-catalog", + "unicode-segmentation", ] -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - [[package]] name = "crc32fast" version = "1.4.0" @@ -340,28 +239,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] -name = "crypto-common" -version = "0.1.6" +name = "ctor" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "deflate64" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d" - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", + "quote", + "syn", ] [[package]] @@ -375,17 +259,6 @@ dependencies = [ "syn", ] -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - [[package]] name = "dirs" version = "4.0.0" @@ -417,15 +290,6 @@ dependencies = [ "syn", ] -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -455,7 +319,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", - "libz-ng-sys", "miniz_oxide", ] @@ -466,76 +329,101 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foreign-types" -version = "0.3.2" +name = "form_urlencoded" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "foreign-types-shared", + "percent-encoding", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "futures" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] [[package]] -name = "form_urlencoded" -version = "1.2.1" +name = "futures-channel" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ - "percent-encoding", + "futures-core", + "futures-sink", ] [[package]] -name = "futures-channel" -version = "0.3.30" +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", + "futures-task", + "futures-util", ] [[package]] -name = "futures-core" -version = "0.3.30" +name = "futures-io" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", + "slab", ] [[package]] @@ -555,25 +443,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "h2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -592,15 +461,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - [[package]] name = "http" version = "1.1.0" @@ -650,7 +510,6 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", "http", "http-body", "httparse", @@ -662,18 +521,19 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "hyper-rustls" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ - "bytes", - "http-body-util", + "futures-util", + "http", "hyper", "hyper-util", - "native-tls", + "rustls", + "rustls-pki-types", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", ] @@ -717,15 +577,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -744,15 +595,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[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" @@ -775,22 +617,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" [[package]] -name = "libredox" -version = "0.1.3" +name = "libloading" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ - "bitflags 2.5.0", - "libc", + "cfg-if", + "windows-link", ] [[package]] -name = "libz-ng-sys" -version = "1.1.15" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6409efc61b12687963e602df8ecf70e8ddacf95bc6576bcf16e3ac6328083c5" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "cmake", + "bitflags", "libc", ] @@ -816,16 +658,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - [[package]] name = "memchr" version = "2.7.2" @@ -859,28 +691,61 @@ dependencies = [ ] [[package]] -name = "native-tls" -version = "0.2.11" +name = "napi" +version = "2.16.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3" dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "bitflags", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", ] [[package]] -name = "num-conv" -version = "0.1.0" +name = "napi-build" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a" + +[[package]] +name = "napi-derive" +version = "2.16.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" +dependencies = [ + "cfg-if", + "convert_case", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" +dependencies = [ + "convert_case", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver", + "syn", +] + +[[package]] +name = "napi-sys" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3" +dependencies = [ + "libloading", +] [[package]] name = "num_cpus" @@ -928,60 +793,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "300.2.3+3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - [[package]] name = "owo-colors" version = "4.0.0" @@ -1011,16 +822,6 @@ dependencies = [ "windows-targets 0.52.5", ] -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest", - "hmac", -] - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1059,18 +860,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -1104,7 +893,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 2.5.0", + "bitflags", ] [[package]] @@ -1118,6 +907,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "reqwest" version = "0.12.4" @@ -1126,37 +944,36 @@ checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2", "http", "http-body", "http-body-util", "hyper", - "hyper-tls", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] @@ -1169,6 +986,21 @@ dependencies = [ "dirs", ] +[[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 = "rustc-demangle" version = "0.1.23" @@ -1181,13 +1013,27 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -1205,19 +1051,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" [[package]] -name = "ryu" -version = "1.0.17" +name = "rustls-webpki" +version = "0.102.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] [[package]] -name = "schannel" -version = "0.1.23" +name = "ryu" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "scopeguard" @@ -1226,27 +1074,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "security-framework" -version = "2.11.0" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.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", -] +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" @@ -1291,17 +1122,6 @@ dependencies = [ "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 = "signal-hook-registry" version = "1.4.2" @@ -1311,12 +1131,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - [[package]] name = "slab" version = "0.4.9" @@ -1342,6 +1156,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "strsim" version = "0.11.1" @@ -1371,27 +1191,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -1424,25 +1223,6 @@ dependencies = [ "syn", ] -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "num-conv", - "powerfmt", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - [[package]] name = "tinyvec" version = "1.6.0" @@ -1489,25 +1269,13 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" +name = "tokio-rustls" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", + "rustls", + "rustls-pki-types", "tokio", ] @@ -1582,18 +1350,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[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 = "unicode-bidi" version = "0.3.15" @@ -1615,6 +1371,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -1632,18 +1400,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[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 = "want" version = "0.3.1" @@ -1735,6 +1491,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1757,6 +1522,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.48.0" @@ -1915,69 +1686,24 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + [[package]] name = "zip" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" dependencies = [ - "aes", "arbitrary", - "bzip2", - "constant_time_eq", "crc32fast", "crossbeam-utils", - "deflate64", "displaydoc", "flate2", - "hmac", "indexmap", - "lzma-rs", "num_enum", - "pbkdf2", - "sha1", "thiserror", - "time", - "zopfli", - "zstd", -] - -[[package]] -name = "zopfli" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1f48f3508a3a3f2faee01629564400bc12260f6214a056d06a3aaaa6ef0736" -dependencies = [ - "crc32fast", - "log", - "simd-adler32", - "typed-arena", -] - -[[package]] -name = "zstd" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" -dependencies = [ - "cc", - "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index ba673b4..6be2261 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,29 @@ [package] name = "bum" -version = "0.6.1" +version = "0.7.0" edition = "2021" +[lib] +crate-type = ["cdylib", "rlib"] + +[[bin]] +name = "bum" +path = "src/main.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -reqwest = { version = "0.12", features = ["json"] } +napi = "2.16" +napi-derive = "2.16" +# Use rustls instead of native-tls to avoid OpenSSL cross-compilation issues +reqwest = { version = "0.12", default-features = false, features = [ + "json", + "rustls-tls", +] } clap = { version = "4.0", features = ["derive"] } tokio = { version = "1", features = ["full"] } -zip = "1.1" +# Disable default features to avoid libz-ng-sys which has cross-compilation issues +zip = { version = "1.1", default-features = false, features = ["deflate"] } owo-colors = "4.0" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } @@ -17,9 +31,9 @@ resolve-path = "0.1" lazy_static = "1.4" anyhow = "1.0" -[target.x86_64-unknown-linux-gnu.dependencies] -openssl = { version = "0.10.66", features = ["vendored"] } -[target.x86_64-unknown-linux-musl.dependencies] -openssl = { version = "0.10.66", features = ["vendored"] } -[target.aarch64-unknown-linux-gnu.dependencies] -openssl = { version = "0.10.66", features = ["vendored"] } +[dev-dependencies] +tempfile = "3.8" +futures = "0.3" + +[build-dependencies] +napi-build = "2.1.3" diff --git a/README.md b/README.md index 06b142a..5551a71 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,21 @@ Introducing Bum, a fast Bun version manager written in Rust from scratch. ## How to install: +### Via npm/npx (Recommended) + +The easiest way to use Bum is via npm: + +```bash +# Use without installation +npx @owenizedd/bum use 1.0.3 + +# Or install globally +npm install -g @owenizedd/bum +bum use 1.0.3 +``` + +### Via Script (Unix) + ## Unix 1. Open your terminal and execute: diff --git a/bin.ts b/bin.ts new file mode 100644 index 0000000..df8ba51 --- /dev/null +++ b/bin.ts @@ -0,0 +1,13 @@ +#!/usr/bin/env node + +const { run } = require("./index"); + +const args = process.argv.slice(2); + +try { + run(args); +} catch (e) { + console.error(e); + process.exit(1); +} + diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..0f1b010 --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + napi_build::setup(); +} diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..1e70af2 --- /dev/null +++ b/bun.lock @@ -0,0 +1,14 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "@rthionanda/bum", + "devDependencies": { + "@napi-rs/cli": "^2.18.4", + }, + }, + }, + "packages": { + "@napi-rs/cli": ["@napi-rs/cli@2.18.4", "", { "bin": { "napi": "scripts/index.js" } }, "sha512-SgJeA4df9DE2iAEpr3M2H0OKl/yjtg1BnRI5/JyowS71tUWhrfSu2LT0V3vlHET+g1hBVlrO60PmEXwUEKp8Mg=="], + } +} diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..50bdbdf --- /dev/null +++ b/index.d.ts @@ -0,0 +1,6 @@ +/* tslint:disable */ +/* eslint-disable */ + +/* auto-generated by NAPI-RS */ + +export declare function run(args: Array): void diff --git a/index.js b/index.js new file mode 100644 index 0000000..0f3744f --- /dev/null +++ b/index.js @@ -0,0 +1,315 @@ +/* tslint:disable */ +/* eslint-disable */ +/* prettier-ignore */ + +/* auto-generated by NAPI-RS */ + +const { existsSync, readFileSync } = require('fs') +const { join } = require('path') + +const { platform, arch } = process + +let nativeBinding = null +let localFileExisted = false +let loadError = null + +function isMusl() { + // For Node 10 + if (!process.report || typeof process.report.getReport !== 'function') { + try { + const lddPath = require('child_process').execSync('which ldd').toString().trim() + return readFileSync(lddPath, 'utf8').includes('musl') + } catch (e) { + return true + } + } else { + const { glibcVersionRuntime } = process.report.getReport().header + return !glibcVersionRuntime + } +} + +switch (platform) { + case 'android': + switch (arch) { + case 'arm64': + localFileExisted = existsSync(join(__dirname, 'bum.android-arm64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./bum.android-arm64.node') + } else { + nativeBinding = require('@owenizedd/bum-android-arm64') + } + } catch (e) { + loadError = e + } + break + case 'arm': + localFileExisted = existsSync(join(__dirname, 'bum.android-arm-eabi.node')) + try { + if (localFileExisted) { + nativeBinding = require('./bum.android-arm-eabi.node') + } else { + nativeBinding = require('@owenizedd/bum-android-arm-eabi') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Android ${arch}`) + } + break + case 'win32': + switch (arch) { + case 'x64': + localFileExisted = existsSync( + join(__dirname, 'bum.win32-x64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.win32-x64-msvc.node') + } else { + nativeBinding = require('@owenizedd/bum-win32-x64-msvc') + } + } catch (e) { + loadError = e + } + break + case 'ia32': + localFileExisted = existsSync( + join(__dirname, 'bum.win32-ia32-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.win32-ia32-msvc.node') + } else { + nativeBinding = require('@owenizedd/bum-win32-ia32-msvc') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'bum.win32-arm64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.win32-arm64-msvc.node') + } else { + nativeBinding = require('@owenizedd/bum-win32-arm64-msvc') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Windows: ${arch}`) + } + break + case 'darwin': + localFileExisted = existsSync(join(__dirname, 'bum.darwin-universal.node')) + try { + if (localFileExisted) { + nativeBinding = require('./bum.darwin-universal.node') + } else { + nativeBinding = require('@owenizedd/bum-darwin-universal') + } + break + } catch {} + switch (arch) { + case 'x64': + localFileExisted = existsSync(join(__dirname, 'bum.darwin-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./bum.darwin-x64.node') + } else { + nativeBinding = require('@owenizedd/bum-darwin-x64') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'bum.darwin-arm64.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.darwin-arm64.node') + } else { + nativeBinding = require('@owenizedd/bum-darwin-arm64') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on macOS: ${arch}`) + } + break + case 'freebsd': + if (arch !== 'x64') { + throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) + } + localFileExisted = existsSync(join(__dirname, 'bum.freebsd-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./bum.freebsd-x64.node') + } else { + nativeBinding = require('@owenizedd/bum-freebsd-x64') + } + } catch (e) { + loadError = e + } + break + case 'linux': + switch (arch) { + case 'x64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-x64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-x64-musl.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-x64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-x64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-x64-gnu.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-x64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-arm64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-arm64-musl.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-arm64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-arm64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-arm64-gnu.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-arm64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-arm-musleabihf.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-arm-musleabihf.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-arm-musleabihf') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-arm-gnueabihf.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-arm-gnueabihf.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-arm-gnueabihf') + } + } catch (e) { + loadError = e + } + } + break + case 'riscv64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-riscv64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-riscv64-musl.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-riscv64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'bum.linux-riscv64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-riscv64-gnu.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-riscv64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 's390x': + localFileExisted = existsSync( + join(__dirname, 'bum.linux-s390x-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./bum.linux-s390x-gnu.node') + } else { + nativeBinding = require('@owenizedd/bum-linux-s390x-gnu') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Linux: ${arch}`) + } + break + default: + throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) +} + +if (!nativeBinding) { + if (loadError) { + throw loadError + } + throw new Error(`Failed to load native binding`) +} + +const { run } = nativeBinding + +module.exports.run = run diff --git a/install.sh b/install.sh index 73c00c5..b7f544b 100755 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -VERSION="v0.6.1" +VERSION="v0.7.0" if ! bun &>/dev/null; then curl -fsSL https://bun.sh/install | bash diff --git a/npm/darwin-arm64/package.json b/npm/darwin-arm64/package.json new file mode 100644 index 0000000..a1957d7 --- /dev/null +++ b/npm/darwin-arm64/package.json @@ -0,0 +1,26 @@ +{ + "name": "@owenizedd/bum-darwin-arm64", + "version": "0.7.0", + "os": [ + "darwin" + ], + "cpu": [ + "arm64" + ], + "main": "bum.darwin-arm64.node", + "files": [ + "bum.darwin-arm64.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/darwin-universal/package.json b/npm/darwin-universal/package.json new file mode 100644 index 0000000..9c9051e --- /dev/null +++ b/npm/darwin-universal/package.json @@ -0,0 +1,23 @@ +{ + "name": "@owenizedd/bum-darwin-universal", + "version": "0.7.0", + "os": [ + "darwin" + ], + "main": "bum.darwin-universal.node", + "files": [ + "bum.darwin-universal.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/darwin-x64/package.json b/npm/darwin-x64/package.json new file mode 100644 index 0000000..92d9c72 --- /dev/null +++ b/npm/darwin-x64/package.json @@ -0,0 +1,26 @@ +{ + "name": "@owenizedd/bum-darwin-x64", + "version": "0.7.0", + "os": [ + "darwin" + ], + "cpu": [ + "x64" + ], + "main": "bum.darwin-x64.node", + "files": [ + "bum.darwin-x64.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/linux-arm64-gnu/package.json b/npm/linux-arm64-gnu/package.json new file mode 100644 index 0000000..d74b7f1 --- /dev/null +++ b/npm/linux-arm64-gnu/package.json @@ -0,0 +1,29 @@ +{ + "name": "@owenizedd/bum-linux-arm64-gnu", + "version": "0.7.0", + "os": [ + "linux" + ], + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "main": "bum.linux-arm64-gnu.node", + "files": [ + "bum.linux-arm64-gnu.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/linux-arm64-musl/package.json b/npm/linux-arm64-musl/package.json new file mode 100644 index 0000000..4433132 --- /dev/null +++ b/npm/linux-arm64-musl/package.json @@ -0,0 +1,29 @@ +{ + "name": "@owenizedd/bum-linux-arm64-musl", + "version": "0.7.0", + "os": [ + "linux" + ], + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "main": "bum.linux-arm64-musl.node", + "files": [ + "bum.linux-arm64-musl.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/linux-x64-gnu/package.json b/npm/linux-x64-gnu/package.json new file mode 100644 index 0000000..f19bdea --- /dev/null +++ b/npm/linux-x64-gnu/package.json @@ -0,0 +1,29 @@ +{ + "name": "@owenizedd/bum-linux-x64-gnu", + "version": "0.7.0", + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "main": "bum.linux-x64-gnu.node", + "files": [ + "bum.linux-x64-gnu.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/linux-x64-musl/package.json b/npm/linux-x64-musl/package.json new file mode 100644 index 0000000..76402b4 --- /dev/null +++ b/npm/linux-x64-musl/package.json @@ -0,0 +1,29 @@ +{ + "name": "@owenizedd/bum-linux-x64-musl", + "version": "0.7.0", + "os": [ + "linux" + ], + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "main": "bum.linux-x64-musl.node", + "files": [ + "bum.linux-x64-musl.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/npm/win32-x64-msvc/package.json b/npm/win32-x64-msvc/package.json new file mode 100644 index 0000000..a6e241f --- /dev/null +++ b/npm/win32-x64-msvc/package.json @@ -0,0 +1,26 @@ +{ + "name": "@owenizedd/bum-win32-x64-msvc", + "version": "0.7.0", + "os": [ + "win32" + ], + "cpu": [ + "x64" + ], + "main": "bum.win32-x64-msvc.node", + "files": [ + "bum.win32-x64-msvc.node" + ], + "description": "Fast Bun version manager written in Rust", + "keywords": [ + "bun", + "version-manager", + "rust", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..567bb39 --- /dev/null +++ b/package.json @@ -0,0 +1,62 @@ +{ + "name": "@owenizedd/bum", + "version": "0.7.0", + "description": "Fast Bun version manager written in Rust", + "main": "index.js", + "types": "index.d.ts", + "bin": "bin.js", + "repository": { + "type": "git", + "url": "git+https://github.com/owenizedd/bum.git" + }, + "keywords": [ + "bun", + "version-manager", + "rust", + "cli", + "napi-rs" + ], + "author": "owenizedd", + "license": "MIT", + "bugs": { + "url": "https://github.com/owenizedd/bum/issues" + }, + "homepage": "https://github.com/owenizedd/bum#readme", + "napi": { + "name": "bum", + "triples": { + "defaults": true, + "additional": [ + "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "aarch64-apple-darwin", + "x86_64-apple-darwin", + "universal-apple-darwin", + "x86_64-pc-windows-msvc" + ] + } + }, + "engines": { + "node": ">= 18" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" + }, + "scripts": { + "artifacts": "napi artifacts", + "build": "npm run build:napi && npm run build:bin", + "build:napi": "napi build --platform --release", + "build:bin": "bun build bin.ts --outdir . --target node --format cjs", + "build:debug": "napi build --platform && bun build bin.ts --outdir . --target node --format cjs", + "prepublishOnly": "napi prepublish -t npm", + "test": "echo \"No tests yet\"", + "universal": "napi universal -d .", + "version": "napi version" + }, + "packageManager": "bun@1.3.0", + "devDependencies": { + "@napi-rs/cli": "^2.18.4" + } +} diff --git a/src/commands.rs b/src/commands.rs index 4ece764..64daff5 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -18,7 +18,7 @@ lazy_static! { pub static ref BUN_BIN_PATH: Cow<'static, Path> = "~/.bun/bin/bun".resolve(); } -fn normalize_version(version: &str) -> String { +pub fn normalize_version(version: &str) -> String { version.replace('v', "") } @@ -187,3 +187,258 @@ pub async fn list_remote() { } } } + +#[cfg(test)] +mod tests { + use super::*; + use std::fs; + use std::path::PathBuf; + use tempfile::TempDir; + + // Test helper to create a temporary test environment + struct TestEnv { + _temp_dir: TempDir, + versions_dir: PathBuf, + bin_dir: PathBuf, + } + + impl TestEnv { + fn new() -> Self { + let temp_dir = TempDir::new().unwrap(); + let bum_dir = temp_dir.path().join(".bum"); + let versions_dir = bum_dir.join("bun-versions"); + let bin_dir = temp_dir.path().join(".bun").join("bin"); + + fs::create_dir_all(&versions_dir).unwrap(); + fs::create_dir_all(&bin_dir).unwrap(); + + TestEnv { + _temp_dir: temp_dir, + versions_dir, + bin_dir, + } + } + + fn create_mock_version(&self, version: &str) -> PathBuf { + let version_dir = self.versions_dir.join(version); + fs::create_dir_all(&version_dir).unwrap(); + + let bun_bin = version_dir.join(BUN_BIN_NAME); + fs::write(&bun_bin, format!("mock bun {}", version)).unwrap(); + + #[cfg(not(windows))] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = fs::metadata(&bun_bin).unwrap().permissions(); + perms.set_mode(0o755); + fs::set_permissions(&bun_bin, perms).unwrap(); + } + + version_dir + } + + fn version_exists(&self, version: &str) -> bool { + self.versions_dir.join(version).exists() + } + + fn bin_path(&self) -> PathBuf { + self.bin_dir.join("bun") + } + + fn read_active_bun(&self) -> Option { + fs::read_to_string(self.bin_path()).ok() + } + } + + #[test] + fn test_version_normalization() { + assert_eq!(normalize_version("v1.0.0"), "1.0.0"); + assert_eq!(normalize_version("1.0.0"), "1.0.0"); + assert_eq!(normalize_version("v1.2.3"), "1.2.3"); + assert_eq!(normalize_version("v2.0.0-beta"), "2.0.0-beta"); + } + + #[test] + fn test_create_version_directory() { + let env = TestEnv::new(); + + let version = "1.0.0"; + env.create_mock_version(version); + + assert!( + env.version_exists(version), + "Version directory should exist" + ); + } + + #[test] + fn test_multiple_versions_coexist() { + let env = TestEnv::new(); + + let versions = vec!["1.0.0", "1.1.0", "1.2.0"]; + for version in &versions { + env.create_mock_version(version); + } + + for version in &versions { + assert!( + env.version_exists(version), + "Version {} should exist", + version + ); + } + } + + #[tokio::test] + async fn test_activate_bun_copies_binary() { + let env = TestEnv::new(); + + let version = "1.0.0"; + let version_dir = env.create_mock_version(version); + let bun_source = version_dir.join(BUN_BIN_NAME); + + fs::copy(&bun_source, env.bin_path()).unwrap(); + + let active_content = env.read_active_bun().unwrap(); + assert_eq!( + active_content, + format!("mock bun {}", version), + "Active binary should match source" + ); + } + + #[tokio::test] + async fn test_remove_version() { + let env = TestEnv::new(); + + let version = "1.0.0"; + env.create_mock_version(version); + assert!( + env.version_exists(version), + "Version should exist before removal" + ); + + let version_path = env.versions_dir.join(version); + fs::remove_dir_all(&version_path).unwrap(); + + assert!( + !env.version_exists(version), + "Version should not exist after removal" + ); + } + + #[tokio::test] + async fn test_switch_between_versions() { + let env = TestEnv::new(); + + let v1 = "1.0.0"; + let v2 = "2.0.0"; + let v1_dir = env.create_mock_version(v1); + let v2_dir = env.create_mock_version(v2); + + // Activate v1 + let bun_v1 = v1_dir.join(BUN_BIN_NAME); + fs::copy(&bun_v1, env.bin_path()).unwrap(); + assert_eq!( + env.read_active_bun().unwrap(), + format!("mock bun {}", v1), + "Should activate v1" + ); + + // Switch to v2 + let bun_v2 = v2_dir.join(BUN_BIN_NAME); + fs::copy(&bun_v2, env.bin_path()).unwrap(); + assert_eq!( + env.read_active_bun().unwrap(), + format!("mock bun {}", v2), + "Should activate v2" + ); + } + + #[tokio::test] + async fn test_list_versions_sorted() { + let env = TestEnv::new(); + + let versions = vec!["1.2.0", "1.0.0", "1.1.0", "2.0.0"]; + for version in &versions { + env.create_mock_version(version); + } + + let mut found_versions = Vec::new(); + let entries = fs::read_dir(env.versions_dir).unwrap(); + for entry in entries { + let entry = entry.unwrap(); + let version = entry.file_name().to_string_lossy().to_string(); + found_versions.push(version); + } + + found_versions.sort(); + found_versions.reverse(); + + assert_eq!( + found_versions, + vec!["2.0.0", "1.2.0", "1.1.0", "1.0.0"], + "Versions should be sorted descending" + ); + } + + #[test] + fn test_version_with_special_characters() { + let env = TestEnv::new(); + + let versions = vec!["1.0.0-canary", "1.0.0-beta.1", "1.0.0+build"]; + + for version in &versions { + env.create_mock_version(version); + assert!( + env.version_exists(version), + "Special version {} should exist", + version + ); + } + } + + #[tokio::test] + async fn test_bumrc_file_format() { + let env = TestEnv::new(); + let bumrc_path = env._temp_dir.path().join(".bumrc"); + + // Test with newline + fs::write(&bumrc_path, "1.0.0\n").unwrap(); + let content = fs::read_to_string(&bumrc_path).unwrap(); + assert_eq!(content.trim(), "1.0.0"); + + // Test with v prefix + fs::write(&bumrc_path, "v1.0.0").unwrap(); + let content = fs::read_to_string(&bumrc_path).unwrap(); + assert_eq!(normalize_version(content.trim()), "1.0.0"); + } + + #[test] + fn test_version_persistence() { + let env = TestEnv::new(); + + let version = "1.0.0"; + let version_dir = env.create_mock_version(version); + let bun_source = version_dir.join(BUN_BIN_NAME); + + fs::copy(&bun_source, env.bin_path()).unwrap(); + + // Version dir still exists + assert!( + env.version_exists(version), + "Source version should persist after activation" + ); + + // Active binary exists + assert!(env.bin_path().exists(), "Active binary should exist"); + + // Content matches + let active = env.read_active_bun().unwrap(); + let original = fs::read_to_string(&bun_source).unwrap(); + assert_eq!( + active, original, + "Active binary content should match original" + ); + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0922ae5 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,143 @@ +#![allow(clippy::all, clippy::pedantic)] + +use anyhow::Result; +use clap::Parser; +use napi_derive::napi; + +pub mod bun; +pub mod commands; +mod os; +mod utils; + +use commands::{list, list_remote, remove, use_bumrc, use_bun}; +use owo_colors::{DynColors, OwoColorize}; + +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[derive(Parser)] +#[command(arg_required_else_help = true)] +pub struct Cli { + #[clap(short, long)] + version: bool, + + #[clap(subcommand)] + pub command: Option, +} + +#[derive(Parser)] +pub enum Command { + Default(DefaultCommand), + Use(UseCommand), + Remove(RemoveCommand), + List(ListCommand), + ListRemote(ListRemoteCommand), +} + +#[derive(Parser)] +pub struct DefaultCommand { + version: String, +} + +#[derive(Parser)] +pub struct UseCommand { + version: Option, +} + +#[derive(Parser)] +pub struct RemoveCommand { + version: String, +} + +#[derive(Parser)] +pub struct ListCommand {} +#[derive(Parser)] +pub struct ListRemoteCommand {} + +async fn run_commands(used_command: Option) -> Result<()> { + if used_command.is_none() { + println!("Use -h to print help"); + return Ok(()); + } + match used_command.unwrap() { + Command::Default(_args) => { + println!("This feature will be implemented in the future."); + } + Command::Remove(args) => { + remove(&args.version).await; + } + Command::Use(args) => match args.version { + Some(version) => { + use_bun(&version).await?; + } + None => { + use_bumrc().await?; + } + }, + Command::List(_) => list().await?, + Command::ListRemote(_) => { + list_remote().await; + } + } + + Ok(()) +} + +fn print_default_message() { + const BUM: &str = r#" _____ ____ ____ ______ _______ + ___|\ \ | | | | | \/ \ + | |\ \ | | | | / /\ \ + | | | || | | | / /\ / /\ | + | | /_ _ / | | | | / /\ \_/ / / /| + | |\ \ | | | || | \|_|/ / / | + | | | | | | | || | | | | + |____|/____/| |\___\_|____||\____\ |____| / + | / || | | | || | | | | / + |____|_____|/ \|____|____| \|____| |____|/ + \( )/ \( )/ \( )/ + ' ' ' ' ' ' "#; + + let colors: [DynColors; 3] = + ["#f6e0b5", "#aa6f73", "#eea990"].map(|color| color.parse().unwrap()); + + for line in BUM.split_inclusive('\n') { + print!("{}", line[0..16].to_string().color(colors[0])); + print!("{}", line[17..33].to_string().color(colors[1])); + print!("{}", line[34..54].to_string().color(colors[2])); + } + println!() +} + +#[napi] +pub fn run(args: Vec) -> napi::Result<()> { + // Create a new tokio runtime for this execution + let rt = tokio::runtime::Runtime::new() + .map_err(|e| napi::Error::from_reason(format!("Failed to create runtime: {}", e)))?; + + // Construct command line args like ["bum", "use", "1.0.3"] + let mut full_args = vec!["bum".to_string()]; + full_args.extend(args); + + let cli = Cli::try_parse_from(full_args); + + match cli { + Ok(result) => { + if result.version { + println!("{}", VERSION); + } else { + rt.block_on(async { + if let Err(e) = run_commands(result.command).await { + eprintln!("An error occurred during the execution: {e}"); + std::process::exit(1); + } + }); + } + } + Err(e) => { + print_default_message(); + eprintln!("{}", e); + std::process::exit(1); + } + } + + Ok(()) +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cea0473 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2020"], + "outDir": "./dist", + "rootDir": "./", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["bin.ts"], + "exclude": ["node_modules", "dist", "target"] +} + +