fiscal 0.6.0

Brazilian fiscal document library (NF-e/NFC-e) — Rust port of sped-nfe
Documentation
name: Publish @fiscal-rs/node to npm

# Runs on every push to master.
# Compares the highest crate version with npm — if different, publishes.
on:
  push:
    branches:
      - master

permissions:
  contents: read

env:
  MACOSX_DEPLOYMENT_TARGET: '10.13'

jobs:
  check-version:
    name: Check if npm publish needed
    runs-on: ubuntu-latest
    outputs:
      should_publish: ${{ steps.check.outputs.should_publish }}
      version: ${{ steps.check.outputs.version }}
    steps:
      - uses: actions/checkout@v6

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Determine version from dependency crates
        id: check
        run: |
          CORE=$(grep '^version' crates/fiscal-core/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          SEFAZ=$(grep '^version' crates/fiscal-sefaz/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          CRYPTO=$(grep '^version' crates/fiscal-crypto/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          FACADE=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')

          echo "fiscal-core: $CORE | fiscal-sefaz: $SEFAZ | fiscal-crypto: $CRYPTO | fiscal: $FACADE"

          VERSION=$(printf '%s\n' "$CORE" "$SEFAZ" "$CRYPTO" "$FACADE" | sort -V | tail -1)
          echo "Resolved npm version: $VERSION"

          NPM_VERSION=$(curl -s https://registry.npmjs.org/@fiscal-rs/node/latest | jq -r '.version // "0.0.0"')
          echo "Current npm version: $NPM_VERSION"

          if [ "$VERSION" != "$NPM_VERSION" ]; then
            echo "should_publish=true" >> $GITHUB_OUTPUT
          else
            echo "should_publish=false" >> $GITHUB_OUTPUT
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT

  build:
    name: Build ${{ matrix.target }}
    needs: check-version
    if: needs.check-version.outputs.should_publish == 'true'
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        working-directory: crates/fiscal-napi
    strategy:
      fail-fast: false
      matrix:
        include:
          # Native builds
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-apple-darwin
            os: macos-latest
          # macOS x86_64 cross-compiled from ARM64 runner
          - target: x86_64-apple-darwin
            os: macos-latest
            cross: true
          # Native Windows build
          - target: x86_64-pc-windows-msvc
            os: windows-latest
          # Cross-compiled Linux builds (use --use-napi-cross)
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-latest
            cross: true
          # Cross-compiled Windows ARM64
          - target: aarch64-pc-windows-msvc
            os: windows-latest
            cross: true

    steps:
      - uses: actions/checkout@v6

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install dependencies
        run: bun install

      # Build: use --use-napi-cross for cross targets, plain build for native
      # OpenSSL is vendored (compiled from source) so no system dependency needed
      - name: Build native addon
        if: ${{ !matrix.cross }}
        run: bunx napi build --release --platform --target ${{ matrix.target }}

      - name: Build native addon (cross)
        if: ${{ matrix.cross }}
        run: bunx napi build --release --platform --target ${{ matrix.target }} --use-napi-cross

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.target }}
          path: crates/fiscal-napi/fiscal.*.node
          if-no-files-found: error

  publish:
    name: Publish to npm
    runs-on: ubuntu-latest
    needs: [check-version, build]
    steps:
      - uses: actions/checkout@v6

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Configure npm registry auth
        run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Install dependencies
        working-directory: crates/fiscal-napi
        run: bun install

      - name: Sync version to package.json
        working-directory: crates/fiscal-napi
        run: |
          VERSION=${{ needs.check-version.outputs.version }}
          jq --arg v "$VERSION" '.version = $v | .optionalDependencies |= with_entries(.value = $v)' package.json > package.json.tmp && mv package.json.tmp package.json
          for pkg in npm/*/package.json; do
            jq --arg v "$VERSION" '.version = $v' "$pkg" > "$pkg.tmp" && mv "$pkg.tmp" "$pkg"
          done

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: crates/fiscal-napi/artifacts

      - name: Move artifacts to npm dirs
        working-directory: crates/fiscal-napi
        run: bunx napi artifacts --output-dir artifacts

      - name: List packages
        working-directory: crates/fiscal-napi
        run: |
          echo "Version: ${{ needs.check-version.outputs.version }}"
          for d in npm/*/; do
            echo "$d: $(ls "$d"fiscal.*.node 2>/dev/null | wc -l) binary"
          done

      - name: Prepare platform packages
        working-directory: crates/fiscal-napi
        run: bunx napi prepublish --no-gh-release --skip-optional-publish -t npm

      - name: Publish platform packages
        working-directory: crates/fiscal-napi
        run: |
          for pkg in npm/*/; do
            cd "$pkg"
            npm publish --access public || true
            cd ../..
          done

      - name: Publish main package
        working-directory: crates/fiscal-napi
        run: npm publish --access public