# Copyright © SixtyFPS GmbH <info@slint.dev>
# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

name: Publish npm package to npm registry

on:
    workflow_dispatch:
        inputs:
            private:
                type: boolean
                default: true
                required: false
                description: "Private build? True means artifacts are only built. False means the package will be published to the NPM registry"
            release:
                type: boolean
                default: false
                required: false
                description: "Release? Enable options for building binaries for a release (i.e. apply a nightly tag, nightly version)"

    schedule:
        - cron: "0 5 * * *"

permissions:
    id-token: write  # Required for OIDC
    contents: read

jobs:
    determine_version:
        runs-on: ubuntu-latest
        outputs:
            PKG_VERSION: ${{ steps.mkversion.outputs.PKG_VERSION }}
        steps:
            - uses: actions/checkout@v6
            - uses: pnpm/action-setup@v5.0.0
              with:
                version: 10.29.3
            - uses: actions/setup-node@v6
              with:
                package-manager-cache: false
            - name: Determine version
              id: mkversion
              env:
                  RELEASE_INPUT: ${{ github.event.inputs.release }}
              working-directory: api/node
              run: |
                  version=`pnpm pkg get version | jq -r`
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      nightly_version_suffix=`git log -1 --format=%cd --date="format:%Y%m%d%H"`
                      version="$version-nightly.$nightly_version_suffix"
                  fi
                  echo $version
                  echo "PKG_VERSION=$version" >> $GITHUB_OUTPUT

    build_binaries:
        env:
            PKG_VERSION: ${{ needs.determine_version.outputs.PKG_VERSION }}
            RELEASE_INPUT: ${{ github.event.inputs.release }}
            MACOSX_DEPLOYMENT_TARGET: "11.0"
        strategy:
            matrix:
                include:
                    - os: ubuntu-22.04
                      rust-target: x86_64-unknown-linux-gnu
                      napi-rs-target: linux-x64-gnu
                    - os: ubuntu-22.04-arm
                      rust-target: aarch64-unknown-linux-gnu
                      napi-rs-target: linux-arm64-gnu
                    - os: macos-26
                      rust-target: aarch64-apple-darwin
                      napi-rs-target: darwin-arm64
                    - os: windows-2022
                      rust-target: x86_64-pc-windows-msvc
                      napi-rs-target: win32-x64-msvc
                      msvc-arch: x64
                    - os: windows-11-arm
                      rust-target: aarch64-pc-windows-msvc
                      napi-rs-target: win32-arm64-msvc
                      msvc-arch: arm64
        needs: determine_version
        runs-on: ${{ matrix.os }}
        steps:
            - uses: actions/checkout@v6
            - uses: ./.github/actions/install-linux-dependencies
              with:
                  old-ubuntu: true
            - uses: ./.github/actions/install-skia-dependencies
            - uses: ilammy/msvc-dev-cmd@v1
              if: runner.os == 'Windows'
              with:
                  arch: ${{ matrix.msvc-arch }}
            - uses: ./.github/actions/setup-rust
              with:
                  target: ${{ matrix.rust-target }}
            - uses: pnpm/action-setup@v5.0.0
              with:
                version: 10.29.3
            # Setup .npmrc file to publish to npm
            - uses: actions/setup-node@v6
              with:
                  node-version: "24"
                  registry-url: "https://registry.npmjs.org"
                  package-manager-cache: false
            - uses: pnpm/action-setup@v5.0.0
              with:
                version: 10.29.3
            - name: Set version
              working-directory: api/node
              shell: bash
              run: |
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      pnpm version $PKG_VERSION
                  fi
            - uses: baptiste0928/cargo-install@v3
              with:
                  crate: taplo-cli
            - name: Prepare feature config for binaries
              working-directory: api/node
              shell: bash
              run: |
                cat Cargo.toml | taplo format --option column_width=100000 --stdin-filepath=Cargo.toml - | \
                  perl -p -e 's,^\s*default\s*=.*,,' | \
                  perl -p -e 's,# binaries:\s?,,' > Cargo.toml.new
                cat Cargo.toml.new | taplo format --stdin-filepath=Cargo.toml - > Cargo.toml
                rm Cargo.toml.new
                taplo get -f Cargo.toml features.default
            - name: Build binary
              shell: bash
              working-directory: api/node
              run: |
                  pnpm install --ignore-scripts
                  pnpm run build --target ${{ matrix.rust-target }}
            - name: Create package
              shell: bash
              working-directory: api/node
              run: |
                  npx napi create-npm-dirs --npm-dir . -c ./binaries.json
                  mv slint-ui.${{ matrix.napi-rs-target }}.node ${{ matrix.napi-rs-target }}/
                  cd ${{ matrix.napi-rs-target }}/
                  pnpm pkg set repository.type=git
                  pnpm pkg set repository.url=https://github.com/slint-ui/slint
                  pnpm pack
            - name: Upload artifact
              uses: actions/upload-artifact@v7
              with:
                  name: binaries-${{ matrix.rust-target }}
                  path: "api/node/${{ matrix.napi-rs-target }}/*.tgz"

    build_and_publish_npm_package:
        runs-on: ubuntu-22.04
        needs: [determine_version, build_binaries]
        env:
            PKG_VERSION: ${{ needs.determine_version.outputs.PKG_VERSION }}
            RELEASE_INPUT: ${{ github.event.inputs.release }}
        steps:
            - uses: actions/checkout@v6
            - uses: ./.github/actions/install-linux-dependencies
            - uses: ./.github/actions/setup-rust
            - uses: pnpm/action-setup@v5.0.0
              with:
                version: 10.29.3
            # Setup .npmrc file to publish to npm
            - uses: actions/setup-node@v6
              with:
                  node-version: "24"
                  registry-url: "https://registry.npmjs.org"
                  package-manager-cache: false
            - name: Update npm as Node 20.x might not have an new enough npm for trusted publishing
              run: npm install -g npm@latest
            - name: Set version
              working-directory: api/node
              run: |
                  if [ "$RELEASE_INPUT" != "true" ]; then
                      pnpm version $PKG_VERSION
                  fi
            - name: Select git revision
              if: github.event.inputs.release != 'true'
              run: |
                  echo "PKG_EXTRA_ARGS=--sha1=$GITHUB_SHA" >> $GITHUB_ENV
                  echo "PUBLISH_TAG=--tag nightly" >> $GITHUB_ENV
            - name: Compile index.js and index.d.ts
              working-directory: api/node
              run: |
                  pnpm install
                  pnpm run build
                  pnpm run compile
            - name: Prepare binary packages
              working-directory: api/node
              run: |
                  npx napi create-npm-dirs --npm-dir . -c ./binaries.json
            - name: Download artifacts
              uses: actions/download-artifact@v8
              with:
                  name: binaries-x86_64-unknown-linux-gnu
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v8
              with:
                  name: binaries-aarch64-unknown-linux-gnu
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v8
              with:
                  name: binaries-aarch64-apple-darwin
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v8
              with:
                  name: binaries-x86_64-pc-windows-msvc
                  path: api/node/
            - name: Download artifacts
              uses: actions/download-artifact@v8
              with:
                  name: binaries-aarch64-pc-windows-msvc
                  path: api/node/
            - name: Add binary dependencies
              working-directory: api/node
              run: |
                  for package in @slint-ui/slint-ui-binary-linux-x64-gnu @slint-ui/slint-ui-binary-linux-arm64-gnu @slint-ui/slint-ui-binary-darwin-arm64 @slint-ui/slint-ui-binary-win32-x64-msvc @slint-ui/slint-ui-binary-win32-arm64-msvc; do
                      jq --arg pkg "$package" --arg version "$PKG_VERSION" '.optionalDependencies[$pkg]=$version' package.json > new.json
                      mv new.json package.json
                  done
            - name: Build package
              run: |
                  cargo xtask node_package $PKG_EXTRA_ARGS
            - name: "Upload npm package Artifact"
              uses: actions/upload-artifact@v7
              with:
                  name: slint-ui-node-package
                  path: |
                      api/node/slint-ui-${{ env.PKG_VERSION }}.tgz
            - name: Smoke test package to see if it builds at least
              run: |
                  mkdir /tmp/nodetest
                  cd /tmp/nodetest
                  echo "neverBuiltDependencies: []" > pnpm-workspace.yaml
                  pnpm init
                  pnpm install --dangerously-allow-all-builds --verbose $GITHUB_WORKSPACE/api/node/slint-ui-$PKG_VERSION.tgz
            - name: Build and publish packages
              if: ${{ github.event.inputs.private != 'true' && (github.ref == 'refs/heads/master' || github.event.inputs.release == 'true') }}
              run: |
                  pnpm publish --no-git-checks --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-linux-x64-gnu-$PKG_VERSION.tgz
                  pnpm publish --no-git-checks --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-linux-arm64-gnu-$PKG_VERSION.tgz
                  pnpm publish --no-git-checks --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-darwin-arm64-$PKG_VERSION.tgz
                  pnpm publish --no-git-checks --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-win32-x64-msvc-$PKG_VERSION.tgz
                  pnpm publish --no-git-checks --access public $PUBLISH_TAG api/node/slint-ui-slint-ui-binary-win32-arm64-msvc-$PKG_VERSION.tgz
                  pnpm publish --no-git-checks $PUBLISH_TAG api/node/slint-ui-$PKG_VERSION.tgz
