---
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:
      - >
        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:
      - 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:
      - pkg package.json

  build:release: 'true'

  build:tsconfig:
    deps:
      - :install:modules:local
      - :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

  bump:
    deps:
      - :install:modules:local
    cmds:
      - npm run build
      - |
        .config/log info 'The current package.json version is `'"$(jq -r '.version' package.json)"'`'
        BUMP_VERSION="$(npm version patch --no-scripts --no-commit-hooks --no-git-tag-version --force | sed 's/^v//')"
        .config/log info 'Bumped the package.json version with a patch update to version `'"$BUMP_VERSION"'`'
      - SKIP_PREPUB=true npm publish

  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

  config:
    deps:
      - :install:software:jq
      - :install:software:node
    vars:
      REGISTRY_ADDRESS:
        sh: jq -r '.publishConfig["@gitlab:registry"]' package.json | sed 's/^https://'
    cmds:
      - npm config set -- '//registry.npmjs.org/:_authToken' '${NPM_TOKEN}' '{{.REGISTRY_ADDRESS}}:_authToken' '${GITLAB_TOKEN}'

  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:
      - depcheck --json | jq -r '.dependencies[]' | xargs -n1 {{.NPM_PROGRAM}} 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

  prepare:
    cmds:
      - task: prepare:project
      - task: prepare:release

  prepare:project:
    cmds:
      - task: :common:husky
    status:
      - '[ -n "$CI" ] || [ -n "$SEMANTIC_RELEASE" ]'

  prepare:prune:
    cmds:
      - task: prune
    status:
      - '! type node-prune &> /dev/null'

  prepare:release:
    cmds:
      - 'true'
    status:
      - '[ -z "$SEMANTIC_RELEASE" ]'

  prune:
    deps:
      - :install:go:node-prune
    log:
      error: Error pruning `node_modules/`
      start: Pruning the `node_modules/` folder
      success: Successfully pruned the `node_modules/` folder
    cmds:
      - node-prune

  publish:gitlab:
    deps:
      - :install:software:jq
      - :install:software:node
      - :npm:config
    vars:
      PKG_NAME:
        sh: jq -r '.name' package.json
      REGISTRY_ADDRESS:
        sh: jq -r '.publishConfig["@gitlab:registry"]' package.json
      VERSION:
        sh: jq -r '.version' package.json
    env:
      BACKUP_PKG:
        sh: mktemp
    cmds:
      - cp package.json "$BACKUP_PKG"
      - TMP="$(mktemp)" && jq '.name = "@gitlab/{{.PKG_NAME}}" | .publishConfig.access = "restricted"' package.json > "$TMP" && mv "$TMP" package.json
      - npm publish
      - npm dist-tag --registry={{.REGISTRY_ADDRESS}} add {{.PKG_NAME}}@{{.VERSION}} latest
      - mv "$BACKUP_PKG" package.json
    status:
      - '[ "$(jq -r ".publishConfig[\"@gitlab:registry\"] | type" package.json)" != "string" ] || [ -z "$NPM_PUBLISH_GITLAB" ]'

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

  start:debug:
    deps:
      - :install:modules:local
      - :install:npm:nest
    log:
      error: Encountered error while running `nest start --watch`
      start: Running `nest start --watch`
      success: Successfully ran `nest start --watch`
    cmds:
      - 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 `ndb nest start --watch`
      start: Running `ndb nest start --watch`
      success: Successfully ran `ndb nest start --watch`
    cmds:
      - ndb nest start --watch

  start:inspect:legacy:
    deps:
      - :install:modules:local
      - :install:npm:nest
    log:
      error: Encountered error while running `nest start --debug --watch`
      start: Running `nest start --debug --watch`
      success: Successfully ran `nest start --debug --watch`
    cmds:
      - 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 `ndb nodemon`
      start: Running `ndb nodemon`
      success: Successfully ran `ndb nodemon`
    cmds:
      - 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 `jest`
      success: Successfully ran `jest`
    cmds:
      - jest --silent=false

  test:ci:
    deps:
      - :install:modules:local
      - :install:npm:jest
    log:
      error: Encountered error while running `jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
      start: Running `jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
      success: Successfully ran `jest --collectCoverage --ci --reporters=default --reporters=jest-junit`
    cmds:
      - 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 `jest --coverage`
      start: Generating code coverage assets by running `jest --coverage`
      success: Successfully ran `jest --coverage`
    cmds:
      - 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 `majestic --debug`
      start: Launching web interface for debugging test cases by running `majestic --debug`
      success: Successfully ran `majestic --debug`
    cmds:
      - majestic --debug

  test:debug:
    deps:
      - :install:modules:local
      - :install:npm:jest
    desc: Debug tests in `watch` mode
    log:
      error: Error running `jest --watch`
      start: Running `jest --watch`
      success: Successfully ran `jest --watch`
    cmds:
      - 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 `ndb nodemon --config .config/nodemon-jest.json`
      start: Running `ndb nodemon --config .config/nodemon-jest.json` to enable debugging with Chrome DevTools in watch mode
      success: Successfully ran `ndb nodemon --config .config/nodemon-jest.json`
    cmds:
      - 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 `typesync`
      start: Installing missing type definitions by running `typesync`
      success: Successfully ran `typesync`
    cmds:
      - typesync

  verify: 'true'
