diff --git a/.cargo/config.toml b/.cargo/config.toml index 1f5b663..491b01d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,10 @@ [target.aarch64-unknown-linux-gnu] linker = "aarch64-linux-gnu-gcc" +rustflags = ["-C", "link-arg=-Wl,-rpath,$ORIGIN/lib/linux/arm64/gnu"] + +[target.x86_64-unknown-linux-gnu] +linker = "x86_64-linux-gnu-gcc" +rustflags = ["-C", "link-arg=-Wl,-rpath,$ORIGIN/lib/linux/x64/gnu"] [target.armv7-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc" @@ -11,3 +16,9 @@ rustflags = ["-C", "target-feature=-crt-static"] [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" rustflags = ["-C", "target-feature=-crt-static"] + +[target.aarch64-apple-darwin] +rustflags = [ "-Clink-args=-Wl,-rpath,@loader_path/lib/darwin/arm64" ] + +[target.x86_64-apple-darwin] +rustflags = [ "-Clink-args=-Wl,-rpath,@loader_path/lib/darwin/x64" ] diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 2598a86..b083798 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -1,34 +1,40 @@ # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs -name: Node.js CI +name: CI on: push: - branches: [ "master", "fridvin*" ] + branches: [ "*" ] pull_request: - branches: [ "master", "fridvin*" ] + branches: [ "*" ] env: CARGO_TERM_COLOR: always jobs: build: - - runs-on: ${{ matrix.os }} - + runs-on: ${{ matrix.settings.host }} permissions: contents: write packages: write - strategy: matrix: - # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ - node-version: [ 18.x ] - os: [ macos-latest, ubuntu-latest ] - + settings: + - host: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + runtests: true + - host: ubuntu-22.04 + target: aarch64-unknown-linux-gnu + runtests: false + - host: macos-latest + target: aarch64-apple-darwin + runtests: true + - host: macos-latest + target: x86_64-apple-darwin + runtests: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup go uses: actions/setup-go@v3 with: @@ -50,21 +56,76 @@ jobs: ln -sf $HOME/.ssh/nfs-rs $HOME/.ssh/id_rsa git clone git@github.com:NetAppLabs/nfs-rs.git rm $HOME/.ssh/id_rsa - - name: Install non-rust non-node dependencies - run: ./deps.sh - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + - name: linux deps + if: runner.os == 'Linux' + shell: bash + run: | + sudo apt-get -y install \ + libc6-dev-amd64-cross libc6-dev-arm64-cross \ + crossbuild-essential-arm64 crossbuild-essential-amd64 \ + gcc-aarch64-linux-gnu \ + binfmt-support binutils binutils-aarch64-linux-gnu + - uses: mlugg/setup-zig@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: - node-version: ${{ matrix.node-version }} + rustflags: "" + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.x cache: 'yarn' + registry-url: 'https://npm.pkg.github.com' + scope: '@netapplabs' - name: Prepare yarn - run: yarn install --immutable + run: yarn install - name: Build - run: yarn build + run: yarn build --target ${{ matrix.settings.target }} - name: Test + if: ${{ matrix.settings.runtests }} run: yarn test - name: Upload node module uses: actions/upload-artifact@v4 with: - name: nfs-js.${{ matrix.os }}-x64-node${{ matrix.node-version }}.node - path: nfs-js.*.node + name: nfs-js-node.${{ matrix.settings.host }}-${{ matrix.settings.target }} + path: | + nfs-js-node.*.node + lib + publish: + runs-on: ubuntu-22.04 + if: ${{ github.ref == 'refs/heads/master' }} + permissions: + contents: write + packages: write + needs: build + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: 'yarn' + registry-url: 'https://npm.pkg.github.com' + scope: '@netapplabs' + + - name: Download Artifact + uses: actions/download-artifact@v4 + with: + pattern: nfs-js-node.* + merge-multiple: true + + - name: Setup git + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + + - name: Bump version + run: npx standard-version + + - name: Publish Artifacts + run: npm publish --ignore-scripts + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Commit and push version bump + run: | + git push --follow-tags diff --git a/.gitignore b/.gitignore index f47feb2..b8575d2 100644 --- a/.gitignore +++ b/.gitignore @@ -132,3 +132,5 @@ libnfs npm .turbo +lib +krb5 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5c79a3c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. diff --git a/Cargo.lock b/Cargo.lock index d1bb4a8..4c34fd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -567,7 +567,7 @@ dependencies = [ [[package]] name = "nfs-js" -version = "0.7.0" +version = "0.8.0" dependencies = [ "bytes", "libnfs", diff --git a/Cargo.toml b/Cargo.toml index ee7027f..85deb37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ authors = ["LongYinan ","Tryggvi Larusson ","Fridvin Oddbjornsson "] edition = "2021" name = "nfs-js" -version = "0.7.0" +version = "0.8.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -30,6 +30,7 @@ napi-build = "2" [profile.release] lto = true +rpath = true [patch.crates-io] libnfs-sys = { path = "./libnfs-sys" } diff --git a/__test__/index.spec.js b/__test__/index.spec.js index ef38298..8249b65 100644 --- a/__test__/index.spec.js +++ b/__test__/index.spec.js @@ -65,8 +65,8 @@ ava_1.default.serial('should be same entry as self for directory', async (t) => }); ava_1.default.serial('should not be same entry as others for directory', async (t) => { const rootHandle = getRootHandle(); - const fileHandle = await rootHandle.getFileHandle('annar'); - const dirHandle = await rootHandle.getDirectoryHandle('first'); + const fileHandle = await rootHandle.getFileHandle('annar', {}); + const dirHandle = await rootHandle.getDirectoryHandle('first', {}); t.false(await fileHandle.isSameEntry(dirHandle)); t.false(await rootHandle.isSameEntry(dirHandle)); t.false(await dirHandle.isSameEntry(fileHandle)); @@ -739,7 +739,7 @@ ava_1.default.serial('should return non-locked writable when creating writable a ava_1.default.serial('should return error when writing unsupported type', async (t) => { const rootHandle = getRootHandle(); const fileHandle = await rootHandle.getFileHandle('writable-write-unsupported-type', { create: true }); - const writable = await fileHandle.createWritable(); + const writable = await fileHandle.createWritable({}); const err = await t.throwsAsync(writable.write(69)); t.is(err?.message, 'Writing unsupported type'); await rootHandle.removeEntry(fileHandle.name); diff --git a/__test__/index.spec.ts b/__test__/index.spec.ts index 1101d6a..d812da0 100644 --- a/__test__/index.spec.ts +++ b/__test__/index.spec.ts @@ -68,8 +68,8 @@ test.serial('should be same entry as self for directory', async (t) => { test.serial('should not be same entry as others for directory', async (t) => { const rootHandle = getRootHandle(); - const fileHandle = await rootHandle.getFileHandle('annar'); - const dirHandle = await rootHandle.getDirectoryHandle('first'); + const fileHandle = await rootHandle.getFileHandle('annar', {}); + const dirHandle = await rootHandle.getDirectoryHandle('first', {}); t.false(await fileHandle.isSameEntry(dirHandle)); t.false(await rootHandle.isSameEntry(dirHandle)); t.false(await dirHandle.isSameEntry(fileHandle)); @@ -810,7 +810,7 @@ test.serial('should return non-locked writable when creating writable and keepin test.serial('should return error when writing unsupported type', async (t) => { const rootHandle = getRootHandle(); const fileHandle = await rootHandle.getFileHandle('writable-write-unsupported-type', {create: true}) as NfsFileHandle; - const writable = await fileHandle.createWritable(); + const writable = await fileHandle.createWritable({}); const err = await t.throwsAsync(writable.write(69 as any)); t.is(err?.message, 'Writing unsupported type'); await rootHandle.removeEntry(fileHandle.name); diff --git a/build.sh b/build.sh index 4f00c35..4bce919 100755 --- a/build.sh +++ b/build.sh @@ -16,22 +16,75 @@ # SPDX-License-Identifier: Apache-2.0 -set -e +set -ex -./deps.sh +ARG1="$1" + +LOCAL_TARGET_TRIPLE=`rustc --version --verbose | grep ^host | awk -F ' ' '{print $2}'` +TARGET_TRIPLE="${LOCAL_TARGET_TRIPLE}" + +if [[ "${ARG1}" == "--target" ]]; then + ARG2="$2" + if [ -n "${ARG2}" ]; then + TARGET_TRIPLE="${ARG2}" + fi +fi + +rustup target add ${TARGET_TRIPLE} +TARGET_TRIPLE_FOR_CC=`echo ${TARGET_TRIPLE} | sed 's/-unknown//g'` + +if [[ "${TARGET_TRIPLE}" == *"linux"* ]]; then + export BINDGEN_EXTRA_CLANG_ARGS="-I/usr/${TARGET_TRIPLE_FOR_CC}/include" +elif [[ "${TARGET_TRIPLE}" == *"darwin"* ]]; then + TARGET_TRIPLE_FOR_CC=`echo ${TARGET_TRIPLE} | sed 's/aarch64/arm64/g'` +fi + +./deps.sh ${TARGET_TRIPLE} ${TARGET_TRIPLE_FOR_CC} SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) LIBNFS_BASE="${SCRIPT_DIR}/libnfs" -LIBNFS_BASE_INSTALL="${SCRIPT_DIR}/libnfs/local-install" -export LIBNFS_LIB_PATH="${LIBNFS_BASE}/lib/.libs/" +LIBNFS_BASE_INSTALL="${SCRIPT_DIR}/libnfs/local-install/${TARGET_TRIPLE}" + +NODE_ARCH=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $1}' | sed 's/aarch64/arm64/g' | sed 's/x86_64/x64/g'` +NODE_PLATFORM=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $2}'` +NODE_OS=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $3}'` +NODE_OS_VARIANT=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $4}'` + +LIBNFS_BASE_LIB_INSTALL_PATH="${LIBNFS_BASE_INSTALL}/lib" + +NFS_JS_LIB_FULL_VER=`cat ${LIBNFS_BASE_LIB_INSTALL_PATH}/pkgconfig/libnfs.pc | grep '^Version:' | awk '{print $2}'` +NFS_JS_LIB_VER=`echo ${NFS_JS_LIB_FULL_VER} | awk -F '.' '{print $1}'` + +export LIBNFS_LIB_PATH="./lib/${NODE_OS}/${NODE_ARCH}" +if [ -n "${NODE_OS_VARIANT}" ]; then + export LIBNFS_LIB_PATH="./lib/${NODE_OS}/${NODE_ARCH}/${NODE_OS_VARIANT}" +fi +mkdir -p ${LIBNFS_LIB_PATH} +if [ "${NODE_OS}" == "darwin" ]; then + cp -R ${LIBNFS_BASE_LIB_INSTALL_PATH}/libnfs.${NFS_JS_LIB_VER}.dylib ${LIBNFS_LIB_PATH}/ + cp -R ${LIBNFS_BASE_LIB_INSTALL_PATH}/libnfs.dylib ${LIBNFS_LIB_PATH}/ +elif [ "${NODE_OS}" == "linux" ]; then + cp -R ${LIBNFS_BASE_LIB_INSTALL_PATH}/libnfs.so* ${LIBNFS_LIB_PATH}/ +fi + export LIBNFS_INCLUDE_PATH="${LIBNFS_BASE_INSTALL}/include" -export LIBNFS_LINK_STATIC="true" +export LIBNFS_LINK_STATIC="false" export DYLD_LIBRARY_PATH=${LIBNFS_LIB_PATH}:$DYLD_LIBRARY_PATH export LD_LIBRARY_PATH=${LIBNFS_LIB_PATH}:$LD_LIBRARY_PATH export RUST_BACKTRACE=1 -yarn build-napi +if [ "$ARG1" == "test" ]; then + cargo test --release +else + yarn build-tsc + yarn build-napi --target ${TARGET_TRIPLE} +fi + +if [ "${NODE_OS}" == "darwin" ]; then + # rewrite dylib search path after build for macos + install_name_tool -change ${LIBNFS_BASE_LIB_INSTALL_PATH}/libnfs.${NFS_JS_LIB_VER}.dylib @loader_path/lib/${NODE_OS}/${NODE_ARCH}/libnfs.${NFS_JS_LIB_VER}.dylib nfs-js-node.${NODE_OS}-${NODE_ARCH}.node +fi diff --git a/deps.sh b/deps.sh index 774f8f5..cb704dd 100755 --- a/deps.sh +++ b/deps.sh @@ -15,8 +15,9 @@ # # SPDX-License-Identifier: Apache-2.0 - -set -e +set -ex +TARGET_TRIPLE=$1 +TARGET_TRIPLE_FOR_CC=$2 if ! command -v git 2>&1 >/dev/null ; then if command -v brew 2>&1 >/dev/null ; then @@ -47,6 +48,33 @@ if ! command -v automake 2>&1 >/dev/null ; then fi fi +if ! command -v add-apt-repository 2>&1 >/dev/null ; then + if command -v apt-get 2>&1 >/dev/null ; then + sudo apt-get update + sudo apt-get -y install software-properties-common + fi +fi + +if command -v lsb_release 2>&1 >/dev/null ; then + lsb_rel_version=`lsb_release -c | grep '^Codename:' | awk -F ' ' '{print $2}'` + if [ "${lsb_rel_version}" == "focal" ]; then + # install backported autoconf 2.71 backported for ubuntu 20.04 / focal + sudo add-apt-repository ppa:savoury1/build-tools -y + sudo apt-get -y install autoconf2.71 + fi +fi + +if ! command -v yacc 2>&1 >/dev/null ; then + if command -v brew 2>&1 >/dev/null ; then + brew install byacc + elif command -v apt-get 2>&1 >/dev/null ; then + sudo apt-get update + sudo apt-get install -y byacc + else + echo "please install yacc" + fi +fi + OS=`uname -s` if [ "${OS}" == "Darwin" ]; then if ! command -v glibtool 2>&1 >/dev/null ; then @@ -108,16 +136,124 @@ else popd &> /dev/null fi -if [ ! -f libnfs/local-install/lib/libnfs.a ]; then - pushd libnfs &> /dev/null - CURDIR="$(pwd)" - INSTALL_DIR="${CURDIR}/local-install" - mkdir -p "${INSTALL_DIR}" - ./bootstrap - ./configure --without-libkrb5 --prefix="${INSTALL_DIR}" --exec-prefix="${INSTALL_DIR}" CFLAGS='-fPIC -Wno-cast-align' - make - make install - popd &> /dev/null +PROCS=8 +YACC="yacc" +if [ "${OS}" == "Darwin" ]; then + YACC="/opt/homebrew/bin/byacc" +fi +if [ ! -f libnfs/local-install/${TARGET_TRIPLE}/lib/libnfs.a ]; then + if [ "${OS}" == "Darwin" ]; then + pushd libnfs &> /dev/null + CURDIR="$(pwd)" + INSTALL_DIR="${CURDIR}/local-install/${TARGET_TRIPLE}" + BUILD_DIR="${CURDIR}/local-build/${TARGET_TRIPLE}" + mkdir -p "${BUILD_DIR}" + mkdir -p "${INSTALL_DIR}" + chmod 775 ./bootstrap + ./bootstrap + pushd ${BUILD_DIR} &> /dev/null + ../../configure \ + --disable-werror \ + --host=${TARGET_TRIPLE_FOR_CC} \ + --prefix="${INSTALL_DIR}" \ + --exec-prefix="${INSTALL_DIR}" \ + CFLAGS="-fPIC -Wno-cast-align -I${CURDIR}" \ + YACC="${YACC}" + make -j${PROCS} install + popd &> /dev/null + popd &> /dev/null + elif [ "${OS}" == "Linux" ]; then + MAIN_CURDIR="$(pwd)" + + EXTRA_CFLAGS="" + EXTRA_LDFLAGS="" + + HOST_ARCH=`uname -m` + COMPILE_FOR_ARCH=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $1}'` + CROSS_COMPILE="false" + if [ "${HOST_ARCH}" != "${COMPILE_FOR_ARCH}" ]; then + CROSS_COMPILE="true" + fi + + if [ "${CROSS_COMPILE}" == "true" ]; then + OPENSSL_INSTALL_DIR="${MAIN_CURDIR}/openssl/local-install/${TARGET_TRIPLE}" + EXTRA_CFLAGS="-I${OPENSSL_INSTALL_DIR}/include" + EXTRA_LDFLAGS="-L${OPENSSL_INSTALL_DIR}/lib" + if [ ! -e openssl ]; then + mkdir -p ${OPENSSL_INSTALL_DIR} + echo "building openssl for cross compile" + if [ "${HOST_ARCH}" == "x86_64" ]; then + sudo add-apt-repository -s "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) main restricted universe multiverse" -y + else + sudo add-apt-repository -s "deb http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc) main restricted universe multiverse" -y + fi + apt-get source openssl + OPENSSL_VER=`apt-cache showsrc openssl | grep '^Version' | awk '{print $2}' | awk -F '-' '{print $1}'` + OPENSSL_SRC_DIR="openssl-${OPENSSL_VER}" + pushd ${OPENSSL_SRC_DIR} + ./Configure linux-${COMPILE_FOR_ARCH} --prefix=${OPENSSL_INSTALL_DIR} CC=${COMPILE_FOR_ARCH}-linux-gnu-gcc + make -j${PROCS} + make -j${PROCS} install + popd + fi + fi + + if [ ! -e krb5 ]; then + git clone --branch krb5-1.21.3-final https://github.com/krb5/krb5.git + fi + + KRB5_INSTALL_DIR="${MAIN_CURDIR}/krb5/local-install/${TARGET_TRIPLE}" + + if [ ! -e krb5/local-install/${TARGET_TRIPLE}/lib/krb5 ]; then + pushd krb5 &> /dev/null + CURDIR="$(pwd)" + INSTALL_DIR="${CURDIR}/local-install/${TARGET_TRIPLE}" + mkdir -p "${INSTALL_DIR}" + BUILD_DIR="${CURDIR}/local-build/${TARGET_TRIPLE}" + mkdir -p "${BUILD_DIR}" + pushd src &> /dev/null + # for cross compile to work + export krb5_cv_attr_constructor_destructor=yes + export ac_cv_func_regcomp=yes + export ac_cv_printf_positional=yes + autoreconf --force + pushd ${BUILD_DIR} &> /dev/null + ../../src/configure \ + --host=${TARGET_TRIPLE_FOR_CC} \ + --prefix="${INSTALL_DIR}" \ + --exec-prefix="${INSTALL_DIR}" \ + --enable-static \ + --disable-shared \ + CFLAGS="-fPIC -fcommon -Wno-cast-align ${EXTRA_CFLAGS}" \ + LDFLAGS="${EXTRA_LDFLAGS}" + make -j${PROCS} + make install + popd &> /dev/null + popd &> /dev/null + popd &> /dev/null + fi + + pushd libnfs &> /dev/null + CURDIR="$(pwd)" + INSTALL_DIR="${CURDIR}/local-install/${TARGET_TRIPLE}" + BUILD_DIR="${CURDIR}/local-build/${TARGET_TRIPLE}" + mkdir -p "${BUILD_DIR}" + mkdir -p "${INSTALL_DIR}" + chmod 775 ./bootstrap + ./bootstrap + pushd ${BUILD_DIR} &> /dev/null + ../../configure \ + --disable-werror \ + --host=${TARGET_TRIPLE_FOR_CC} \ + --prefix="${INSTALL_DIR}" \ + --exec-prefix="${INSTALL_DIR}" \ + CFLAGS="-fPIC -Wno-cast-align -I${KRB5_INSTALL_DIR}/include -I${CURDIR}" \ + LDFLAGS="-L${KRB5_INSTALL_DIR}/lib" \ + LIBS="-ldl -lgssapi_krb5 -lkrb5 -lcom_err -lgssrpc -lk5crypto -lkdb5 -lkrad -lkrb5_db2 -lkrb5_k5tls -lkrb5_otp -lkrb5_spake -lkrb5support -lverto -lresolv" + make -j${PROCS} install + popd &> /dev/null + popd &> /dev/null + fi fi if [ ! -d go-nfs ]; then diff --git a/indax.js b/indax.js index 55bc5f7..fb00d21 100644 --- a/indax.js +++ b/indax.js @@ -132,6 +132,9 @@ class NfsFileHandle extends NfsHandle { async getFile() { return this._js.getFile(); } + async createSyncAccessHandle() { + throw new Error("createSyncAccessHandle not implemented"); + } async createWritable(options) { return new Promise(async (resolve, reject) => { await this._js.createWritable(options) diff --git a/indax.ts b/indax.ts index 2ea9fe9..9bd9321 100644 --- a/indax.ts +++ b/indax.ts @@ -18,10 +18,6 @@ import { JsNfsHandlePermissionDescriptor, - JsNfsGetDirectoryOptions, - JsNfsGetFileOptions, - JsNfsRemoveOptions, - JsNfsCreateWritableOptions, JsNfsHandle, JsNfsDirectoryHandle, JsNfsFileHandle, @@ -33,6 +29,8 @@ type NfsHandlePermissionDescriptor = JsNfsHandlePermissionDescriptor; type NfsCreateWritableOptions = FileSystemCreateWritableOptions; // @ts-ignore type FileSystemWritableFileStream = FileSystemWritableFileStream; +// @ts-ignore +type FileSystemSyncAccessHandle = FileSystemSyncAccessHandle; type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array; @@ -116,7 +114,7 @@ export class NfsDirectoryHandle extends NfsHandle implements FileSystemDirectory } async getDirectoryHandle(name: string, options?: FileSystemGetDirectoryOptions): Promise { return new Promise(async (resolve, reject) => { - await this._js.getDirectoryHandle(name, options as JsNfsGetDirectoryOptions) + await this._js.getDirectoryHandle(name, options) .then((handle) => resolve(new NfsDirectoryHandle(handle) as FileSystemDirectoryHandle)) .catch((reason) => { let errMsg: string = reason.message; @@ -133,7 +131,7 @@ export class NfsDirectoryHandle extends NfsHandle implements FileSystemDirectory } async getFileHandle(name: string, options?: FileSystemGetFileOptions): Promise { return new Promise(async (resolve, reject) => { - await this._js.getFileHandle(name, options as JsNfsGetFileOptions) + await this._js.getFileHandle(name, options) .then((handle) => resolve(new NfsFileHandle(handle) as FileSystemFileHandle)) .catch((reason) => { let errMsg: string = reason.message; @@ -149,7 +147,7 @@ export class NfsDirectoryHandle extends NfsHandle implements FileSystemDirectory }); } async removeEntry(name: string, options?: FileSystemRemoveOptions): Promise { - return this._js.removeEntry(name, options as JsNfsRemoveOptions); + return this._js.removeEntry(name, options); } async resolve(possibleDescendant: FileSystemHandle): Promise | null> { return this._js.resolve((possibleDescendant as any)._jsh || possibleDescendant); @@ -190,9 +188,12 @@ export class NfsFileHandle extends NfsHandle implements FileSystemFileHandle { async getFile(): Promise { return this._js.getFile(); } + async createSyncAccessHandle(): Promise { + throw new Error("createSyncAccessHandle not implemented"); + } async createWritable(options?: NfsCreateWritableOptions): Promise { return new Promise(async (resolve, reject) => { - await this._js.createWritable(options as JsNfsCreateWritableOptions) + await this._js.createWritable(options) .then((stream) => resolve(new NfsWritableFileStream(stream) as FileSystemWritableFileStream)) .catch((reason) => reject(reason)); }); diff --git a/index.d.ts b/index.d.ts index 13a427d..c5b20d1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -7,16 +7,16 @@ export interface JsNfsHandlePermissionDescriptor { mode: 'read' | 'readwrite' } export interface JsNfsGetDirectoryOptions { - create: boolean + create?: boolean } export interface JsNfsGetFileOptions { - create: boolean + create?: boolean } export interface JsNfsRemoveOptions { - recursive: boolean + recursive?: boolean } export interface JsNfsCreateWritableOptions { - keepExistingData: boolean + keepExistingData?: boolean } export declare class JsNfsDirectoryHandleEntries { [Symbol.asyncIterator]: AsyncIterableIterator<[string, JsNfsDirectoryHandle | JsNfsFileHandle]> diff --git a/index.js b/index.js index 026facb..7c034c7 100644 --- a/index.js +++ b/index.js @@ -32,10 +32,10 @@ switch (platform) { case 'android': switch (arch) { case 'arm64': - localFileExisted = existsSync(join(__dirname, 'nfs-js.android-arm64.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.android-arm64.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.android-arm64.node') + nativeBinding = require('./nfs-js-node.android-arm64.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-android-arm64') } @@ -44,10 +44,10 @@ switch (platform) { } break case 'arm': - localFileExisted = existsSync(join(__dirname, 'nfs-js.android-arm-eabi.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.android-arm-eabi.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.android-arm-eabi.node') + nativeBinding = require('./nfs-js-node.android-arm-eabi.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-android-arm-eabi') } @@ -62,10 +62,10 @@ switch (platform) { case 'win32': switch (arch) { case 'x64': - localFileExisted = existsSync(join(__dirname, 'nfs-js.win32-x64-msvc.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.win32-x64-msvc.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.win32-x64-msvc.node') + nativeBinding = require('./nfs-js-node.win32-x64-msvc.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-win32-x64-msvc') } @@ -74,10 +74,10 @@ switch (platform) { } break case 'ia32': - localFileExisted = existsSync(join(__dirname, 'nfs-js.win32-ia32-msvc.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.win32-ia32-msvc.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.win32-ia32-msvc.node') + nativeBinding = require('./nfs-js-node.win32-ia32-msvc.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-win32-ia32-msvc') } @@ -86,10 +86,10 @@ switch (platform) { } break case 'arm64': - localFileExisted = existsSync(join(__dirname, 'nfs-js.win32-arm64-msvc.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.win32-arm64-msvc.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.win32-arm64-msvc.node') + nativeBinding = require('./nfs-js-node.win32-arm64-msvc.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-win32-arm64-msvc') } @@ -102,10 +102,10 @@ switch (platform) { } break case 'darwin': - localFileExisted = existsSync(join(__dirname, 'nfs-js.darwin-universal.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.darwin-universal.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.darwin-universal.node') + nativeBinding = require('./nfs-js-node.darwin-universal.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-darwin-universal') } @@ -113,10 +113,10 @@ switch (platform) { } catch {} switch (arch) { case 'x64': - localFileExisted = existsSync(join(__dirname, 'nfs-js.darwin-x64.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.darwin-x64.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.darwin-x64.node') + nativeBinding = require('./nfs-js-node.darwin-x64.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-darwin-x64') } @@ -125,10 +125,10 @@ switch (platform) { } break case 'arm64': - localFileExisted = existsSync(join(__dirname, 'nfs-js.darwin-arm64.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.darwin-arm64.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.darwin-arm64.node') + nativeBinding = require('./nfs-js-node.darwin-arm64.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-darwin-arm64') } @@ -144,10 +144,10 @@ switch (platform) { if (arch !== 'x64') { throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) } - localFileExisted = existsSync(join(__dirname, 'nfs-js.freebsd-x64.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.freebsd-x64.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.freebsd-x64.node') + nativeBinding = require('./nfs-js-node.freebsd-x64.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-freebsd-x64') } @@ -159,10 +159,10 @@ switch (platform) { switch (arch) { case 'x64': if (isMusl()) { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-x64-musl.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-x64-musl.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-x64-musl.node') + nativeBinding = require('./nfs-js-node.linux-x64-musl.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-x64-musl') } @@ -170,10 +170,10 @@ switch (platform) { loadError = e } } else { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-x64-gnu.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-x64-gnu.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-x64-gnu.node') + nativeBinding = require('./nfs-js-node.linux-x64-gnu.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-x64-gnu') } @@ -184,10 +184,10 @@ switch (platform) { break case 'arm64': if (isMusl()) { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-arm64-musl.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-arm64-musl.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-arm64-musl.node') + nativeBinding = require('./nfs-js-node.linux-arm64-musl.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-arm64-musl') } @@ -195,10 +195,10 @@ switch (platform) { loadError = e } } else { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-arm64-gnu.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-arm64-gnu.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-arm64-gnu.node') + nativeBinding = require('./nfs-js-node.linux-arm64-gnu.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-arm64-gnu') } @@ -209,10 +209,10 @@ switch (platform) { break case 'arm': if (isMusl()) { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-arm-musleabihf.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-arm-musleabihf.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-arm-musleabihf.node') + nativeBinding = require('./nfs-js-node.linux-arm-musleabihf.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-arm-musleabihf') } @@ -220,10 +220,10 @@ switch (platform) { loadError = e } } else { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-arm-gnueabihf.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-arm-gnueabihf.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-arm-gnueabihf.node') + nativeBinding = require('./nfs-js-node.linux-arm-gnueabihf.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-arm-gnueabihf') } @@ -234,10 +234,10 @@ switch (platform) { break case 'riscv64': if (isMusl()) { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-riscv64-musl.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-riscv64-musl.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-riscv64-musl.node') + nativeBinding = require('./nfs-js-node.linux-riscv64-musl.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-riscv64-musl') } @@ -245,10 +245,10 @@ switch (platform) { loadError = e } } else { - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-riscv64-gnu.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-riscv64-gnu.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-riscv64-gnu.node') + nativeBinding = require('./nfs-js-node.linux-riscv64-gnu.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-riscv64-gnu') } @@ -258,10 +258,10 @@ switch (platform) { } break case 's390x': - localFileExisted = existsSync(join(__dirname, 'nfs-js.linux-s390x-gnu.node')) + localFileExisted = existsSync(join(__dirname, 'nfs-js-node.linux-s390x-gnu.node')) try { if (localFileExisted) { - nativeBinding = require('./nfs-js.linux-s390x-gnu.node') + nativeBinding = require('./nfs-js-node.linux-s390x-gnu.node') } else { nativeBinding = require('@netapplabs/nfs-js-node-linux-s390x-gnu') } diff --git a/nfs-rs b/nfs-rs index 50f8fa7..410c59c 160000 --- a/nfs-rs +++ b/nfs-rs @@ -1 +1 @@ -Subproject commit 50f8fa7deda8765e553b89bb9eb50c7592733431 +Subproject commit 410c59c5d52602bfdabb09b423671db393403738 diff --git a/package.json b/package.json index 50d12a9..8ca7a76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@netapplabs/nfs-js-node", - "version": "0.7.0", + "version": "0.8.0", "description": "nfs js", "main": "indax.js", "repository": "git@github.com:NetAppLabs/nfs-js-node.git", @@ -16,23 +16,19 @@ "files": [ "indax.ts", "index.d.ts", - "index.js" + "index.js", + "*.node", + "lib" ], "napi": { - "name": "nfs-js", + "name": "nfs-js-node", "triples": { "defaults": true, "additional": [ - "x86_64-unknown-linux-musl", - "aarch64-unknown-linux-gnu", - "i686-pc-windows-msvc", - "armv7-unknown-linux-gnueabihf", + "x86_64-apple-darwin", "aarch64-apple-darwin", - "aarch64-linux-android", - "x86_64-unknown-freebsd", - "aarch64-unknown-linux-musl", - "aarch64-pc-windows-msvc", - "armv7-linux-androideabi" + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu" ] } }, @@ -40,15 +36,14 @@ "node": ">= 10" }, "publishConfig": { - "registry": "https://registry.npmjs.org/", - "access": "public" + "registry": "https://npm.pkg.github.com", + "access": "restricted" }, "scripts": { "artifacts": "napi artifacts", "bench": "node -r @swc-node/register benchmark/bench.ts", - "build": "npm run build-sh && npm run build-tsc", + "build": "./build.sh", "build-tsc": "npx tsc -p .", - "build-sh": "./build.sh", "build-napi": "napi build --platform --release --pipe \"prettier -w\"", "build:darwin:x64": "napi build --platform --release --target x86_64-apple-darwin --pipe \"prettier -w\"", "build:darwin:arm64": "napi build --platform --release --target aarch64-apple-darwin --pipe \"prettier -w\"", @@ -60,8 +55,10 @@ "format:rs": "cargo fmt", "lint": "eslint . -c ./.eslintrc.yml", "prepublishOnly": "napi prepublish -t npm", - "test": "./test.sh", + "test": "npm run test-cargo && npm run test-sh", "test-ava": "ava", + "test-cargo": "./build.sh test", + "test-sh": "./test.sh", "version": "napi version" }, "devDependencies": { diff --git a/src/lib.rs b/src/lib.rs index ef48761..50bd9b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,15 +64,15 @@ interface FileSystemHandle { } interface FileSystemGetDirectoryOptions { - create: boolean; + create?: boolean; } interface FileSystemGetFileOptions { - create: boolean; + create?: boolean; } interface FileSystemRemoveOptions { - recursive: boolean; + recursive?: boolean; } interface FileSystemDirectoryHandle extends FileSystemHandle { @@ -88,7 +88,7 @@ interface FileSystemDirectoryHandle extends FileSystemHandle { } interface FileSystemCreateWritableOptions { - keepExistingData: boolean; + keepExistingData?: boolean; } interface FileSystemFileHandle extends FileSystemHandle { @@ -278,7 +278,7 @@ impl JsNfsHandlePermissionDescriptor { #[napi(object)] pub struct JsNfsGetDirectoryOptions { - pub create: bool + pub create: Option } impl Default for JsNfsGetDirectoryOptions { @@ -290,7 +290,7 @@ impl Default for JsNfsGetDirectoryOptions { #[napi(object)] pub struct JsNfsGetFileOptions { - pub create: bool + pub create: Option } impl Default for JsNfsGetFileOptions { @@ -302,7 +302,7 @@ impl Default for JsNfsGetFileOptions { #[napi(object)] pub struct JsNfsRemoveOptions { - pub recursive: bool + pub recursive: Option } impl Default for JsNfsRemoveOptions { @@ -314,7 +314,7 @@ impl Default for JsNfsRemoveOptions { #[napi(object)] pub struct JsNfsCreateWritableOptions { - pub keep_existing_data: bool + pub keep_existing_data: Option } impl Default for JsNfsCreateWritableOptions { @@ -493,7 +493,7 @@ impl JsNfsDirectoryHandle { return Ok(entry.into()); } } - if !options.unwrap_or_default().create { + if !options.unwrap_or_default().create.unwrap_or_default() { return Err(Error::new(Status::GenericFailure, format!("Directory {:?} not found", name))); } let path = format_dir_path(&self.handle.path, &name); @@ -513,7 +513,7 @@ impl JsNfsDirectoryHandle { return Ok(entry.into()); } } - if !options.unwrap_or_default().create { + if !options.unwrap_or_default().create.unwrap_or_default() { return Err(Error::new(Status::GenericFailure, format!("File {:?} not found", name))); } let path = format_file_path(&self.handle.path, &name); @@ -552,7 +552,7 @@ impl JsNfsDirectoryHandle { pub async fn remove_entry(&self, name: String, #[napi(ts_arg_type="JsNfsRemoveOptions")] options: Option) -> Result<()> { for entry in self.nfs_entries()? { if entry.name == name { - return self.nfs_remove(&entry, options.unwrap_or_default().recursive); + return self.nfs_remove(&entry, options.unwrap_or_default().recursive.unwrap_or_default()); } } Err(Error::new(Status::GenericFailure, format!("Entry {:?} not found", name))) @@ -657,8 +657,9 @@ impl JsNfsFileHandle { #[napi] pub async fn create_writable(&self, #[napi(ts_arg_type="JsNfsCreateWritableOptions")] options: Option) -> Result { - let position = (!options.unwrap_or_default().keep_existing_data).then(|| 0); - Ok(JsNfsWritableFileStream{handle: self.handle.clone(), position, locked: false}) + let keep_existing_data = options.unwrap_or_default().keep_existing_data; + let position = (!keep_existing_data.unwrap_or_default()).then(|| 0); + Ok(JsNfsWritableFileStream{handle: self.handle.clone(), keep_existing_data, position, locked: false}) } } @@ -808,6 +809,7 @@ impl JsNfsReadableStreamSource { #[napi] pub struct JsNfsWritableFileStream { handle: JsNfsHandle, + keep_existing_data: Option, position: Option, #[napi(readonly)] pub locked: bool @@ -969,6 +971,11 @@ impl JsNfsWritableFileStream { fn try_write_data(&mut self, options: &JsNfsWritableFileStreamWriteOptions) -> Result { if let Some(data) = &options.data { + if let Some(keep) = self.keep_existing_data.take() { + if !keep { + _ = self.nfs_truncate(0)?; + } + } return self.nfs_write(data.as_slice()); } Err(Error::new(Status::InvalidArg, format!("Property data of type object or string is required when writing object with type={:?}", WRITE_TYPE_WRITE))) diff --git a/test.sh b/test.sh index 400aa90..3c0832c 100755 --- a/test.sh +++ b/test.sh @@ -18,6 +18,23 @@ set -e +LOCAL_TARGET_TRIPLE=`rustc --version --verbose | grep ^host | awk -F ' ' '{print $2}'` +TARGET_TRIPLE="${LOCAL_TARGET_TRIPLE}" + +NODE_ARCH=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $1}' | sed 's/aarch64/arm64/g' | sed 's/x86_64/x64/g'` +NODE_PLATFORM=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $2}'` +NODE_OS=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $3}'` +NODE_OS_VARIANT=`echo ${TARGET_TRIPLE} | awk -F '-' '{print $4}'` + +LIBNFS_LIB_PATH="./lib/${NODE_OS}/${NODE_ARCH}" +if [ -n "${NODE_OS_VARIANT}" ]; then + LIBNFS_LIB_PATH="./lib/${NODE_OS}/${NODE_ARCH}/${NODE_OS_VARIANT}" +fi + +if [ -d "${LIBNFS_LIB_PATH}" -a -f "${LIBNFS_LIB_PATH}/libnfs.so" ]; then + export LD_LIBRARY_PATH="${LIBNFS_LIB_PATH}" +fi + NFS_TEST_DIR="/tmp/nfs-js-testrun-$RANDOM" mkdir -p ${NFS_TEST_DIR} @@ -34,8 +51,8 @@ GO_NFS_PID=$! function kill_go_nfs() { EXITCODE=$? - echo "Stopping go-nfs" - kill $GO_NFS_PID + echo "Stopping go-nfs" + kill $GO_NFS_PID if [ $EXITCODE -ne 0 ]; then cat /tmp/go-nfs/osnfs.log fi