#!/bin/bash
set -eu

###
#
# Publishes all *.tgz files to npm
#
# Usage: ./publib-npm [DIR]
#
# DIR: directory where npm tarballs are found (default is `dist/js`).
#
# NPM_TOKEN (optional): registry authentication token (either from npmjs or a GitHub personal access token), not used for AWS CodeArtifact
# NPM_TRUSTED_PUBLISHER (optional): use a Trusted Publisher configuration instead of tokens, any value 
# NPM_REGISTRY (optional): the registry URL (defaults to "registry.npmjs.org")
# AWS_ACCESS_KEY_ID (optional): If AWS CodeArtifact is used as registry, an AWS access key can be spedified.
# AWS_SECRET_ACCESS_KEY (optional): Secret access key that belongs to the AWS access key.
# AWS_ROLE_TO_ASSUME (optional): If AWS CodeArtifact is used as registry and need to assume role.
# DISABLE_HTTPS (optional): connect to the registry with HTTP instead of HTTPS (defaults to false)
#
###

dir="${1:-"dist/js"}"

# Evaluate trusted publisher flag once as boolean
use_trusted_publisher=false
if [ -n "${NPM_TRUSTED_PUBLISHER:-}" ] && [ "${NPM_TRUSTED_PUBLISHER}" != "false" ]; then
  use_trusted_publisher=true
fi

if ! [ -z "${NPM_REGISTRY:-}" ] && [[ $NPM_REGISTRY =~ .codeartifact.*.amazonaws.com ]]; then
  codeartifact_account="$(echo $NPM_REGISTRY | cut -d. -f1 | rev | cut -d- -f1 | rev)"
  codeartifact_subdomain="$(echo $NPM_REGISTRY | cut -d. -f1)"
  codeartifact_domain="$(echo $codeartifact_subdomain | cut -b -$((${#codeartifact_subdomain}-${#codeartifact_account}-1)))"
  codeartifact_region="$(echo $NPM_REGISTRY | cut -d. -f4)"
  export AWS_DEFAULT_REGION="$(echo $codeartifact_region)" 
  if [ -n "${AWS_ROLE_TO_ASSUME:-}" ]; then
    credentials=`aws sts assume-role --role-session-name "publib-code-artifact" --role-arn ${AWS_ROLE_TO_ASSUME} --output text | sed -n '2 p'`
    export AWS_ACCESS_KEY_ID="$(echo $credentials | cut -d' ' -f2)"
    export AWS_SECRET_ACCESS_KEY="$(echo $credentials | cut -d' ' -f4)"
    export AWS_SESSION_TOKEN="$(echo $credentials | cut -d' ' -f5)"
  fi
  NPM_TOKEN=`aws codeartifact get-authorization-token --domain $codeartifact_domain --domain-owner $codeartifact_account --region $codeartifact_region --query authorizationToken --output text`
elif [ -z "${NPM_TOKEN:-}" ] && [ "$use_trusted_publisher" = "false" ]; then
  echo "NPM_TOKEN=<token> or NPM_TRUSTED_PUBLISHER=true is required"
  exit 1
fi

if [ "$use_trusted_publisher" = "true" ]; then
  unset NPM_TOKEN
fi

NPM_REGISTRY=${NPM_REGISTRY:-"registry.npmjs.org"}
if ! [ -z "${NPM_TOKEN:-}" ]; then
  echo "//${NPM_REGISTRY%%/}/:_authToken=${NPM_TOKEN}" > ~/.npmrc
fi

# this overrides any registry configuration defined externally. For example, yarn sets the registry to the yarn proxy
# which requires `yarn login`. but since we are logging in through ~/.npmrc, we must make sure we publish directly to npm.
if ! [ -z "${DISABLE_HTTPS:-}" ]; then
  export NPM_CONFIG_REGISTRY="http://${NPM_REGISTRY}"
else
  export NPM_CONFIG_REGISTRY="https://${NPM_REGISTRY}"
fi

# dist-tags
tag=""
if [ -n "${NPM_DIST_TAG:-}" ]; then
  tag="--tag ${NPM_DIST_TAG}"
  echo "Publishing under the following dist-tag: ${NPM_DIST_TAG}"
fi

# access level
access=""
if [ -n "${NPM_ACCESS_LEVEL:-}" ]; then
  if ! [[ "${NPM_ACCESS_LEVEL}" =~ ^(public|restricted)$ ]]; then
    echo "Invalid package access level: ${NPM_ACCESS_LEVEL}. Valid values are: public, restricted (default is restricted for scoped packages and public for unscoped packages)"
    exit 1
  fi

  access="--access ${NPM_ACCESS_LEVEL}"
  echo "Publishing package with access level: ${NPM_ACCESS_LEVEL}"
fi

log=$(mktemp -d)/npmlog.txt

# Check for dry run
if [ "${PUBLIB_DRYRUN:-}" = "true" ]; then
  echo "🏜️ Dry run: skipping npm publish"
  for file in ${dir}/**.tgz; do
    echo "  (would publish ${file})"
  done
  echo "SUCCESS (dry run)"
  exit 0
fi

for file in ${dir}/**.tgz; do
  npm publish ${tag} ${access} ${file} 2>&1 | tee ${log}
  exit_code="${PIPESTATUS[0]}"

  if [ ${exit_code} -ne 0 ]; then

    # error returned from npmjs
    if cat ${log} | grep -q "You cannot publish over the previously published versions"; then
      echo "SKIPPING: already published"
      continue
    fi

    # error returned from github packages
    if cat ${log} | grep -q "Cannot publish over existing version"; then
      echo "SKIPPING: already published"
      continue
    fi

    echo "ERROR"
    exit 1
  fi
done

echo "SUCCESS"
