From 5359723d922b103e7ed536c72bfcfd7264c34e02 Mon Sep 17 00:00:00 2001 From: Roger Qiu Date: Sat, 21 May 2022 21:01:18 +1000 Subject: [PATCH] Synchronise changes from TypeScript-Demo-Lib-Native --- .github/workflows/codesee-arch-diagram.yml | 10 +- .gitignore | 5 + .gitlab-ci.yml | 537 ++++++++++++++++++--- .npmignore | 7 +- default.nix | 26 +- jest.config.js | 56 ++- nix/leveldown.patch | 14 - package-lock.json | 60 ++- package.json | 11 +- release.nix | 62 +-- scripts/pkg.js | 174 +++++++ shell.nix | 13 +- src/bin/typescript-demo-lib.ts | 2 +- src/lib/test-level.ts | 1 + tests/global.d.ts | 9 + tests/setup.ts | 13 - tests/setupAfterEnv.ts | 4 + utils.nix | 49 +- 18 files changed, 853 insertions(+), 200 deletions(-) delete mode 100644 nix/leveldown.patch create mode 100755 scripts/pkg.js create mode 100644 tests/global.d.ts create mode 100644 tests/setupAfterEnv.ts diff --git a/.github/workflows/codesee-arch-diagram.yml b/.github/workflows/codesee-arch-diagram.yml index 0b75778..fe56ca3 100644 --- a/.github/workflows/codesee-arch-diagram.yml +++ b/.github/workflows/codesee-arch-diagram.yml @@ -54,13 +54,19 @@ jobs: with: ruby-version: '3.0' - # CodeSee Maps Rust support uses a static binary so there's no setup step required. + # We need the rust toolchain because it uses rustc and cargo to inspect the package + - name: Configure Rust 1.x stable + uses: actions-rs/toolchain@v1 + if: ${{ fromJSON(steps.detect-languages.outputs.languages).rust }} + with: + toolchain: stable - name: Generate Map id: generate-map uses: Codesee-io/codesee-map-action@latest with: step: map + api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} github_ref: ${{ github.ref }} languages: ${{ steps.detect-languages.outputs.languages }} @@ -71,7 +77,7 @@ jobs: step: mapUpload api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} github_ref: ${{ github.ref }} - + - name: Insights id: insights uses: Codesee-io/codesee-map-action@latest diff --git a/.gitignore b/.gitignore index ef0d174..84856b0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,13 @@ /dist .env* !.env.example +# nix /result* /builds +# node-gyp +/build +# prebuildify +/prebuilds # Logs logs diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2a33158..81d8820 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,51 +1,245 @@ +workflow: + rules: + # Disable merge request pipelines + - if: $CI_MERGE_REQUEST_ID + when: never + - when: always + default: interruptible: true variables: GIT_SUBMODULE_STRATEGY: recursive + # Cache .npm + NPM_CONFIG_CACHE: "${CI_PROJECT_DIR}/tmp/npm" + # Prefer offline node module installation + NPM_CONFIG_PREFER_OFFLINE: "true" + # `ts-node` has its own cache + TS_CACHED_TRANSPILE_CACHE: "${CI_PROJECT_DIR}/tmp/ts-node-cache" + TS_CACHED_TRANSPILE_PORTABLE: "true" + # Homebrew cache only used by macos runner + HOMEBREW_CACHE: "${CI_PROJECT_DIR}/tmp/Homebrew" + +# Cached directories shared between jobs & pipelines per-branch per-runner +cache: + key: $CI_COMMIT_REF_SLUG + paths: + - ./tmp/npm/ + - ./tmp/ts-node-cache/ + # Homebrew cache is only used by the macos runner + - ./tmp/Homebrew + # `jest` cache is configured in jest.config.js + - ./tmp/jest/ stages: - - check - - build - - quality - - release + - check # Linting, unit tests + - build # Cross-platform library compilation, unit tests + - integration # Cross-platform application bundling, integration tests, and pre-release + - release # Cross-platform distribution and deployment -lint: +image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner + +check:lint: stage: check - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner + needs: [] script: - > - nix-shell -I nixpkgs=./pkgs.nix --packages nodejs --run ' - npm install; + nix-shell --run ' npm run lint; ' + rules: + # Runs on feature and staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH =~ /^(?:feature.*|staging)$/ && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Manually run on commits other than master and ignore version commits + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != 'master' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + when: manual + +check:nix-dry: + stage: check + needs: [] + script: + - nix-build -v -v --dry-run ./release.nix + rules: + # Runs on feature and staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH =~ /^(?:feature.*|staging)$/ && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Manually run on commits other than master and ignore version commits + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != 'master' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + when: manual -test: +check:test: stage: check - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner + needs: [] script: - > - nix-shell -I nixpkgs=./pkgs.nix --packages nodejs --run ' - npm install; - npm run test; + nix-shell --run ' + npm run build --verbose; + npm test -- --ci; ' + artifacts: + when: always + reports: + junit: + - ./tmp/junit.xml + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH =~ /^feature.*$/ && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Manually run on commits other than master and staging and ignore version commits + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH !~ /^(?:master|staging)$/ && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + when: manual -nix-dry: - stage: check - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner +build:merge: + stage: build + needs: [] + # Don't interrupt pr creation job + interruptible: false + allow_failure: true + script: + # Required for `gh pr create` + - git remote add upstream "https://${GITHUB_TOKEN}@github.com/MatrixAI/TypeScript-Demo-Lib-Native.git" + - > + nix-shell -I nixpkgs=./pkgs.nix --packages gitAndTools.gh --run ' + gh pr create \ + --head staging \ + --base master \ + --title "ci: merge staging to master" \ + --body "This is an automatic PR generated by the pipeline CI/CD. This will be automatically fast-forward merged if successful." \ + --assignee "@me" \ + --no-maintainer-edit \ + --repo MatrixAI/TypeScript-Demo-Lib-Native || true; + gh pr comment staging \ + --body "Pipeline Attempt ${CI_PIPELINE_ID} - ${CI_PIPELINE_URL}" \ + --repo MatrixAI/TypeScript-Demo-Lib-Native; + ' + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +build:linux: + stage: build + needs: + - job: check:lint + optional: true + script: + - > + nix-shell --run ' + npm run build --verbose; + npm test -- --ci; + ' + artifacts: + when: always + reports: + junit: + - ./tmp/junit.xml + paths: + # Only the build:linux preserves the dist + - ./dist + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +build:windows: + stage: build + needs: + - job: check:lint + optional: true + tags: + - windows + before_script: + - choco install nodejs --version=16.14.2 -y + - choco install python --version=3.9.12 -y + - refreshenv + script: + - npm config set msvs_version 2019 + - npm install --ignore-scripts + - $env:Path = "$(npm bin);" + $env:Path + - npm run build --verbose + - npm test -- --ci + artifacts: + when: always + reports: + junit: + - ./tmp/junit.xml + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +build:macos: + stage: build + needs: + - job: check:lint + optional: true + tags: + - shared-macos-amd64 + image: macos-11-xcode-12 + variables: + HOMEBREW_NO_INSTALL_UPGRADE: "true" + HOMEBREW_NO_INSTALL_CLEANUP: "true" + before_script: + - brew install node@16 + - brew link --overwrite node@16 + - brew install python@3.9 + - brew link --overwrite python@3.9 + - hash -r script: - - nix-build -v -v --dry-run ./release.nix --attr application - - nix-build -v -v --dry-run ./release.nix --attr docker - - nix-build -v -v --dry-run ./release.nix --attr package.linux.x64.elf - - nix-build -v -v --dry-run ./release.nix --attr package.windows.x64.exe - - nix-build -v -v --dry-run ./release.nix --attr package.macos.x64.macho + - npm install --ignore-scripts + - export PATH="$(npm bin):$PATH" + - npm run build --verbose + - npm test -- --ci + artifacts: + when: always + reports: + junit: + - ./tmp/junit.xml + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -nix: +build:prerelease: stage: build - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner + needs: + - build:linux + - build:windows + - build:macos + # Don't interrupt publishing job + interruptible: false + allow_failure: true + before_script: + - echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./.npmrc + script: + - echo 'Publishing library prerelease' + - > + nix-shell --run ' + npm publish --tag prerelease --access public; + ' + after_script: + - rm -f ./.npmrc + rules: + # Only runs on tag pipeline where the tag is a prerelease version + # This requires dependencies to also run on tag pipeline + # However version tag comes with a version commit + # Dependencies must not run on the version commit + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+-.*[0-9]+$/ + +integration:builds: + stage: integration + needs: + - build:linux + - build:windows + - build:macos script: - mkdir -p ./builds - # nix-specific application target - > build_application="$(nix-build \ --max-jobs "$(nproc)" --cores "$(nproc)" \ @@ -64,19 +258,38 @@ nix: --attr docker \ --attr package.linux.x64.elf \ --attr package.windows.x64.exe \ - --attr package.macos.x64.macho)" + --attr package.macos.x64.macho \ + --attr package.macos.arm64.macho)" - cp -r $builds ./builds/ - only: - - master artifacts: paths: - ./builds/ + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -application run: - stage: quality - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner - dependencies: - - nix +integration:deployment: + stage: integration + needs: + - integration:builds + # Don't interrupt deploying job + interruptible: false + script: + - echo 'Perform service deployment for integration testing' + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +integration:nix: + stage: integration + needs: + - integration:builds + - job: integration:deployment + optional: true script: - > build_application="$( \ @@ -85,14 +298,19 @@ application run: tail -1 \ )" - $build_application/bin/typescript-demo-lib - only: - - master + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -docker run: - stage: quality +integration:docker: + stage: integration + needs: + - integration:builds + - job: integration:deployment + optional: true image: docker:20.10.11 - dependencies: - - nix services: - docker:20.10.11-dind variables: @@ -102,61 +320,230 @@ docker run: script: - image="$(docker load --input ./builds/*docker* | cut -d' ' -f3)" - docker run "$image" - only: - - master + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -linux run: - stage: quality +integration:linux: + stage: integration + needs: + - integration:builds + - job: integration:deployment + optional: true image: ubuntu:latest - dependencies: - - nix script: - for f in ./builds/*-linux-*; do "$f"; done - only: - - master + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -windows run: - stage: quality - dependencies: - - nix - script: - - Get-ChildItem -File ./builds/*-win32-* | ForEach {& $_.FullName} +integration:windows: + stage: integration + needs: + - integration:builds + - job: integration:deployment + optional: true tags: - windows - only: - - master - -macos run: - stage: quality - image: macos-11-xcode-12 - dependencies: - - nix script: - - for f in ./builds/*-macos-*; do "$f"; done - only: - - master + - Get-ChildItem -File ./builds/*-win-* | ForEach {& $_.FullName} + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +integration:macos: + stage: integration + needs: + - integration:builds + - job: integration:deployment + optional: true tags: - shared-macos-amd64 + image: macos-11-xcode-12 + script: + - for f in ./builds/*-macos-x64*; do "$f"; done + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ -packages: +integration:prerelease: + stage: integration + needs: + - integration:builds + - job: integration:nix + optional: true + - job: integration:docker + optional: true + - job: integration:linux + optional: true + - job: integration:windows + optional: true + - job: integration:macos + optional: true + # Don't interrupt publishing job + interruptible: false + allow_failure: true + script: + - echo 'Publishing application prerelease' + - > + nix-shell -I nixpkgs=./pkgs.nix --packages gitAndTools.gh --run ' + if gh release view "$CI_COMMIT_TAG" --repo MatrixAI/TypeScript-Demo-Lib-Native >/dev/null; then \ + gh release \ + upload "$CI_COMMIT_TAG" \ + builds/*.closure.gz \ + builds/*-docker-* \ + builds/*-linux-* \ + builds/*-win-* \ + builds/*-macos-* \ + --clobber \ + --repo MatrixAI/TypeScript-Demo-Lib-Native; \ + else \ + gh release \ + create "$CI_COMMIT_TAG" \ + builds/*.closure.gz \ + builds/*-docker-* \ + builds/*-linux-* \ + builds/*-win-* \ + builds/*-macos-* \ + --title "Build-$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \ + --notes "" \ + --prerelease \ + --target staging \ + --repo MatrixAI/TypeScript-Demo-Lib-Native; \ + fi; + ' + rules: + # Only runs on tag pipeline where the tag is a release version + # This requires dependencies to also run on tag pipeline + # However version tag comes with a version commit + # Dependencies must not run on the version commit + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+-.*[0-9]+$/ + +integration:merge: + stage: integration + needs: + - job: build:merge + artifacts: false + - job: integration:nix + optional: true + artifacts: false + - job: integration:docker + optional: true + artifacts: false + - job: integration:linux + optional: true + artifacts: false + - job: integration:windows + optional: true + artifacts: false + - job: integration:macos + artifacts: false + optional: true + # Don't interrupt pr merging job + interruptible: false + allow_failure: true + variables: + # Ensure that CI/CD is fetching all commits + # this is necessary to checkout origin/master + # and to also merge origin/staging + GIT_DEPTH: 0 + script: + - > + nix-shell -I nixpkgs=./pkgs.nix --packages gitAndTools.gh --run ' + gh pr comment staging \ + --body "Pipeline Succeeded ${CI_PIPELINE_ID} - ${CI_PIPELINE_URL}" \ + --repo MatrixAI/TypeScript-Demo-Lib-Native; + ' + - git remote add upstream "https://${GITHUB_TOKEN}@github.com/MatrixAI/TypeScript-Demo-Lib-Native.git" + - git checkout origin/master + - git merge --ff-only origin/staging + - git push upstream HEAD:master + rules: + # Runs on staging commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'staging' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a prerelease or release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + +release:deployment: stage: release - image: registry.gitlab.com/matrixai/engineering/maintenance/gitlab-runner - dependencies: - - nix + needs: + - job: integration:merge + optional: true + - project: $CI_PROJECT_PATH + job: integration:builds + ref: staging + artifacts: true + # Don't interrupt deploying job + interruptible: false script: + - echo 'Perform service deployment for production' + rules: + # Runs on master commits and ignores version commits + - if: $CI_COMMIT_BRANCH == 'master' && $CI_COMMIT_TITLE !~ /^[0-9]+\.[0-9]+\.[0-9]+(?:-.*[0-9]+)?$/ + # Runs on tag pipeline where the tag is a release version + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ + +release:distribution: + stage: release + needs: + - job: integration:merge + optional: true + - job: release:deployment + optional: true + - project: $CI_PROJECT_PATH + job: build:linux + ref: staging + artifacts: true + - project: $CI_PROJECT_PATH + job: build:windows + ref: staging + artifacts: true + - project: $CI_PROJECT_PATH + job: build:macos + ref: staging + artifacts: true + - project: $CI_PROJECT_PATH + job: integration:builds + ref: staging + artifacts: true + # Don't interrupt publishing job + interruptible: false + allow_failure: true + before_script: + - echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ./.npmrc + script: + - echo 'Publishing library & application release' + - > + nix-shell --run ' + npm publish --access public; + ' - > - nix-shell -I nixpkgs=./pkgs.nix --packages git gitAndTools.gh --run ' - commit="$(git rev-parse --short HEAD)"; + nix-shell -I nixpkgs=./pkgs.nix --packages gitAndTools.gh --run ' gh release \ - create "$commit" \ + create "$CI_COMMIT_TAG" \ builds/*.closure.gz \ + builds/*-docker-* \ builds/*-linux-* \ - builds/*-win32-* \ + builds/*-win-* \ builds/*-macos-* \ --title "Build-$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \ - --prerelease \ --notes "" \ - --repo MatrixAI/TypeScript-Demo-Lib; + --target master \ + --repo MatrixAI/TypeScript-Demo-Lib-Native; ' - only: - - master + after_script: + - rm -f ./.npmrc + rules: + # Only runs on tag pipeline where the tag is a release version + # This requires dependencies to also run on tag pipeline + # However version tag comes with a version commit + # Dependencies must not run on the version commit + - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ diff --git a/.npmignore b/.npmignore index 6c68156..6e59877 100644 --- a/.npmignore +++ b/.npmignore @@ -1,16 +1,15 @@ .* +/*.nix /nix -/pkgs.nix -/default.nix -/shell.nix -/release.nix /tsconfig.json /tsconfig.build.json /jest.config.js +/scripts /src /tests /tmp /docs /benches +/build /builds /dist/tsbuildinfo diff --git a/default.nix b/default.nix index 623b39d..283de76 100644 --- a/default.nix +++ b/default.nix @@ -12,38 +12,44 @@ let packageName = utils.node2nixDev.packageName; } '' - mkdir -p "$out/lib/node_modules/${utils.node2nixDev.packageName}" + mkdir -p "$out/lib/node_modules/$packageName" # copy the package.json cp \ - "${utils.node2nixDev}/lib/node_modules/${utils.node2nixDev.packageName}/package.json" \ - "$out/lib/node_modules/${utils.node2nixDev.packageName}/" + "${utils.node2nixDev}/lib/node_modules/$packageName/package.json" \ + "$out/lib/node_modules/$packageName/" + # copy the native addons + if [ -d "${utils.node2nixDev}/lib/node_modules/$packageName/prebuilds" ]; then + cp -r \ + "${utils.node2nixDev}/lib/node_modules/$packageName/prebuilds" \ + "$out/lib/node_modules/$packageName/" + fi # copy the dist cp -r \ - "${utils.node2nixDev}/lib/node_modules/${utils.node2nixDev.packageName}/dist" \ - "$out/lib/node_modules/${utils.node2nixDev.packageName}/" + "${utils.node2nixDev}/lib/node_modules/$packageName/dist" \ + "$out/lib/node_modules/$packageName/" # copy over the production dependencies if [ -d "${utils.node2nixProd}/lib/node_modules" ]; then cp -r \ "${utils.node2nixProd}/lib/node_modules" \ - "$out/lib/node_modules/${utils.node2nixDev.packageName}/" + "$out/lib/node_modules/$packageName/" fi # symlink bin executables if [ \ - "$(${jq}/bin/jq 'has("bin")' "$out/lib/node_modules/${utils.node2nixDev.packageName}/package.json")" \ + "$(${jq}/bin/jq 'has("bin")' "$out/lib/node_modules/$packageName/package.json")" \ == \ "true" \ ]; then mkdir -p "$out/bin" while IFS= read -r bin_name && IFS= read -r bin_path; do # make files executable - chmod a+x "$out/lib/node_modules/${utils.node2nixDev.packageName}/$bin_path" + chmod a+x "$out/lib/node_modules/$packageName/$bin_path" # create the symlink ln -s \ - "../lib/node_modules/${utils.node2nixDev.packageName}/$bin_path" \ + "../lib/node_modules/$packageName/$bin_path" \ "$out/bin/$bin_name" done < <( ${jq}/bin/jq -r 'select(.bin != null) | .bin | to_entries[] | (.key, .value)' \ - "$out/lib/node_modules/${utils.node2nixDev.packageName}/package.json" + "$out/lib/node_modules/$packageName/package.json" ) fi ''; diff --git a/jest.config.js b/jest.config.js index ca8aa09..d398835 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,33 @@ +const path = require('path'); const { pathsToModuleNameMapper } = require('ts-jest'); const { compilerOptions } = require('./tsconfig'); +const moduleNameMapper = pathsToModuleNameMapper( + compilerOptions.paths, + { prefix: "/src/" } +); + +// Global variables that are shared across the jest worker pool +// These variables must be static and serializable +const globals = { + // Absolute directory to the project root + projectDir: __dirname, + // Absolute directory to the test root + testDir: path.join(__dirname, 'tests'), + // Default asynchronous test timeout + defaultTimeout: 20000, + // Timeouts rely on setTimeout which takes 32 bit numbers + maxTimeout: Math.pow(2, 31) - 1, +}; + +// The `globalSetup` and `globalTeardown` cannot access the `globals` +// They run in their own process context +// They can however receive the process environment +// Use `process.env` to set variables + module.exports = { + testEnvironment: "node", + cacheDirectory: '/tmp/jest', verbose: true, roots: [ "/tests" @@ -10,15 +36,31 @@ module.exports = { "**/?(*.)+(spec|test|unit.test).+(ts|tsx|js)" ], transform: { - "^.+\\.tsx?$": "ts-jest" + "^.+\\.tsx?$": "ts-jest", + "^.+\\.jsx?$": "babel-jest" }, - setupFiles: [ - "/tests/setup.ts" + reporters: [ + "default", + [ + "jest-junit", + { outputDirectory: "./tmp" } + ] ], + globals, + // Global setup script executed once before all test files globalSetup: "/tests/globalSetup.ts", + // Global teardown script executed once after all test files globalTeardown: "/tests/globalTeardown.ts", - moduleNameMapper: pathsToModuleNameMapper( - compilerOptions.paths, - { prefix: "/src/" } - ) + // Setup files are executed before each test file + // Can access globals + setupFiles: [ + "/tests/setup.ts" + ], + // Setup files after env are executed before each test file + // after the jest test environment is installed + // Can access globals + setupFilesAfterEnv: [ + "/tests/setupAfterEnv.ts" + ], + moduleNameMapper: moduleNameMapper }; diff --git a/nix/leveldown.patch b/nix/leveldown.patch deleted file mode 100644 index 0d35bab..0000000 --- a/nix/leveldown.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- dictionary/leveldown.js 2021-08-04 15:43:31.836337623 +1000 -+++ dictionary/leveldown_.js 2021-08-04 15:43:11.977266316 +1000 -@@ -1,10 +1,3 @@ - 'use strict'; - --module.exports = { -- pkg: { -- patches: { -- 'binding.js': ['__dirname', "require('path').dirname(process.execPath)"], -- }, -- deployFiles: [['prebuilds', 'prebuilds', 'directory']], -- }, --}; -+module.exports = {}; diff --git a/package-lock.json b/package-lock.json index e0c6266..bcb33af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,10 +28,11 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.2.5", + "jest-junit": "^13.2.0", "jest-mock-process": "^1.4.0", - "node-gyp-build": "4.4.0", "pkg": "5.6.0", "prettier": "^2.6.2", + "rimraf": "^3.0.2", "ts-jest": "^27.0.5", "ts-node": "^10.4.0", "tsconfig-paths": "^3.9.0", @@ -4521,6 +4522,21 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/jest-junit": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-13.2.0.tgz", + "integrity": "sha512-B0XNlotl1rdsvFZkFfoa19mc634+rrd8E4Sskb92Bb8MmSXeWV9XJGUyctunZS1W410uAxcyYuPUGVnbcOH8cg==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/jest-leak-detector": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", @@ -5356,6 +5372,18 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -7542,6 +7570,12 @@ } } }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -11004,6 +11038,18 @@ "throat": "^6.0.1" } }, + "jest-junit": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-13.2.0.tgz", + "integrity": "sha512-B0XNlotl1rdsvFZkFfoa19mc634+rrd8E4Sskb92Bb8MmSXeWV9XJGUyctunZS1W410uAxcyYuPUGVnbcOH8cg==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + } + }, "jest-leak-detector": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", @@ -11657,6 +11703,12 @@ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -13270,6 +13322,12 @@ "dev": true, "requires": {} }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index 628f2cb..2d8df79 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,6 @@ "types": "dist/index.d.ts", "pkg": { "assets": [ - "node_modules/leveldown/**/*", - "node_modules/utp-native/**/*", - "node_modules/fd-lock/**/*", "dist/**/*.json" ], "scripts": [ @@ -26,12 +23,13 @@ }, "scripts": { "prepare": "tsc -p ./tsconfig.build.json", - "build": "rm -r ./dist || true; tsc -p ./tsconfig.build.json", + "build": "rimraf ./dist && tsc -p ./tsconfig.build.json", "ts-node": "ts-node -r tsconfig-paths/register", "test": "jest", "lint": "eslint '{src,tests}/**/*.{js,ts}'", "lintfix": "eslint '{src,tests}/**/*.{js,ts}' --fix", - "docs": "rm -r ./docs || true; typedoc --gitRevision master --tsconfig ./tsconfig.build.json --out ./docs src", + "docs": "rimraf ./docs && typedoc --gitRevision master --tsconfig ./tsconfig.build.json --out ./docs src", + "pkg": "./scripts/pkg.js --no-dict=leveldown.js", "typescript-demo-lib": "ts-node -r tsconfig-paths/register --compiler typescript-cached-transpile --transpile-only src/bin/typescript-demo-lib.ts" }, "dependencies": { @@ -51,10 +49,11 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.2.5", + "jest-junit": "^13.2.0", "jest-mock-process": "^1.4.0", - "node-gyp-build": "4.4.0", "pkg": "5.6.0", "prettier": "^2.6.2", + "rimraf": "^3.0.2", "ts-jest": "^27.0.5", "ts-node": "^10.4.0", "tsconfig-paths": "^3.9.0", diff --git a/release.nix b/release.nix index f682e50..46131f3 100644 --- a/release.nix +++ b/release.nix @@ -8,21 +8,16 @@ let name = "${utils.basename}-${version}-linux-${arch}"; version = utils.node2nixDev.version; src = "${utils.node2nixDev}/lib/node_modules/${utils.node2nixDev.packageName}"; - buildInputs = [ - utils.pkg - ]; + nativeBuildInputs = [ nodejs ]; PKG_CACHE_PATH = utils.pkgCachePath; PKG_IGNORE_TAG = 1; - # ensure that native modules are built from source - npm_config_build_from_source = "true"; buildPhase = '' - cp ${./package.json} package.json - pkg . \ - --targets node${utils.nodeVersion}-linux-${arch} \ - --no-bytecode \ - --public \ - --public-packages "*" \ - --output out + npm run pkg -- \ + --output=out \ + --executable=typescript-demo-lib \ + --node-version=${utils.nodeVersion} \ + --platform=linux \ + --arch=${arch} ''; installPhase = '' cp out $out @@ -31,24 +26,19 @@ let }; buildExe = arch: stdenv.mkDerivation rec { - name = "${utils.basename}-${version}-win32-${arch}.exe"; + name = "${utils.basename}-${version}-win-${arch}.exe"; version = utils.node2nixDev.version; src = "${utils.node2nixDev}/lib/node_modules/${utils.node2nixDev.packageName}"; - buildInputs = [ - utils.pkg - ]; + nativeBuildInputs = [ nodejs ]; PKG_CACHE_PATH = utils.pkgCachePath; PKG_IGNORE_TAG = 1; - # ensure that native modules are built from source - npm_config_build_from_source = "true"; buildPhase = '' - cp ${./package.json} package.json - pkg . \ - --targets node${utils.nodeVersion}-win-${arch} \ - --no-bytecode \ - --public \ - --public-packages "*" \ - --output out.exe + npm run pkg -- \ + --output=out.exe \ + --executable=typescript-demo-lib \ + --node-version=${utils.nodeVersion} \ + --platform=win32 \ + --arch=${arch} ''; installPhase = '' cp out.exe $out @@ -60,21 +50,16 @@ let name = "${utils.basename}-${version}-macos-${arch}"; version = utils.node2nixDev.version; src = "${utils.node2nixDev}/lib/node_modules/${utils.node2nixDev.packageName}"; - buildInputs = [ - utils.pkg - ]; + nativeBuildInputs = [ nodejs ]; PKG_CACHE_PATH = utils.pkgCachePath; PKG_IGNORE_TAG = 1; - # ensure that native modules are built from source - npm_config_build_from_source = "true"; buildPhase = '' - cp ${./package.json} package.json - pkg . \ - --targets node${utils.nodeVersion}-macos-${arch} \ - --no-bytecode \ - --public \ - --public-packages "*" \ - --output out + npm run pkg -- \ + --output=out \ + --executable=typescript-demo-lib \ + --node-version=${utils.nodeVersion} \ + --platform=darwin \ + --arch=${arch} ''; installPhase = '' cp out $out @@ -110,6 +95,9 @@ in x64 = { macho = buildMacho "x64"; }; + arm64 = { + macho = buildMacho "arm64"; + }; }; }; } diff --git a/scripts/pkg.js b/scripts/pkg.js new file mode 100755 index 0000000..d5e55c1 --- /dev/null +++ b/scripts/pkg.js @@ -0,0 +1,174 @@ +#!/usr/bin/env node + +const os = require('os'); +const fs = require('fs'); +const path = require('path'); +const process = require('process'); +const crypto = require('crypto'); +const child_process = require('child_process'); +const packageJSON = require('../package.json'); + +/** + * Supported platforms + * Maps os.platform() to pkg platform + */ +const platforms = { + 'linux': 'linux', + 'win32': 'win', + 'darwin': 'macos', +}; + +/** + * Supported architectures + * Maps os.arch() to pkg arch + */ +const archs = { + 'x64': 'x64', + 'arm64': 'arm64', +}; + +function randomString(l) { + return crypto + .randomBytes(l) + .toString('base64') + .replace(/\//, '_'); +} + +async function find(dirPath, pattern) { + const found = []; + let entries; + try { + entries = await fs.promises.readdir(dirPath); + } catch (e) { + if (e.code === 'ENOENT') { + return found ; + } + throw e; + } + for (const entry of entries) { + const entryPath = path.join(dirPath, entry); + const stat = await fs.promises.lstat(entryPath); + if (stat.isDirectory()) { + found.push(...(await find(entryPath, pattern))); + } else if (pattern.test(entryPath)) { + found.push(entryPath); + } + } + return found; +}; + +async function main(argv = process.argv) { + argv = argv.slice(2); + let outPath; + let binTarget; + let nodeVersion = process.versions.node.match(/\d+/)[0]; + let platform = os.platform(); + let arch = os.arch(); + const restArgs = []; + while (argv.length > 0) { + const option = argv.shift(); + let match; + if (match = option.match(/--output(?:=(.+)|$)/)) { + outPath = match[1] ?? argv.shift(); + } else if (match = option.match(/--bin(?:=(.+)|$)/)) { + binTarget = match[1] ?? argv.shift(); + } else if (match = option.match(/--node-version(?:=(.+)|$)/)) { + nodeVersion = match[1] ?? argv.shift(); + } else if (match = option.match(/--platform(?:=(.+)|$)/)) { + platform = match[1] ?? argv.shift(); + } else if (match = option.match(/--arch(?:=(.+)|$)/)) { + arch = match[1] ?? argv.shift(); + } else { + restArgs.push(option); + } + } + let entryPoint; + if (binTarget == null) { + entryPoint = Object.values(packageJSON.bin ?? {})[0]; + } else { + entryPoint = packageJSON.bin[binTarget]; + } + if (entryPoint == null) { + throw new Error('Bin executable is required'); + } + if (typeof outPath !== 'string') { + throw new Error('Output path is required'); + } + if (entryPoint == null) { + throw new Error(`Unknown bin target: ${binTarget}`); + } + if (isNaN(parseInt(nodeVersion))) { + throw new Error(`Unsupported node version: ${nodeVersion}`); + } + if (!(platform in platforms)) { + throw new Error(`Unsupported platform: ${platform}`); + } + if (!(arch in archs)) { + throw new Error(`Unsupported architecture: ${arch}`); + } + // Monkey patch the os.platform and os.arch for node-gyp-build + os.platform = () => platform; + os.arch = () => arch; + const nodeGypBuild = require('node-gyp-build'); + const pkgConfig = packageJSON.pkg ?? {}; + pkgConfig.assets = pkgConfig.assets ?? {}; + const npmLsOut = child_process.execFileSync( + 'npm', + ['ls', '--all', '--prod', '--parseable'], + { + windowsHide: true, + encoding: 'utf-8' + } + ); + const nodePackages = npmLsOut.trim().split('\n'); + const projectRoot = path.join(__dirname, '..'); + for (const nodePackage of nodePackages) { + // If `build` or `prebuilds` directory exists with a `.node` file + // then we expect to find the appropriate native addon + // The `node-gyp-build` will look in these 2 directories + const buildPath = path.join(nodePackage, 'build'); + const prebuildsPath = path.join(nodePackage, 'prebuilds'); + const buildFinds = await find(buildPath, /.node$/); + const prebuildsFinds = await find(prebuildsPath, /.node$/); + if (buildFinds.length > 0 || prebuildsFinds.length > 0) { + let nativeAddonPath = nodeGypBuild.path(nodePackage); + // Must use relative paths + // so that assets are added relative to the project + nativeAddonPath = path.relative(projectRoot, nativeAddonPath); + pkgConfig.assets.push(nativeAddonPath); + } + } + console.error('Configured pkg with:'); + console.error(pkgConfig); + // The pkg config must be in the same directory as the `package.json` + // otherwise the relative paths won't work + const pkgConfigPath = path.join(projectRoot, 'pkg.json'); + await fs.promises.writeFile(pkgConfigPath, JSON.stringify(pkgConfig)); + const pkgPlatform = platforms[platform]; + const pkgArch = archs[arch]; + const pkgArgs = [ + entryPoint, + `--config=${pkgConfigPath}`, + `--targets=node${nodeVersion}-${pkgPlatform}-${pkgArch}`, + '--no-bytecode', + '--no-native-build', + '--public', + '--public-packages=\'*\'', + `--output=${outPath}`, + ...restArgs + ]; + console.error('Running pkg:') + console.error(['pkg', ...pkgArgs].join(' ')); + child_process.execFileSync( + 'pkg', + pkgArgs, + { + stdio: ['inherit', 'inherit', 'inherit'], + windowsHide: true, + encoding: 'utf-8' + } + ); + await fs.promises.rm(pkgConfigPath); +} + +void main(); diff --git a/shell.nix b/shell.nix index 49a28a6..a8fbad6 100644 --- a/shell.nix +++ b/shell.nix @@ -4,11 +4,10 @@ with pkgs; let utils = callPackage ./utils.nix {}; in - pkgs.mkShell { + mkShell { nativeBuildInputs = [ nodejs utils.node2nix - utils.pkg ]; PKG_CACHE_PATH = utils.pkgCachePath; PKG_IGNORE_TAG = 1; @@ -24,18 +23,10 @@ in # Built executables and NPM executables export PATH="$(pwd)/dist/bin:$(npm bin):$PATH" - # pkg is installed in package.json - # this ensures that in nix-shell we are using the nix packaged versions - export PATH="${lib.makeBinPath - [ - utils.pkg - ] - }:$PATH" - # Enables npm link export npm_config_prefix=~/.npm - npm install + npm install --ignore-scripts set +v ''; diff --git a/src/bin/typescript-demo-lib.ts b/src/bin/typescript-demo-lib.ts index 2e0986a..8e90ff1 100755 --- a/src/bin/typescript-demo-lib.ts +++ b/src/bin/typescript-demo-lib.ts @@ -13,7 +13,7 @@ import { version, test } from '../utils'; async function main(argv = process.argv): Promise { // Print out command-line arguments - argv = argv.slice(2); // Removing prepended file paths. + argv = argv.slice(2); // Removing prepended file paths process.stdout.write('[' + argv.slice(0, 2).toString() + ']\n'); // Create a new Library with the value someParam = 'new library' diff --git a/src/lib/test-level.ts b/src/lib/test-level.ts index f7cd5eb..0210067 100644 --- a/src/lib/test-level.ts +++ b/src/lib/test-level.ts @@ -11,6 +11,7 @@ async function testLevel(dir: string) { await db.put(key, value); process.stdout.write(key + ' ' + (await db.get(key)) + '\n'); process.stdout.write('\n'); + await db.close(); } export default testLevel; diff --git a/tests/global.d.ts b/tests/global.d.ts new file mode 100644 index 0000000..85365f1 --- /dev/null +++ b/tests/global.d.ts @@ -0,0 +1,9 @@ +/* eslint-disable no-var */ +/** + * Follows the globals in jest.config.ts + * @module + */ +declare var projectDir: string; +declare var testDir: string; +declare var defaultTimeout: number; +declare var maxTimeout: number; diff --git a/tests/setup.ts b/tests/setup.ts index fdcbc88..e69de29 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -1,13 +0,0 @@ -import path from 'path'; - -declare global { - namespace NodeJS { - interface Global { - projectDir: string; - testDir: string; - } - } -} - -global.projectDir = path.join(__dirname, '../'); -global.testDir = __dirname; diff --git a/tests/setupAfterEnv.ts b/tests/setupAfterEnv.ts new file mode 100644 index 0000000..6d49ee9 --- /dev/null +++ b/tests/setupAfterEnv.ts @@ -0,0 +1,4 @@ +// Default timeout per test +// some tests may take longer in which case you should specify the timeout +// explicitly for each test by using the third parameter of test function +jest.setTimeout(global.defaultTimeout); diff --git a/utils.nix b/utils.nix index e63e463..31f0b10 100644 --- a/utils.nix +++ b/utils.nix @@ -2,7 +2,6 @@ , linkFarm , nix-gitignore , nodejs -, nodePackages , pkgs , lib , fetchurl @@ -12,7 +11,7 @@ rec { # this removes the org scoping basename = builtins.baseNameOf node2nixDev.packageName; - src = nix-gitignore.gitignoreSource [".git"] ./.; + src = nix-gitignore.gitignoreSource [".git" "/*.nix"] ./.; nodeVersion = builtins.elemAt (lib.versions.splitVersion nodejs.version) 0; # custom node2nix directly from GitHub node2nixSrc = fetchFromGitHub { @@ -33,21 +32,30 @@ rec { --composition $out/default.nix \ --nodejs-${nodeVersion} ''; - # the shell attribute has the nodeDependencies, whereas the package does not - node2nixProd = ( - (import (node2nixDrv false) { inherit pkgs nodejs; }).shell.override (attrs: { - buildInputs = attrs.buildInputs ++ [ nodePackages.node-gyp-build ]; - dontNpmInstall = true; - }) - ).nodeDependencies; - node2nixDev = (import (node2nixDrv true) { inherit pkgs nodejs; }).package.override (attrs: { + node2nixProd = (import (node2nixDrv false) { inherit pkgs nodejs; }).nodeDependencies.override (attrs: { + # Use filtered source src = src; - buildInputs = attrs.buildInputs ++ [ nodePackages.node-gyp-build ]; + # Do not run build scripts during npm rebuild and npm install + npmFlags = "--ignore-scripts"; + # Do not run npm install, dependencies are installed by nix dontNpmInstall = true; + }); + node2nixDev = (import (node2nixDrv true) { inherit pkgs nodejs; }).package.override (attrs: { + # Use filtered source + src = src; + # Do not run build scripts during npm rebuild and npm install + # They will be executed in the postInstall hook + npmFlags = "--ignore-scripts"; + # Show full compilation flags + NIX_DEBUG = 1; + # Don't set rpath for native addons + # Native addons do not require their own runtime search path + # because they dynamically loaded by the nodejs runtime + NIX_DONT_SET_RPATH = true; + NIX_NO_SELF_RPATH = true; postInstall = '' - # The dependencies were prepared in the installphase - # See `node2nix` generated `node-env.nix` for details - npm run build + # This will setup the typescript build + npm --nodedir=${nodejs} run build ''; }); pkgBuilds = { @@ -64,6 +72,10 @@ rec { url = "https://github.com/vercel/pkg-fetch/releases/download/v3.3/node-v16.14.2-macos-x64"; sha256 = "1hq7v40vzc2bfr29y71lm0snaxcc8rys5w0da7pi5nmx4pyybc2v"; }; + "macos-arm64" = fetchurl { + url = "https://github.com/vercel/pkg-fetch/releases/download/v3.3/node-v16.14.2-macos-arm64"; + sha256 = "05q350aw7fhirmlqg6ckyi5hg9pwcvs0w5r047r8mf3ivy1hxra4"; + }; }; }; pkgCachePath = @@ -85,10 +97,9 @@ rec { name = fetchedName pkgBuild.macos-x64.name; path = pkgBuild.macos-x64; } + { + name = fetchedName pkgBuild.macos-arm64.name; + path = pkgBuild.macos-arm64; + } ]; - pkg = nodePackages.pkg.override { - postFixup = '' - patch -p0 < ${./nix/leveldown.patch} - ''; - }; }