---
version: '3'

vars:
  BINARY_BUILD_FOLDER: dist/bin
  BUILD_FOLDERS: build coverage dist

tasks:
  build:
    deps:
      - :install:modules:local
      - :install:npm:esbuild
      - :install:npm:nest
      - clean
    desc: Build the application
    log:
      error: Error building the application
      start: Building the application
      success: Successfully built the application
    cmds:
      - task: depcheck:dependencies
      - mkdir -p dist
      - task: build:compile

  build:compile:
    deps:
      - build:nest
      - build:esbuild:bundled
      - build:esbuild:minified
      - build:fpm

  build:esbuild:bundled:
    deps:
      - :install:modules:local
      - :install:npm:esbuild
    log:
      error: Error running `esbuild` (config -> ./.config/esbuild/bundled.js)
      start: Running `esbuild` with bundle script (config -> ./.config/esbuild/bundled.js)
      success: Finished running `esbuild` (config -> ./.config/esbuild/bundled.js)
    cmds:
      - node .config/esbuild/bundled.js

  build:esbuild:minified:
    deps:
      - :install:modules:local
      - :install:npm:esbuild
    log:
      error: Error running `esbuild` (config -> ./.config/esbuild/minified.js)
      start: Running `esbuild` with minify script (config -> ./.config/esbuild/minified.js)
      success: Finished running `esbuild with minify script (config -> ./.config/esbuild/minified.js)
    cmds:
      - node .config/esbuild/minified.js

  build:fpm:
    deps:
      - :install:software:jq
    vars:
      NPM_PACKAGE_NAME:
        sh: jq -r '.blueprint.binName' package.json
      NPM_PACKAGE_VERSION:
        sh: jq -r '.version' package.json
    cmds:
      - task: build:fpm-build
        vars:
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'

  build:fpm:build:
    deps:
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: amd64
          FILE_EXTENSION: deb
          FPM_TARGET: deb
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: debian
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: arm64
          FILE_EXTENSION: deb
          FPM_TARGET: deb
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: debian
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: amd64
          FILE_EXTENSION: txz
          FPM_TARGET: freebsd
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: freebsd
      # - task: build:fpm:compile
      #   vars:
      #     ARCHITECTURE: amd64
      #     FILE_EXTENSION:
      #     FPM_TARGET: pacman
      #     NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
      #     NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
      #     SYSTEM: archlinux
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: amd64
          FILE_EXTENSION: rpm
          FPM_TARGET: rpm
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: redhat
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: arm64
          FILE_EXTENSION: rpm
          FPM_TARGET: rpm
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: redhat
      - task: build:fpm:compile
        vars:
          ARCHITECTURE: all
          FILE_EXTENSION: tar
          FPM_TARGET: tar
          NPM_PACKAGE_NAME: '{{.NPM_PACKAGE_NAME}}'
          NPM_PACKAGE_VERSION: '{{.NPM_PACKAGE_VERSION}}'
          SYSTEM: source
    log:
      error: Encountered error while building binaries with FPM
      start: Building binaries with FPM
      success: Successfully built binaries with FPM
    cmds:
      - |
        .config/log success 'Running gzip on `{{.NPM_PACKAGE_NAME}}-{{.NPM_PACKAGE_VERSION}}-source-all.tar`'
        gzip -9 {{.NPM_PACKAGE_NAME}}-{{.NPM_PACKAGE_VERSION}}-source-all.tar

  build:fpm:compile:
    deps:
      - :install:software:fpm
    log:
      error: Encountered error while compiling {{.ARCHITECTURE}} {{.FPM_TARGET}} binary with FPM for {{.NPM_PACKAGE_NAME}}, version {{.NPM_PACKAGE_VERSION}}
      start: Compiling {{.ARCHITECTURE}} {{.FPM_TARGET}} binary with FPM for {{.NPM_PACKAGE_NAME}}, version {{.NPM_PACKAGE_VERSION}}
      success: Finished compiling {{.ARCHITECTURE}} {{.FPM_TARGET}} binary with FPM for {{.NPM_PACKAGE_NAME}}, version {{.NPM_PACKAGE_VERSION}}
    cmds:
      - >
        {{.NPX_HANDLE}}fpm -s npm -t {{.FPM_TARGET}}
        -p {{.BINARY_BUILD_FOLDER}}/{{.NPM_PACKAGE_NAME}}-{{.NPM_PACKAGE_VERSION}}-{{.SYSTEM}}-{{.ARCHITECTURE}}.{{.FILE_EXTENSION}}
        --architecture {{.ARCHITECTURE}} .

  build:nest:
    deps:
      - :install:modules:local
      - :install:npm:nest
    log:
      error: Encountered error while building NestJS project
      start: Building NestJS project
      success: Finished building NestJS project
    cmds:
      - '{{.NPX_HANDLE}}nest build'
      - task: build:nest:after

  build:nest:after:
    deps:
      - :common:update:man-page
      - build:pkg

  build:none:
    log:
      start: Skipping build step because project does not need building
    cmds:
      - task: :donothing

  build:pkg:
    deps:
      - :install:modules:local
      - :install:npm:pkg
    log:
      error: Encountered error while generating standalone executables for macOS, Linux, and Windows using `pkg`
      start: Generating standalone executables for macOS, Linux, and Windows using `pkg`
      success: Generated standalone executables for macOS, Linux, and Windows using `pkg`
    cmds:
      - '{{.NPX_HANDLE}}pkg package.json'

  build:release: 'true'

  build:tsconfig:
    deps:
      - :install:npm:typescript
    log:
      error: Error building with `tsconfig.json`
      start: Removing `dist/` folder and running `tsc -p tsconfig.json`
      success: Successfully built project
    cmds:
      - rm -rf dist
      - tsc -p tsconfig.json

  clean:
    deps:
      - :install:software:rsync
    desc: Remove temporary folders that might conflicts with builds
    vars:
      RANDOM_STRING:
        sh: openssl rand -hex 14
    log:
      error: Error removing `{{.BUILD_FOLDERS}}` with rsync
      start: Removing `{{.BUILD_FOLDERS}}` with rsync
      success: Successfully removed `{{.BUILD_FOLDERS}}`
    cmds:
      - mkdir -p '/tmp/{{.RANDOM_STRING}}'
      - mkdir -p '/tmp/{{.RANDOM_STRING}}-empty'
      - |
        for TMP_FILE in {{.BUILD_FOLDERS}}; do
          if [ -d "$TMP_FILE" ]; then
            mv "$TMP_FILE" "/tmp/{{.RANDOM_STRING}}/$TMP_FILE" 2> /dev/null
            (rsync -a --delete '/tmp/{{.RANDOM_STRING}}-empty' "/tmp/{{.RANDOM_STRING}}/$TMP_FILE" && rm -rf "/tmp/{{.RANDOM_STRING}}-$TMP_FILE") &
          fi
        done
        wait

  depcheck:dependencies:
    deps:
      - :install:npm:depcheck
      - :install:software:jq
    desc: Remove unused dependencies
    log:
      error: Error uninstalling unused dependencies in package.json
      start: Uninstalling unused dependencies in package.json
      success: Successfully uninstalled unused dependencies in package.json
    cmds:
      - |
        {{.NPX_HANDLE}}depcheck --json | jq -r '.dependencies[]' | xargs -n1 {{.NPM_PROGRAM_LOCAL}} uninstall --save

  preinstall:
    deps:
      - :install:npm:only-allow
    log:
      error: '`pnpm` must be used as the package manager'
      start: Forcing `pnpm` as the package manager by running `only-allow pnpm`
      success: Successfully enforced `pnpm` as the package manager
    cmds:
      - only-allow pnpm

  start:
    deps:
      - :install:modules:local
      - :install:npm:nest
    desc: Run the application
    log:
      error: Encountered error while running `{{.NPX_HANDLE}}nest start`
      start: Running `{{.NPX_HANDLE}}nest start`
      success: Successfully ran `{{.NPX_HANDLE}}nest start`
    cmds:
      - '{{.NPX_HANDLE}}nest start'

  start:debug:
    deps:
      - :install:modules:local
      - :install:npm:nest
    log:
      error: Encountered error while running `{{.NPX_HANDLE}}nest start --watch`
      start: Running `{{.NPX_HANDLE}}nest start --watch`
      success: Successfully ran `{{.NPX_HANDLE}}nest start --watch`
    cmds:
      - '{{.NPX_HANDLE}}nest start --watch'

  start:inspect:
    deps:
      - :install:modules:local
      - :install:npm:ndb
      - :install:npm:nodemon
      - :install:npm:ts-node
    desc: Run the application in `watch` mode and open DevTools
    log:
      error: Error encountered while running `{{.NPX_HANDLE}}ndb nest start --watch`
      start: Running `{{.NPX_HANDLE}}ndb nest start --watch`
      success: Successfully ran `{{.NPX_HANDLE}}ndb nest start --watch`
    cmds:
      - '{{.NPX_HANDLE}}ndb nest start --watch'

  start:inspect:legacy:
    deps:
      - :install:modules:local
      - :install:npm:nest
    log:
      error: Encountered error while running `{{.NPX_HANDLE}}nest start --debug --watch`
      start: Running `{{.NPX_HANDLE}}nest start --debug --watch`
      success: Successfully ran `{{.NPX_HANDLE}}nest start --debug --watch`
    cmds:
      - '{{.NPX_HANDLE}}nest start --debug --watch'

  start:prod:
    deps:
      - :install:modules:local
      - :install:npm:nest
    desc: Run the application in `production` mode
    log:
      error: Error encountered while building and running `node dist/main`
      start: Running `production` build by building the project and then running `node dist/main`
      success: Successfully ran `production` build
    cmds:
      - task: build
      - node dist/main

  start:prod:inspect:
    deps:
      - :install:modules:local
      - :install:npm:nest
    desc: Run the application in `production` and `watch` mode and open DevTools
    log:
      error: Error encountered while running `{{.NPX_HANDLE}}ndb nodemon`
      start: Running `{{.NPX_HANDLE}}ndb nodemon`
      success: Successfully ran `{{.NPX_HANDLE}}ndb nodemon`
    cmds:
      - '{{.NPX_HANDLE}}ndb nodemon'

  test:
    deps:
      - :install:modules:local
      - :install:npm:jest
    desc: Run the unit tests for an NPM project
    log:
      error: Errors were detected by Jest
      start: Running `{{.NPX_HANDLE}}jest`
      success: Successfully ran `{{.NPX_HANDLE}}jest`
    cmds:
      - '{{.NPX_HANDLE}}jest'

  test:ci:
    deps:
      - :install:modules:local
      - :install:npm:jest
    log:
      error: Encountered error while running `{{.NPX_HANDLE}}jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
      start: Running `{{.NPX_HANDLE}}jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
      success: Successfully ran `{{.NPX_HANDLE}}jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
    cmds:
      - '{{.NPX_HANDLE}}jest --collectCoverage --ci --reporters=default --reporters=jest-junit'

  test:coverage:
    deps:
      - :install:modules:local
      - :install:npm:jest
    desc: Generate code coverage assets
    log:
      error: Error running `{{.NPX_HANDLE}}jest --coverage`
      start: Generating code coverage assets by running `{{.NPX_HANDLE}}jest --coverage`
      success: Successfully ran `{{.NPX_HANDLE}}jest --coverage`
    cmds:
      - '{{.NPX_HANDLE}}jest --coverage'

  test:dashboard:
    deps:
      - :install:modules:local
      - :install:npm:majestic
    desc: Run and manage test cases from a web interface (powered by `majestic`)
    log:
      error: Error running `{{.NPX_HANDLE}}majestic --debug`
      start: Launching web interface for debugging test cases by running `{{.NPX_HANDLE}}majestic --debug`
      success: Successfully ran `{{.NPX_HANDLE}}majestic --debug`
    cmds:
      - '{{.NPX_HANDLE}}majestic --debug'

  test:debug:
    deps:
      - :install:modules:local
      - :install:npm:jest
    desc: Debug tests in `watch` mode
    log:
      error: Error running `{{.NPX_HANDLE}}jest --watch`
      start: Running `{{.NPX_HANDLE}}jest --watch`
      success: Successfully ran `{{.NPX_HANDLE}}jest --watch`
    cmds:
      - '{{.NPX_HANDLE}}jest --watch'

  test:e2e: 'true'

  test:inspect:
    deps:
      - :install:modules:local
      - :install:npm:jest
      - :install:npm:ndb
      - :install:npm:nodemon
      - :install:npm:ts-node
    desc: Debug tests with DevTools in `watch` mode
    log:
      error: Error running `{{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json`
      start: Running `{{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json` to enable debugging with Chrome DevTools in watch mode
      success: Successfully ran `{{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json`
    cmds:
      - '{{.NPX_HANDLE}}ndb nodemon --config .config/nodemon-jest.json'

  test:none:
    log:
      start: No tests have been set up for this project
    cmds:
      - task: :donothing

  typesync:
    deps:
      - :install:npm:typesync
    desc: Install missing type definitions
    log:
      error: Error running `{{.NPX_HANDLE}}typesync`
      start: Installing missing type definitions by running `{{.NPX_HANDLE}}typesync`
      success: Successfully ran `{{.NPX_HANDLE}}typesync`
    cmds:
      - '{{.NPX_HANDLE}}typesync'
