@beplus/be 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/be +95 -116
  2. package/package.json +1 -1
package/bin/be CHANGED
@@ -64,7 +64,7 @@ function n_grep() {
64
64
  # Setup and state
65
65
  #
66
66
 
67
- VERSION="v0.9.0"
67
+ VERSION="v0.11.0"
68
68
 
69
69
  BE_PREFIX="${BE_PREFIX-/usr/local}"
70
70
  BE_PREFIX=${BE_PREFIX%/}
@@ -278,6 +278,7 @@ Commands:
278
278
 
279
279
  be Display downloaded beplus CLI versions and install selection
280
280
  be latest Install the latest beplus CLI release (downloading if necessary)
281
+ be auto Install the beplus CLI version the nearest beplus.estate.json pins
281
282
  be <version> Install beplus CLI <version> (downloading if necessary)
282
283
  be install <version> Install beplus CLI <version> (downloading if necessary)
283
284
  be run <version> [args ...] Execute downloaded beplus CLI <version> with [args ...]
@@ -316,7 +317,8 @@ Versions:
316
317
 
317
318
  0.17.0, 1, v1.2 Numeric versions
318
319
  latest, current Newest official release
319
- auto Read version from file: .bepluscloud, .beplus-version, or package.json
320
+ auto The exact version pinned as "cli": { "version": "x.y.z" } in the nearest
321
+ beplus.estate.json (in the current directory or above it); fails without one
320
322
 
321
323
  EOF
322
324
  }
@@ -897,138 +899,109 @@ function tarball_url() {
897
899
  }
898
900
 
899
901
  #
900
- # Synopsis: get_file_node_version filename
901
- # Sets g_target_beplus
902
+ # Synopsis: display_estate_manifest_path
903
+ # Output the path of the nearest beplus.estate.json: in PWD, or else in the closest directory above
904
+ # it. Fails when there is none.
902
905
  #
903
906
 
904
- function get_file_node_version() {
905
- g_target_beplus=
906
- local filepath="$1"
907
- verbose_log "found" "${filepath}"
908
- # read returns a non-zero status but does still work if there is no line ending
909
- local version
910
- <"${filepath}" read -r version
911
- # trim possible trailing \d from a Windows created file
912
- version="${version%%[[:space:]]}"
913
- verbose_log "read" "${version}"
914
- g_target_beplus="${version}"
907
+ function display_estate_manifest_path() {
908
+ local dir="${PWD}"
909
+ while true; do
910
+ if [[ -f "${dir%/}/beplus.estate.json" ]]; then
911
+ echo "${dir%/}/beplus.estate.json"
912
+ return 0
913
+ fi
914
+ [[ -z "${dir}" || "${dir}" == "/" ]] && return 1
915
+ dir="${dir%/*}"
916
+ done
915
917
  }
916
918
 
917
919
  #
918
- # Synopsis: get_package_engine_version\
919
- # Sets g_target_beplus
920
- #
921
-
922
- function get_package_engine_version() {
923
- g_target_beplus=
924
- local filepath="$1"
925
- verbose_log "found" "${filepath}"
926
- command -v node &> /dev/null || abort "an active version of node is required to read 'engines' from package.json"
927
- local range
928
- range="$(node -e "package = require('${filepath}'); if (package && package.engines && package.engines.node) console.log(package.engines.node)")"
929
- verbose_log "read" "${range}"
930
- [[ -n "${range}" ]] || return 2
931
- if [[ "*" == "${range}" ]]; then
932
- verbose_log "target" "current"
933
- g_target_beplus="current"
934
- return
935
- fi
936
-
937
- local version
938
- if [[ "${range}" =~ ^([>~^=]|\>\=)?v?([0-9]+(\.[0-9]+){0,2})(.[xX*])?$ ]]; then
939
- local operator="${BASH_REMATCH[1]}"
940
- version="${BASH_REMATCH[2]}"
941
- case "${operator}" in
942
- '' | =) ;;
943
- \> | \>=) version="current" ;;
944
- \~) [[ "${version}" =~ ^([0-9]+\.[0-9]+)\.[0-9]+$ ]] && version="${BASH_REMATCH[1]}" ;;
945
- ^) [[ "${version}" =~ ^([0-9]+) ]] && version="${BASH_REMATCH[1]}" ;;
946
- esac
947
- verbose_log "target" "${version}"
920
+ # Synopsis: display_estate_cli_version node|jq manifest
921
+ # Output the manifest's "cli": { "version" } as JSON, on one line: a string when the pin is one,
922
+ # null when the manifest has none. Fails, with the reason on stderr, when the file is not exactly
923
+ # one JSON value.
924
+ #
925
+
926
+ function display_estate_cli_version() {
927
+ if [[ "$1" == "node" ]]; then
928
+ node -e '
929
+ const has = (value, key) =>
930
+ value !== null && typeof value === "object" && !Array.isArray(value)
931
+ && Object.prototype.hasOwnProperty.call(value, key);
932
+ let manifest;
933
+ try {
934
+ manifest = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
935
+ } catch (error) {
936
+ console.error(error.message);
937
+ process.exit(1);
938
+ }
939
+ const version = has(manifest, "cli") && has(manifest.cli, "version") ? manifest.cli.version : null;
940
+ console.log(JSON.stringify(version));
941
+ ' "$2"
948
942
  else
949
- command -v npx &> /dev/null || abort "an active version of npx is required to use complex 'engine' ranges from package.json"
950
- verbose_log "resolving" "${range}"
951
- local version_per_line="$(be lsr --all)"
952
- local versions_one_line=$(echo "${version_per_line}" | tr '\n' ' ')
953
- # Using semver@7 so works with older versions of node.
954
- # shellcheck disable=SC2086
955
- version=$(npm_config_yes=true npx --quiet semver@7 -r "${range}" ${versions_one_line} | tail -n 1)
943
+ # --slurp so that an empty file, or one holding several values, fails as JSON.parse does.
944
+ jq -r --slurp '
945
+ if length != 1 then error("expected one JSON value, found \(length)")
946
+ else .[0]
947
+ | if type == "object" and (.cli | type) == "object" and (.cli | has("version"))
948
+ then .cli.version
949
+ else null
950
+ end
951
+ | tojson
952
+ end
953
+ ' "$2"
956
954
  fi
957
- g_target_beplus="${version}"
958
955
  }
959
956
 
960
957
  #
961
- # Synopsis: get_nvmrc_version
958
+ # Synopsis: get_auto_version
959
+ # Resolve auto to the beplus CLI version the nearest beplus.estate.json pins as
960
+ # "cli": { "version": "x.y.z" }. The pin must be one exact version (a leading v and a pre-release
961
+ # are allowed, as everywhere in be); a missing, floating or unreadable pin aborts, naming the file,
962
+ # rather than falling back to another version. The nearest manifest decides, even when it pins
963
+ # nothing: one further up is never consulted.
962
964
  # Sets g_target_beplus
963
965
  #
964
966
 
965
- function get_nvmrc_version() {
967
+ function get_auto_version() {
966
968
  g_target_beplus=
967
- local filepath="$1"
968
- verbose_log "found" "${filepath}"
969
- local version
970
- <"${filepath}" read -r version
971
- verbose_log "read" "${version}"
972
- # Translate from nvm aliases
973
- case "${version}" in
974
- lts/\*) version="lts" ;;
975
- lts/*) version="${version:4}" ;;
976
- node) version="current" ;;
977
- *) ;;
978
- esac
979
- g_target_beplus="${version}"
980
- }
969
+ local manifest
970
+ manifest="$(display_estate_manifest_path)" \
971
+ || abort "auto found no beplus.estate.json in ${PWD} or above it, so no beplus CLI version is pinned"
972
+ verbose_log "found" "${manifest}"
981
973
 
982
- #
983
- # Synopsis: get_engine_version [error-message]
984
- # Sets g_target_beplus
985
- #
974
+ # node is on every deploy path; jq is what be's remote lookups use.
975
+ local reader
976
+ if command -v node &> /dev/null; then
977
+ reader="node"
978
+ elif command -v jq &> /dev/null; then
979
+ reader="jq"
980
+ else
981
+ abort "reading the beplus CLI pin from ${manifest} needs node or jq, and neither is on PATH"
982
+ fi
986
983
 
987
- function get_engine_version() {
988
- g_target_beplus=
989
- local error_message="${1-package.json not found}"
990
- local parent
991
- parent="${PWD}"
992
- while [[ -n "${parent}" ]]; do
993
- if [[ -e "${parent}/package.json" ]]; then
994
- get_package_engine_version "${parent}/package.json"
995
- else
996
- parent=${parent%/*}
997
- continue
998
- fi
999
- break
1000
- done
1001
- [[ -n "${parent}" ]] || abort "${error_message}"
1002
- [[ -n "${g_target_beplus}" ]] || abort "did not find supported version of node in 'engines' field of package.json"
1003
- }
984
+ local value
985
+ if ! value="$(display_estate_cli_version "${reader}" "${manifest}" 2> /dev/null)"; then
986
+ abort "${manifest} could not be read as JSON by ${reader}: $(display_estate_cli_version "${reader}" "${manifest}" 2>&1 > /dev/null)"
987
+ fi
1004
988
 
1005
- #
1006
- # Synopsis: get_auto_version
1007
- # Sets g_target_beplus
1008
- #
989
+ local version
990
+ case "${value}" in
991
+ null)
992
+ abort "${manifest} pins no beplus CLI version; add \"cli\": { \"version\": \"x.y.z\" }" ;;
993
+ \"*\")
994
+ version="${value#\"}"
995
+ version="${version%\"}"
996
+ ;;
997
+ *)
998
+ abort "\"cli\": { \"version\" } in ${manifest} is ${value}, not a version string like \"2.11.0\"" ;;
999
+ esac
1000
+ verbose_log "read" "${version}"
1009
1001
 
1010
- # @todo
1011
- function get_auto_version() {
1012
- g_target_beplus=
1013
- # Search for a version control file first
1014
- local parent
1015
- parent="${PWD}"
1016
- while [[ -n "${parent}" ]]; do
1017
- if [[ -e "${parent}/.n-node-version" ]]; then
1018
- get_file_node_version "${parent}/.n-node-version"
1019
- elif [[ -e "${parent}/.node-version" ]]; then
1020
- get_file_node_version "${parent}/.node-version"
1021
- elif [[ -e "${parent}/.nvmrc" ]]; then
1022
- get_nvmrc_version "${parent}/.nvmrc"
1023
- else
1024
- parent=${parent%/*}
1025
- continue
1026
- fi
1027
- break
1028
- done
1029
- # Fallback to package.json
1030
- [[ -n "${parent}" ]] || get_engine_version "no file found for auto version (.n-node-version, .node-version, .nvmrc, or package.json)"
1031
- [[ -n "${g_target_beplus}" ]] || abort "file found for auto did not contain target version of node"
1002
+ is_exact_numeric_version "${version}" \
1003
+ || abort "\"cli\": { \"version\" } in ${manifest} is \"${version}\", not one exact version like \"2.11.0\""
1004
+ g_target_beplus="${version#v}"
1032
1005
  }
1033
1006
 
1034
1007
  #
@@ -1039,6 +1012,12 @@ function get_auto_version() {
1039
1012
  function get_latest_resolved_version() {
1040
1013
  g_target_beplus=
1041
1014
  local version=${1}
1015
+ if [[ "${version}" == "auto" ]]; then
1016
+ # The pin is one exact version, so there is nothing to look up: auto installs exactly that
1017
+ # version or fails, and never reads the release index (where "newest" lives).
1018
+ get_auto_version
1019
+ return
1020
+ fi
1042
1021
  simple_version=${version}
1043
1022
  if is_exact_numeric_version "${simple_version}"; then
1044
1023
  # Just numbers, already resolved, no need to lookup first.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beplus/be",
3
3
  "description": "Interactively Manage beplus CLI Versions",
4
- "version": "0.9.0",
4
+ "version": "0.11.0",
5
5
  "author": "Igor Lamos <igor@be.plus>",
6
6
  "homepage": "https://github.com/beplus/be",
7
7
  "bugs": "https://github.com/beplus/be",