feat(core): add native node bindings for hashing (#14476)

Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
This commit is contained in:
Jonathan Cammisuli 2023-02-01 14:43:40 -05:00 committed by GitHub
parent 8614f3ac62
commit fecf7fb82f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 1731 additions and 62 deletions

12
.cargo/config.toml Normal file
View File

@ -0,0 +1,12 @@
[build]
target-dir = 'build/target'
[target.x86_64-unknown-linux-musl]
rustflags = [
"-C",
"target-feature=-crt-static",
]
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"
rustflags = ["-C", "target-feature=-crt-static"]

View File

@ -6,6 +6,7 @@ version: 2.1
orbs:
nx: nrwl/nx@1.6.1
node: circleci/node@5.0.2
rust: circleci/rust@1.6.0
browser-tools: circleci/browser-tools@1.4.0
# -------------------------
@ -38,7 +39,7 @@ executors:
linux:
<<: *defaults
docker:
- image: cimg/node:lts-browsers
- image: cimg/rust:1.66.1-browsers
resource_class: medium+
macos:
@ -224,6 +225,7 @@ jobs:
echo "export NX_RUN_GROUP=\"run-group-macos-$CIRCLE_WORKFLOW_ID\";" >> $BASH_ENV
- setup:
os: macos
- rust/install
- run:
name: Run E2E Tests for macOS
# FIXME: remove --exclude=e2e-detox once we have a fix for the detox tests

225
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,225 @@
name: publish
env:
DEBUG: napi:*
NX_RUN_GROUP: ${{ github.run_id }}-${{ github.run_attempt }}
on:
release:
types: [published]
jobs:
build:
if: "!contains(github.event.head_commit.message, 'skip ci')"
strategy:
fail-fast: false
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
build: |
yarn nx -- run-many --target=build-native -- --target=x86_64-apple-darwin
- host: windows-latest
build: yarn nx -- run-many --target=build-native -- --target=x86_64-pc-windows-msvc
target: x86_64-pc-windows-msvc
# Windows 32bit (not needed)
# - host: windows-latest
# build: |
# yarn nx -- run-many --target=build-native -- --target=i686-pc-windows-msvc
# target: i686-pc-windows-msvc
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
build: |-
set -e &&
yarn --version &&
yarn nx -- run-many --target=build-native -- --target=x86_64-unknown-linux-gnu
- host: ubuntu-latest
target: x86_64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: set -e && yarn nx -- run-many --target=build-native -- --target=x86_64-unknown-linux-musl
- host: macos-latest
target: aarch64-apple-darwin
build: |
sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
export CC=$(xcrun -f clang);
export CXX=$(xcrun -f clang++);
SYSROOT=$(xcrun --sdk macosx --show-sdk-path);
export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT";
yarn nx -- run-many --target=build-native -- --target=aarch64-apple-darwin
- host: ubuntu-latest
target: aarch64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: |-
set -e &&
yarn --version &&
yarn nx -- run-many --target=build-native -- --target=aarch64-unknown-linux-gnu
- host: ubuntu-latest
target: armv7-unknown-linux-gnueabihf
setup: |
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf -y
build: |
yarn nx -- run-many --target=build-native -- --target=armv7-unknown-linux-gnueabihf
# Android (not needed)
# - host: ubuntu-latest
# target: aarch64-linux-android
# build: |
# yarn nx -- run-many --target=build-native -- --target=aarch64-linux-android
# - host: ubuntu-latest
# target: armv7-linux-androideabi
# build: |
# yarn nx -- run-many --target=build-native -- --target=armv7-linux-androideabi
- 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 &&
yarn nx -- run-many --target=build-native -- --target=aarch64-unknown-linux-musl
- host: windows-latest
target: aarch64-pc-windows-msvc
build: yarn nx -- run-many --target=build-native -- --target=aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@18
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
if: ${{ !matrix.settings.docker }}
with:
node-version: 18
check-latest: true
cache: yarn
- name: Install
uses: dtolnay/rust-toolchain@stable
if: ${{ !matrix.settings.docker }}
with:
targets: ${{ matrix.settings.target }}
- name: Cache cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
.cargo-cache
target/
key: ${{ matrix.settings.target }}-cargo-registry
- uses: goto-bus-stop/setup-zig@v2
if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' }}
with:
version: 0.10.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: yarn config set supportedArchitectures.cpu "ia32"
shell: bash
- name: Install dependencies
run: yarn install
timeout-minutes: 30
- name: Setup node x86
uses: actions/setup-node@v3
if: matrix.settings.target == 'i686-pc-windows-msvc'
with:
node-version: 18
check-latest: true
cache: yarn
architecture: x86
- 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@v3
with:
name: bindings-${{ matrix.settings.target }}
path: packages/**/*.node
if-no-files-found: error
# build-freebsd:
# runs-on: macos-12
# name: Build FreeBSD
# steps:
# - uses: actions/checkout@v3
# - name: Build
# id: build
# uses: vmactions/freebsd-vm@v0
# env:
# DEBUG: napi:*
# RUSTUP_HOME: /usr/local/rustup
# CARGO_HOME: /usr/local/cargo
# RUSTUP_IO_THREADS: 1
# with:
# envs: DEBUG RUSTUP_HOME CARGO_HOME RUSTUP_IO_THREADS
# usesh: true
# mem: 3000
# prepare: |
# pkg install -y -f curl node libnghttp2
# curl -qL https://www.npmjs.com/install.sh | sh
# npm install --location=global --ignore-scripts yarn
# curl https://sh.rustup.rs -sSf --output rustup.sh
# sh rustup.sh -y --profile minimal --default-toolchain stable
# export PATH="/usr/local/cargo/bin:$PATH"
# echo "~~~~ rustc --version ~~~~"
# rustc --version
# echo "~~~~ node -v ~~~~"
# node -v
# echo "~~~~ yarn --version ~~~~"
# yarn --version
# run: |
# export PATH="/usr/local/cargo/bin:$PATH"
# pwd
# ls -lah
# whoami
# env
# freebsd-version
# yarn install
# yarn nx -- run-many --target=build-native -- --target=x86_64-unknown-freebsd
# strip -x packages/*/*.node
# rm -rf node_modules
# rm -rf target
# rm -rf .yarn/cache
# - name: Upload artifact
# uses: actions/upload-artifact@v3
# with:
# name: bindings-freebsd
# path: packages/*/*.node
# if-no-files-found: error
publish:
name: Publish
runs-on: ubuntu-latest
needs:
# - build-freebsd
- build
steps:
- uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 18
check-latest: true
cache: yarn
- name: Install dependencies
run: yarn install
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: artifacts
- name: List artifacts
run: ls -R artifacts
shell: bash
- name: Publish
run: |
git checkout -b publish/$GITHUB_REF_NAME
npm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN
yarn nx-release --local=false $GITHUB_REF_NAME
env:
GH_TOKEN: ${{ github.token }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

2
.gitignore vendored
View File

@ -27,3 +27,5 @@ CHANGELOG.md
# Local dev files
.env
*.node

View File

@ -14,6 +14,7 @@ packages/react/src/schematics/**/files/**/*.json
packages/jest/src/schematics/**/files/**/*.json
packages/**/schematics/**/files/**/*.html
packages/**/generators/**/files/**/*.html
packages/nx/src/native/
nx-dev/nx-dev/.next/
nx-dev/nx-dev/public/documentation
graph/client/src/assets/environment.js

View File

@ -37,6 +37,8 @@ Source code and documentation are included in the top-level folders listed below
## Building the Project
> Nx uses Rust to build native bindings for Node. Please make sure that you have Rust installed via [rustup.rs](https://rustup.rs)
After cloning the project to your machine, to install the dependencies, run:
```bash

484
Cargo.lock generated Normal file
View File

@ -0,0 +1,484 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "assert_fs"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d94b2a3f3786ff2996a98afbd6b4e5b7e890d685ccf67577f508ee2342c71cc9"
dependencies = [
"doc-comment",
"globwalk",
"predicates",
"predicates-core",
"predicates-tree",
"tempfile",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "convert_case"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]]
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "fastrand"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "globset"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags",
"ignore",
"walkdir",
]
[[package]]
name = "ignore"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a05705bc64e0b66a806c3740bd6578ea66051b157ec42dc219c785cbf185aef3"
dependencies = [
"globset",
"lazy_static",
"log",
"memchr",
"regex",
"same-file",
"thread_local",
"walkdir",
"winapi-util",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[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 = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "napi"
version = "2.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "838b5b414a008e75b97edb3c3e6f189034af789a0608686299b149d3b0e66c39"
dependencies = [
"bitflags",
"ctor",
"napi-sys",
"once_cell",
"thread_local",
]
[[package]]
name = "napi-build"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e"
[[package]]
name = "napi-derive"
version = "2.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af4e44e34e70aa61be9036ae652e27c20db5bca80e006be0f482419f6601352a"
dependencies = [
"convert_case",
"napi-derive-backend",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "napi-derive-backend"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17925fff04b6fa636f8e4b4608cc1a4f1360b64ac8ecbfdb7da1be1dc74f6843"
dependencies = [
"convert_case",
"once_cell",
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "napi-sys"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "529671ebfae679f2ce9630b62dd53c72c56b3eb8b2c852e7e2fa91704ff93d67"
dependencies = [
"libloading",
]
[[package]]
name = "nx"
version = "0.1.0"
dependencies = [
"assert_fs",
"crossbeam-channel",
"ignore",
"napi",
"napi-build",
"napi-derive",
"xxhash-rust",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "predicates"
version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
dependencies = [
"difflib",
"itertools",
"predicates-core",
]
[[package]]
name = "predicates-core"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2"
[[package]]
name = "predicates-tree"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[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 = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termtree"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
[[package]]
name = "thread_local"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[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 = "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.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[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 = "xxhash-rust"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "735a71d46c4d68d71d4b24d03fdc2b98e38cea81730595801db779c04fe80d70"

6
Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[workspace]
members = ['packages/nx']
[profile.release]
lto = true

View File

@ -1,10 +1,6 @@
{
"packages": ["build/packages/*"],
"packages": ["build/packages/*", "build/packages/nx/native-packages/*"],
"version": "15.7.0-beta.0",
"granularPathspec": false,
"command": {
"publish": {
"graphType": "all"
}
}
"command": { "publish": { "graphType": "all" } }
}

26
nx.json
View File

@ -13,8 +13,10 @@
"lint-base",
"lint",
"build-base",
"build-native",
"e2e",
"test",
"test-native",
"sitemap",
"build-storybook"
],
@ -39,15 +41,25 @@
"!{projectRoot}/.storybook/**/*",
"!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)"
],
"sharedGlobals": ["{workspaceRoot}/babel.config.json"]
"sharedGlobals": ["{workspaceRoot}/babel.config.json"],
"native": [
"{projectRoot}/**/*.rs",
"{projectRoot}/**/Cargo.*",
{
"runtime": "node -p 'process.platform'"
}
]
},
"targetDefaults": {
"build": {
"dependsOn": ["build-base"],
"inputs": ["production", "^production"]
},
"build-native": {
"inputs": ["native"]
},
"build-base": {
"dependsOn": ["^build-base"],
"dependsOn": ["^build-base", "build-native"],
"inputs": ["production", "^production"],
"executor": "@nrwl/js:tsc",
"options": {
@ -58,7 +70,13 @@
},
"outputs": ["{options.outputPath}"]
},
"test-native": {
"inputs": ["native"],
"executor": "@monodon/rust:test",
"options": {}
},
"test": {
"dependsOn": ["test-native", "build-native", "^build-native"],
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
"executor": "@nrwl/jest:jest",
"options": {
@ -68,6 +86,7 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"]
},
"lint": {
"dependsOn": ["build-native", "^build-native"],
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.json",
@ -164,5 +183,6 @@
"inputs": ["default", "^production", "{workspaceRoot}/.storybook/**/*"]
}
},
"defaultProject": "@nrwl/nx-source"
"defaultProject": "@nrwl/nx-source",
"plugins": ["@monodon/rust"]
}

View File

@ -22,7 +22,8 @@
"submit-plugin": "node ./scripts/submit-plugin.js",
"prepare": "is-ci || husky install",
"echo": "echo 123458",
"root-lint": "nx workspace-lint"
"root-lint": "nx workspace-lint",
"preinstall": "node ./scripts/preinstall.js"
},
"devDependencies": {
"@angular-devkit/architect": "~0.1501.0",
@ -44,6 +45,8 @@
"@babel/preset-typescript": "^7.15.0",
"@cypress/react": "^6.0.0",
"@floating-ui/react-dom": "^1.0.1",
"@monodon/rust": "0.4.4",
"@napi-rs/cli": "2.14.0",
"@nestjs/cli": "^9.0.0",
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0",

View File

@ -1,3 +1,5 @@
import 'nx/src/utils/testing/mock-fs';
import type { FileData, ProjectGraph } from '@nrwl/devkit';
import { DependencyType } from '@nrwl/devkit';
import * as parser from '@typescript-eslint/parser';
@ -9,8 +11,6 @@ import enforceModuleBoundaries, {
} from '../../src/rules/enforce-module-boundaries';
import { createProjectRootMappings } from 'nx/src/project-graph/utils/find-project-for-path';
jest.mock('fs', () => require('memfs').fs);
jest.mock('@nrwl/devkit', () => ({
...jest.requireActual<any>('@nrwl/devkit'),
workspaceRoot: '/root',

View File

@ -1,3 +1,5 @@
import 'nx/src/utils/testing/mock-fs';
import {
getUpdatedPackageJsonContent,
updatePackageJson,
@ -10,7 +12,6 @@ import { DependentBuildableProjectNode } from '@nrwl/workspace/src/utilities/bui
jest.mock('nx/src/utils/workspace-root', () => ({
workspaceRoot: '/root',
}));
jest.mock('fs', () => require('memfs').fs);
describe('getUpdatedPackageJsonContent', () => {
it('should update fields for commonjs only (default)', () => {

View File

@ -1,3 +1,4 @@
import 'nx/src/utils/testing/mock-fs';
import { createWebpackConfig, prepareConfig } from './config';
import { NextBuildBuilderOptions } from '@nrwl/next';
import { dirname } from 'path';
@ -15,7 +16,6 @@ jest.mock('next/dist/server/config', () => ({
webpack: () => ({}),
}),
}));
jest.mock('fs', () => require('memfs').fs);
describe('Next.js webpack config builder', () => {
beforeEach(() => {

2
packages/nx/.npmignore Normal file
View File

@ -0,0 +1,2 @@
native-packages/
/*.node

20
packages/nx/Cargo.toml Normal file
View File

@ -0,0 +1,20 @@
[package]
name = 'nx'
version = '0.1.0'
edition = '2021'
[dependencies]
xxhash-rust = { version = '0.8.5', features = ['xxh3', 'xxh64'] }
napi = { version = '2.10.2', default-features = false, features = ['napi4'] }
napi-derive = '2.9.3'
ignore = '0.4'
crossbeam-channel = '0.5'
[lib]
crate-type = ['cdylib']
[build-dependencies]
napi-build = '2.0.1'
[dev-dependencies]
assert_fs = "1.0.10"

5
packages/nx/build.rs Normal file
View File

@ -0,0 +1,5 @@
extern crate napi_build;
fn main() {
napi_build::setup();
}

View File

@ -0,0 +1,3 @@
# `nx-darwin-arm64`
This is the **aarch64-apple-darwin** binary for `@nrwl/nx`

View File

@ -0,0 +1,20 @@
{
"name": "@nrwl/nx-darwin-arm64",
"version": "0.0.0",
"os": [
"darwin"
],
"cpu": [
"arm64"
],
"main": "nx.darwin-arm64.node",
"files": [
"nx.darwin-arm64.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-darwin-x64`
This is the **x86_64-apple-darwin** binary for `@nrwl/nx`

View File

@ -0,0 +1,20 @@
{
"name": "@nrwl/nx-darwin-x64",
"version": "0.0.0",
"os": [
"darwin"
],
"cpu": [
"x64"
],
"main": "nx.darwin-x64.node",
"files": [
"nx.darwin-x64.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-linux-arm-gnueabihf`
This is the **armv7-unknown-linux-gnueabihf** binary for `@nrwl/nx`

View File

@ -0,0 +1,20 @@
{
"name": "@nrwl/nx-linux-arm-gnueabihf",
"version": "0.0.0",
"os": [
"linux"
],
"cpu": [
"arm"
],
"main": "nx.linux-arm-gnueabihf.node",
"files": [
"nx.linux-arm-gnueabihf.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-linux-arm64-gnu`
This is the **aarch64-unknown-linux-gnu** binary for `@nrwl/nx`

View File

@ -0,0 +1,23 @@
{
"name": "@nrwl/nx-linux-arm64-gnu",
"version": "0.0.0",
"os": [
"linux"
],
"cpu": [
"arm64"
],
"main": "nx.linux-arm64-gnu.node",
"files": [
"nx.linux-arm64-gnu.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
},
"libc": [
"glibc"
]
}

View File

@ -0,0 +1,3 @@
# `nx-linux-arm64-musl`
This is the **aarch64-unknown-linux-musl** binary for `@nrwl/nx`

View File

@ -0,0 +1,23 @@
{
"name": "@nrwl/nx-linux-arm64-musl",
"version": "0.0.0",
"os": [
"linux"
],
"cpu": [
"arm64"
],
"main": "nx.linux-arm64-musl.node",
"files": [
"nx.linux-arm64-musl.node"
],
"engines": {
"node": ">= 10"
},
"libc": [
"musl"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-linux-x64-gnu`
This is the **x86_64-unknown-linux-gnu** binary for `@nrwl/nx`

View File

@ -0,0 +1,23 @@
{
"name": "@nrwl/nx-linux-x64-gnu",
"version": "0.0.0",
"os": [
"linux"
],
"cpu": [
"x64"
],
"main": "nx.linux-x64-gnu.node",
"files": [
"nx.linux-x64-gnu.node"
],
"engines": {
"node": ">= 10"
},
"libc": [
"glibc"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-linux-x64-musl`
This is the **x86_64-unknown-linux-musl** binary for `@nrwl/nx`

View File

@ -0,0 +1,23 @@
{
"name": "@nrwl/nx-linux-x64-musl",
"version": "0.0.0",
"os": [
"linux"
],
"cpu": [
"x64"
],
"main": "nx.linux-x64-musl.node",
"files": [
"nx.linux-x64-musl.node"
],
"engines": {
"node": ">= 10"
},
"libc": [
"musl"
],
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-win32-arm64-msvc`
This is the **aarch64-pc-windows-msvc** binary for `@nrwl/nx`

View File

@ -0,0 +1,20 @@
{
"name": "@nrwl/nx-win32-arm64-msvc",
"version": "0.0.0",
"os": [
"win32"
],
"cpu": [
"arm64"
],
"main": "nx.win32-arm64-msvc.node",
"files": [
"nx.win32-arm64-msvc.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
# `nx-win32-x64-msvc`
This is the **x86_64-pc-windows-msvc** binary for `@nrwl/nx`

View File

@ -0,0 +1,20 @@
{
"name": "@nrwl/nx-win32-x64-msvc",
"version": "0.0.0",
"os": [
"win32"
],
"cpu": [
"x64"
],
"main": "nx.win32-x64-msvc.node",
"files": [
"nx.win32-x64-msvc.node"
],
"engines": {
"node": ">= 10"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -78,6 +78,17 @@
"optional": true
}
},
"optionalDependencies": {
"@nrwl/nx-win32-x64-msvc": "*",
"@nrwl/nx-darwin-x64": "*",
"@nrwl/nx-linux-x64-gnu": "*",
"@nrwl/nx-darwin-arm64": "*",
"@nrwl/nx-linux-arm64-gnu": "*",
"@nrwl/nx-linux-arm64-musl": "*",
"@nrwl/nx-win32-arm64-msvc": "*",
"@nrwl/nx-linux-arm-gnueabihf": "*",
"@nrwl/nx-linux-x64-musl": "*"
},
"nx-migrations": {
"migrations": "./migrations.json",
"packageGroup": [
@ -116,5 +127,21 @@
"builders": "./executors.json",
"publishConfig": {
"access": "public"
},
"napi": {
"name": "nx",
"package": {
"name": "@nrwl/nx"
},
"triples": {
"additional": [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"aarch64-pc-windows-msvc",
"armv7-unknown-linux-gnueabihf",
"x86_64-unknown-linux-musl"
]
}
}
}

View File

@ -5,11 +5,28 @@
"projectType": "library",
"implicitDependencies": ["graph-client"],
"targets": {
"build-native": {
"outputs": ["{projectRoot}/src/native/*.node"],
"executor": "@monodon/rust:napi",
"options": {
"dist": "packages/nx/src/native",
"jsFile": "packages/nx/src/native/index.js",
"release": true
}
},
"artifacts": {
"command": "yarn napi artifacts -c build/packages/nx/package.json -d ./artifacts --dist build/packages/nx/native-packages"
},
"build-base": {
"executor": "@nrwl/js:tsc",
"options": {
"main": "packages/nx/bin/nx.ts",
"assets": [
{
"input": "packages/nx",
"glob": ".npmignore",
"output": "/"
},
{
"input": "packages/nx",
"glob": "**/files/**",
@ -46,16 +63,16 @@
}
},
"echo": {
"executor": "nx:command",
"options": {
"command": "echo hi"
}
"command": "echo hi"
},
"build": {
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/build/packages/nx"],
"options": {
"commands": [
{
"command": "node ./scripts/copy-local-native.js nx"
},
{
"command": "node ./scripts/copy-graph-client.js"
},
@ -76,6 +93,7 @@
}
},
"lint": {},
"test": {}
"test": {},
"test-native": {}
}
}

View File

@ -5,6 +5,7 @@ import { FileHasherBase } from './file-hasher-base';
import { execSync } from 'child_process';
import { existsSync } from 'fs';
import { join } from 'path';
import { NativeFileHasher } from './native-file-hasher';
function createFileHasher(): FileHasherBase {
// special case for unit tests
@ -12,6 +13,10 @@ function createFileHasher(): FileHasherBase {
return new NodeBasedFileHasher();
}
try {
if (process.env.NX_NATIVE_HASHER) {
return new NativeFileHasher();
}
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
// we don't use git based hasher when the repo uses git submodules
if (!existsSync(join(workspaceRoot, '.git', 'modules'))) {

View File

@ -0,0 +1,34 @@
import { FileHasherBase } from './file-hasher-base';
import { performance } from 'perf_hooks';
import { hashFile, hashFiles } from '../native';
import { workspaceRoot } from '../utils/app-root';
export class NativeFileHasher extends FileHasherBase {
async init(): Promise<void> {
performance.mark('init hashing:start');
this.clear();
const filesObject = hashFiles(workspaceRoot);
this.fileHashes = new Map(Object.entries(filesObject));
performance.mark('init hashing:end');
performance.measure(
'init hashing',
'init hashing:start',
'init hashing:end'
);
}
async hashFiles(files: string[]): Promise<Map<string, string>> {
const r = new Map<string, string>();
for (let f of files) {
r.set(f, this.hashFile(f));
}
return r;
}
hashFile(path: string): string {
return hashFile(path).hash;
}
}

5
packages/nx/src/lib.rs Normal file
View File

@ -0,0 +1,5 @@
// add all the napi macros globally
#[macro_use]
extern crate napi_derive;
pub mod native;

11
packages/nx/src/native/index.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export interface FileData {
file: string
hash: string
}
export function hashFile(file: string): FileData | null
export function hashFiles(workspaceRoot: string): Record<string, string>

View File

@ -0,0 +1,252 @@
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, 'nx.android-arm64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./nx.android-arm64.node')
} else {
nativeBinding = require('@nrwl/nx-android-arm64')
}
} catch (e) {
loadError = e
}
break
case 'arm':
localFileExisted = existsSync(join(__dirname, 'nx.android-arm-eabi.node'))
try {
if (localFileExisted) {
nativeBinding = require('./nx.android-arm-eabi.node')
} else {
nativeBinding = require('@nrwl/nx-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, 'nx.win32-x64-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.win32-x64-msvc.node')
} else {
nativeBinding = require('@nrwl/nx-win32-x64-msvc')
}
} catch (e) {
loadError = e
}
break
case 'ia32':
localFileExisted = existsSync(
join(__dirname, 'nx.win32-ia32-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.win32-ia32-msvc.node')
} else {
nativeBinding = require('@nrwl/nx-win32-ia32-msvc')
}
} catch (e) {
loadError = e
}
break
case 'arm64':
localFileExisted = existsSync(
join(__dirname, 'nx.win32-arm64-msvc.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.win32-arm64-msvc.node')
} else {
nativeBinding = require('@nrwl/nx-win32-arm64-msvc')
}
} catch (e) {
loadError = e
}
break
default:
throw new Error(`Unsupported architecture on Windows: ${arch}`)
}
break
case 'darwin':
localFileExisted = existsSync(join(__dirname, 'nx.darwin-universal.node'))
try {
if (localFileExisted) {
nativeBinding = require('./nx.darwin-universal.node')
} else {
nativeBinding = require('@nrwl/nx-darwin-universal')
}
break
} catch {}
switch (arch) {
case 'x64':
localFileExisted = existsSync(join(__dirname, 'nx.darwin-x64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./nx.darwin-x64.node')
} else {
nativeBinding = require('@nrwl/nx-darwin-x64')
}
} catch (e) {
loadError = e
}
break
case 'arm64':
localFileExisted = existsSync(
join(__dirname, 'nx.darwin-arm64.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.darwin-arm64.node')
} else {
nativeBinding = require('@nrwl/nx-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, 'nx.freebsd-x64.node'))
try {
if (localFileExisted) {
nativeBinding = require('./nx.freebsd-x64.node')
} else {
nativeBinding = require('@nrwl/nx-freebsd-x64')
}
} catch (e) {
loadError = e
}
break
case 'linux':
switch (arch) {
case 'x64':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'nx.linux-x64-musl.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.linux-x64-musl.node')
} else {
nativeBinding = require('@nrwl/nx-linux-x64-musl')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'nx.linux-x64-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.linux-x64-gnu.node')
} else {
nativeBinding = require('@nrwl/nx-linux-x64-gnu')
}
} catch (e) {
loadError = e
}
}
break
case 'arm64':
if (isMusl()) {
localFileExisted = existsSync(
join(__dirname, 'nx.linux-arm64-musl.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.linux-arm64-musl.node')
} else {
nativeBinding = require('@nrwl/nx-linux-arm64-musl')
}
} catch (e) {
loadError = e
}
} else {
localFileExisted = existsSync(
join(__dirname, 'nx.linux-arm64-gnu.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.linux-arm64-gnu.node')
} else {
nativeBinding = require('@nrwl/nx-linux-arm64-gnu')
}
} catch (e) {
loadError = e
}
}
break
case 'arm':
localFileExisted = existsSync(
join(__dirname, 'nx.linux-arm-gnueabihf.node')
)
try {
if (localFileExisted) {
nativeBinding = require('./nx.linux-arm-gnueabihf.node')
} else {
nativeBinding = require('@nrwl/nx-linux-arm-gnueabihf')
}
} 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 { hashFile, hashFiles } = nativeBinding
module.exports.hashFile = hashFile
module.exports.hashFiles = hashFiles

View File

@ -0,0 +1 @@
pub mod native_hasher;

View File

@ -0,0 +1,167 @@
#![allow(unused)]
use crossbeam_channel::unbounded;
use ignore::WalkBuilder;
use std::collections::HashMap;
use std::thread::{self, available_parallelism};
use xxhash_rust::xxh3;
type FileHashes = HashMap<String, String>;
#[napi(object)]
pub struct FileData {
pub file: String,
pub hash: String,
}
#[napi]
fn hash_file(file: String) -> Option<FileData> {
let Ok(content) = std::fs::read(&file) else {
return None;
};
let hash = xxh3::xxh3_64(&content).to_string();
Some(FileData { hash, file })
}
#[napi]
fn hash_files(workspace_root: String) -> HashMap<String, String> {
let mut walker = WalkBuilder::new(&workspace_root);
let workspace_root = workspace_root + "/";
walker.add_ignore(workspace_root.clone() + ".nxignore");
let git_folder = workspace_root.clone() + ".git";
// We should make sure to always ignore node_modules
let node_folder = workspace_root.clone() + "node_modules";
walker.filter_entry(move |entry| {
!(entry.path().starts_with(&git_folder) || entry.path().starts_with(&node_folder))
});
// dot files are hidden by default. We want to make sure we include those here
walker.hidden(false);
let (sender, reciever) = unbounded::<(String, Vec<u8>)>();
let receiver_thread = thread::spawn(move || {
let mut collection: HashMap<String, String> = HashMap::new();
for (path, content) in reciever {
collection.insert(path, xxh3::xxh3_64(&content).to_string());
}
collection
});
let cpus = available_parallelism().map_or(2, |n| n.get()) - 1;
walker.threads(cpus).build_parallel().run(|| {
let tx = sender.clone();
let workspace_root = workspace_root.clone();
Box::new(move |entry| {
use ignore::WalkState::*;
#[rustfmt::skip]
let Ok(dir_entry) = entry else {
return Continue;
};
let Ok(content) = std::fs::read(dir_entry.path()) else {
return Continue;
};
let file_path = dir_entry.path().display().to_string();
let Some(file_path) = file_path.strip_prefix(&workspace_root) else {
return Continue;
};
tx.send((file_path.to_string(), content)).ok();
Continue
})
});
drop(sender);
receiver_thread.join().unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
use assert_fs::prelude::*;
use assert_fs::TempDir;
///
/// Setup a temporary directory to do testing in
///
fn setup_fs() -> TempDir {
let temp = TempDir::new().unwrap();
temp.child("test.txt").write_str("content").unwrap();
temp.child("foo.txt").write_str("content1").unwrap();
temp.child("bar.txt").write_str("content2").unwrap();
temp.child("baz")
.child("qux.txt")
.write_str("content@qux")
.unwrap();
temp.child("node_modules")
.child("node-module-dep")
.write_str("content")
.unwrap();
temp
}
#[test]
fn it_hashes_a_file() {
// handle non existent files
let content = hash_file("".into());
assert!(content.is_none());
let temp_dir = setup_fs();
let test_file_path = temp_dir.display().to_string() + "/test.txt";
let content = hash_file(test_file_path);
assert_eq!(content.unwrap().hash, "6193209363630369380");
}
#[test]
fn it_hashes_a_directory() {
// handle empty workspaces
let content = hash_files("/does/not/exist".into());
assert!(content.is_empty());
let temp_dir = setup_fs();
let content = hash_files(temp_dir.display().to_string());
// println!("{:?}", content);
assert_eq!(
content,
HashMap::from([
("baz/qux.txt".into(), "8039819779822413286".into()),
("foo.txt".into(), "8455857314690418558".into()),
("test.txt".into(), "6193209363630369380".into()),
("bar.txt".into(), "1707056588989152788".into()),
])
);
}
#[test]
fn handles_nx_ignore() {
let temp_dir = setup_fs();
// add nxignore file with baz/
temp_dir.child(".nxignore").write_str("baz/").unwrap();
let content = hash_files(temp_dir.display().to_string());
assert_eq!(
content,
HashMap::from([
("foo.txt".into(), "8455857314690418558".into()),
("test.txt".into(), "6193209363630369380".into()),
("bar.txt".into(), "1707056588989152788".into()),
(".nxignore".into(), "5786346484289078730".into())
])
);
}
}
//
//

View File

@ -0,0 +1,22 @@
import { hashFile } from '../index';
import { tmpdir } from 'os';
import { mkdtemp, writeFile } from 'fs-extra';
import { join } from 'path';
describe('native', () => {
it('should hash', async () => {
expect(hashFile).toBeDefined();
const tempDirPath = await mkdtemp(join(tmpdir(), 'native-test'));
const tempFilePath = join(tempDirPath, 'temp.txt');
await writeFile(tempFilePath, 'content');
expect(hashFile(tempFilePath).hash).toBe('6193209363630369380');
});
it('should create an instance of NativeHasher', () => {
// const nativeHasher = new NativeFileHasher('/root');
// expect(nativeHasher instanceof NativeFileHasher).toBe(true);
});
});

View File

@ -1,3 +1,4 @@
import '../../utils/testing/mock-fs';
import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies';
import { vol } from 'memfs';
import { createProjectFileMap } from '../file-map-utils';
@ -8,7 +9,6 @@ import {
} from '../../config/project-graph';
import { ProjectGraphBuilder } from '../project-graph-builder';
jest.mock('fs', () => require('memfs').fs);
jest.mock('nx/src/utils/workspace-root', () => ({
workspaceRoot: '/root',
}));

View File

@ -1,10 +1,10 @@
import '../../utils/testing/mock-fs';
import { vol } from 'memfs';
import { defaultFileHasher } from '../../hasher/file-hasher';
import { createProjectFileMap } from '../file-map-utils';
import { ProjectGraphBuilder } from '../project-graph-builder';
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
jest.mock('fs', () => require('memfs').fs);
jest.mock('nx/src/utils/workspace-root', () => ({
workspaceRoot: '/root',
}));

View File

@ -1,7 +1,8 @@
import '../utils/testing/mock-fs';
import { vol, fs } from 'memfs';
jest.mock('fs', () => require('memfs').fs);
jest.mock('../utils/workspace-root', () => ({
jest.mock('nx/src/utils/workspace-root', () => ({
workspaceRoot: '/root',
}));
import { buildProjectGraph } from './build-project-graph';

View File

@ -0,0 +1,14 @@
// @ts-ignore
jest.mock('fs', (): Partial<typeof import('fs')> => {
const mockFs = require('memfs').fs;
return {
...mockFs,
existsSync(path: string) {
if (path.endsWith('.node')) {
return true;
} else {
return mockFs.existsSync(path);
}
},
};
});

View File

@ -0,0 +1,11 @@
//@ts-check
const fs = require('fs');
const glob = require('fast-glob');
const p = process.argv[2];
const nativeFiles = glob.sync(`packages/${p}/**/*.node`);
nativeFiles.forEach((file) => {
fs.copyFileSync(file, `build/${file}`);
});

View File

@ -132,6 +132,21 @@ const IGNORE_MATCHES_IN_PACKAGE = {
'@nrwl/angular',
'@nestjs/cli', // nx init nest makes use of nestjs cli (which should be available in NestJS CLI app) to parse the nest-cli.json file
'ts-node', // We *may* fall back on ts-node, but we want to encourage the use of @swc-node instead so we don't explicitly list ts-node as an optional dep
'@nrwl/nx-android-arm-eabi', // native optional deps
'@nrwl/nx-android-arm64', // native optional deps
'@nrwl/nx-darwin-arm64', // native optional deps
'@nrwl/nx-darwin-universal', // native optional deps
'@nrwl/nx-darwin-x64', // native optional deps
'@nrwl/nx-freebsd-x64', // native optional deps
'@nrwl/nx-linux-arm-gnueabihf', // native optional deps
'@nrwl/nx-linux-arm64-gnu', // native optional deps
'@nrwl/nx-linux-arm64-musl', // native optional deps
'@nrwl/nx-linux-x64-gnu', // native optional deps
'@nrwl/nx-linux-x64-musl', // native optional deps
'@nrwl/nx-win32-arm64-msvc', // native optional deps
'@nrwl/nx-win32-ia32-msvc', // native optional deps
'@nrwl/nx-win32-x64-msvc', // native optional deps
'memfs', // used in mock for handling .node files in tests
],
web: [
// we don't want to bloat the install of @nrwl/web by including @swc/core and swc-loader as a dependency.

View File

@ -5,9 +5,14 @@ import { existsSync, readFileSync, writeFileSync } from 'fs';
import { URL } from 'url';
import { join } from 'path';
import { parse } from 'semver';
import * as version from '@lerna/version/index';
import * as publish from '@lerna/publish/index';
const lernaJsonPath = join(__dirname, '../lerna.json');
const originalLernaJson = readFileSync(lernaJsonPath);
function hideFromGitIndex(uncommittedFiles: string[]) {
execSync(`git update-index --assume-unchanged ${uncommittedFiles.join(' ')}`);
@ -19,23 +24,35 @@ function hideFromGitIndex(uncommittedFiles: string[]) {
(async () => {
const options = parseArgs();
if (!options.local && !options.force) {
console.log('Authenticating to NPM');
execSync('npm adduser', {
stdio: [0, 1, 2],
});
}
if (options.clearLocalRegistry) {
execSync('yarn local-registry clear');
}
const currentLatestVersion = execSync('npm view nx version')
.toString()
.trim();
const parsedVersion = parse(options.version);
const parsedCurrentLatestVersion = parse(currentLatestVersion);
const distTag =
parsedVersion?.prerelease.length > 0
? 'next'
: parsedVersion?.major < parsedCurrentLatestVersion.major
? 'previous'
: 'latest';
const buildCommand = 'yarn build';
console.log(`> ${buildCommand}`);
execSync(buildCommand, {
stdio: [0, 1, 2],
});
if (options.local) {
updateLernaJsonVersion(currentLatestVersion);
}
if (options.local) {
// Force all projects to be not private
const projects = JSON.parse(
@ -54,21 +71,26 @@ function hideFromGitIndex(uncommittedFiles: string[]) {
}
}
if (!options.local && process.env.NPM_TOKEN) {
execSync('npx nx run-many --target=artifacts', {
stdio: [0, 1, 2],
});
}
const versionOptions = {
bump: options.version ? options.version : undefined,
conventionalCommits: true,
conventionalPrerelease: options.tag === 'next',
preid: options.preid,
forcePublish: true,
createRelease: options.tag !== 'next' ? 'github' : undefined,
noChangelog: options.tag === 'next',
createRelease: 'github',
tagVersionPrefix: '',
exact: true,
gitRemote: options.gitRemote,
gitTagVersion: options.tag !== 'next',
gitTagVersion: !process.env.NPM_TOKEN,
message: 'chore(misc): publish %v',
loglevel: options.loglevel ?? 'info',
yes: false,
yes: !!process.env.NPM_TOKEN,
};
if (options.local) {
@ -80,12 +102,6 @@ function hideFromGitIndex(uncommittedFiles: string[]) {
versionOptions.bump = options.version ? options.version : 'minor';
}
const lernaJsonPath = join(__dirname, '../lerna.json');
let originalLernaJson: Buffer | undefined;
if (options.local || options.tag === 'next') {
originalLernaJson = readFileSync(lernaJsonPath);
}
if (options.local) {
/**
* Hide changes from Lerna
@ -104,18 +120,25 @@ function hideFromGitIndex(uncommittedFiles: string[]) {
const publishOptions: Record<string, boolean | string | undefined> = {
gitReset: false,
distTag: options.tag,
distTag: distTag,
};
if (!options.skipPublish) {
if (!options.local && !process.env.NPM_TOKEN) {
execSync('git status --ahead-behind');
await version(versionOptions);
console.log(
'Check github: https://github.com/nrwl/nx/actions/workflows/publish.yml'
);
} else if (!options.skipPublish) {
await publish({ ...versionOptions, ...publishOptions });
} else {
await version(versionOptions);
console.warn('Not Publishing because --dryRun was passed');
}
if (originalLernaJson) {
writeFileSync(lernaJsonPath, originalLernaJson);
if (options.local) {
restoreOriginalLernaJson();
}
})();
@ -161,17 +184,6 @@ function parseArgs() {
'Alternate git remote name to publish tags to (useful for testing changelog)',
default: 'origin',
})
.option('tag', {
type: 'string',
description: 'NPM Tag',
choices: ['next', 'latest', 'previous'],
})
.option('preid', {
type: 'string',
description: 'The kind of prerelease tag. (1.0.0-[preid].0)',
choices: ['alpha', 'beta', 'rc'],
default: 'beta',
})
.option('loglevel', {
type: 'string',
description: 'Log Level',
@ -182,23 +194,23 @@ function parseArgs() {
`By default, this will locally publish a minor version bump as latest. Great for local development. Most developers should only need this.`
)
.example(
'$0 --local false',
`This will really publish a new beta version to npm as next. The version is inferred by the changes.`
'$0 --local false 2.3.4-beta.0',
`This will really publish a new version to npm as next.`
)
.example(
'$0 --local false --tag latest',
`This will really publish a new stable version to npm as latest, tag, commit, push, and create a release on GitHub.`
'$0 --local false 2.3.4',
`Given the current latest major version on npm is 2, this will really publish a new version to npm as latest.`
)
.example(
'$0 --local false --preid rc',
`This will really publish a new rc version to npm as next.`
'$0 --local false 1.3.4-beta.0',
`Given the current latest major version on npm is 2, this will really publish a new version to npm as previous.`
)
.group(
['local', 'clearLocalRegistry'],
'Local Publishing Options for most developers'
)
.group(
['preid', 'tag', 'gitRemote', 'force'],
['gitRemote', 'force'],
'Real Publishing Options for actually publishing to NPM'
)
.check((args) => {
@ -228,6 +240,18 @@ function parseArgs() {
return parsedArgs;
}
function updateLernaJsonVersion(version: string) {
const json = JSON.parse(readFileSync(lernaJsonPath).toString());
json.version = version;
writeFileSync(lernaJsonPath, JSON.stringify(json));
}
function restoreOriginalLernaJson() {
writeFileSync(lernaJsonPath, originalLernaJson);
}
function getRegistry() {
return new URL(execSync('npm config get registry').toString().trim());
}

31
scripts/preinstall.js Normal file
View File

@ -0,0 +1,31 @@
/*
This pre-install script will check that the necessary dependencies are installed
Checks for:
* Node 18+
* Cargo
*/
if (process.env.CI) {
process.exit(0);
}
const childProcess = require('child_process');
// Check node version
const nodeVersion = process.version.slice(1).split('.');
if (+nodeVersion[0] < 18) {
console.error(
'Please make sure that your installed Node version is greater than v18'
);
process.exit(1);
}
// Check for cargo
try {
childProcess.execSync('cargo --version');
} catch {
console.error(
'Could not find Cargo. Please make sure that Cargo and Rust is installed with https://rustup.rs'
);
process.exit(1);
}

View File

@ -15,6 +15,7 @@
"resolveJsonModule": true,
"baseUrl": ".",
"rootDir": ".",
"allowJs": true,
"paths": {
"@nrwl/angular": ["packages/angular"],
"@nrwl/angular/*": ["packages/angular/*"],

View File

@ -4114,6 +4114,11 @@
npmlog "^6.0.2"
write-file-atomic "^4.0.1"
"@ltd/j-toml@1.24.0":
version "1.24.0"
resolved "https://registry.yarnpkg.com/@ltd/j-toml/-/j-toml-1.24.0.tgz#4c993610586964fb21fd38a84bb41913f6e4f5ff"
integrity sha512-XWEvSNLJ2YeCvlNDd/DQfTMldJqBZWX8+RKgPMY2i3MShqsB9XvtY2UfHqcuPb+eRrNO1WR7w4xlNfzCzop+Ig==
"@markdoc/markdoc@0.1.13":
version "0.1.13"
resolved "https://registry.yarnpkg.com/@markdoc/markdoc/-/markdoc-0.1.13.tgz#358408d3b4edf5dae90b51c2d8d89d51743dbd18"
@ -4169,6 +4174,15 @@
"@monaco-editor/loader" "^1.3.2"
prop-types "^15.7.2"
"@monodon/rust@0.4.4":
version "0.4.4"
resolved "https://registry.yarnpkg.com/@monodon/rust/-/rust-0.4.4.tgz#b0df3b547692e1a66971387efeb7ec48620fadb8"
integrity sha512-sBU0h+6NoFaZYy3lcSqh6uNiGBp8cugj8V/wilsUy0+oEYmYTakO3So9EWwAsLMFRvh15yUOoOEVLuJ4ggIJOA==
dependencies:
"@ltd/j-toml" "1.24.0"
"@nrwl/devkit" "15.3.0"
chalk "4.1.2"
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@ -4237,6 +4251,11 @@
"@napi-rs/canvas-linux-x64-musl" "0.1.30"
"@napi-rs/canvas-win32-x64-msvc" "0.1.30"
"@napi-rs/cli@2.14.0":
version "2.14.0"
resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.14.0.tgz#ca1c1a75d6922f8af098d8d56f4914e0889963c8"
integrity sha512-hQW+gOTQ80nCoBAWA0hq49HM3QqyC7x879CdF/CEEFHeJNlHT8tgru8nbMQa6YqMP1XADfiudsYzy5V7TxBxCw==
"@nestjs/cli@^9.0.0":
version "9.1.8"
resolved "https://registry.yarnpkg.com/@nestjs/cli/-/cli-9.1.8.tgz#e4cb06c0cb628bf08ae143c2c6278a7beb38044b"
@ -4731,6 +4750,17 @@
dotenv "~10.0.0"
semver "7.3.4"
"@nrwl/devkit@15.3.0":
version "15.3.0"
resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.3.0.tgz#4b0fc4c94f0b92413aa3d028f8cc75f586936d27"
integrity sha512-1O9QLB/eYS6ddw4MZnV4yj4CEqLIbpleZZiG/9w1TaiVO/jfNfXVaxc8EA87XSzMpk2W+/4Qggmabt6gAQaabA==
dependencies:
"@phenomnomnominal/tsquery" "4.1.1"
ejs "^3.1.7"
ignore "^5.0.4"
semver "7.3.4"
tslib "^2.3.0"
"@nrwl/devkit@15.6.0-beta.1":
version "15.6.0-beta.1"
resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.6.0-beta.1.tgz#a518608b7632fa95076b12912114c7787d1714ca"