diff --git a/node_modules/.bin/bats b/node_modules/.bin/bats
new file mode 120000
index 00000000..3ea23c3e
--- /dev/null
+++ b/node_modules/.bin/bats
@@ -0,0 +1 @@
+../bats/bin/bats
\ No newline at end of file
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 00000000..3c7314fe
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,16 @@
+{
+ "name": "pr-672",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/bats": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/bats/-/bats-1.13.0.tgz",
+ "integrity": "sha512-giSYKGTOcPZyJDbfbTtzAedLcNWdjCLbXYU3/MwPnjyvDXzu6Dgw8d2M+8jHhZXSmsCMSQqCp+YBsJ603UO4vQ==",
+ "license": "MIT",
+ "bin": {
+ "bats": "bin/bats"
+ }
+ }
+ }
+}
diff --git a/node_modules/bats/LICENSE.md b/node_modules/bats/LICENSE.md
new file mode 100644
index 00000000..0c742997
--- /dev/null
+++ b/node_modules/bats/LICENSE.md
@@ -0,0 +1,53 @@
+Copyright (c) 2017 bats-core contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+---
+
+* [bats-core] is a continuation of [bats]. Copyright for portions of the
+ bats-core project are held by Sam Stephenson, 2014 as part of the project
+ [bats], licensed under MIT:
+
+Copyright (c) 2014 Sam Stephenson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For details, please see the [version control history][commits].
+
+[bats-core]: https://github.com/bats-core/bats-core
+[bats]:https://github.com/sstephenson/bats
+[commits]:https://github.com/bats-core/bats-core/commits/master
diff --git a/node_modules/bats/README.md b/node_modules/bats/README.md
new file mode 100644
index 00000000..4ccc248e
--- /dev/null
+++ b/node_modules/bats/README.md
@@ -0,0 +1,135 @@
+[](https://github.com/bats-core/bats-core/releases/latest)
+[](https://www.npmjs.com/package/bats)
+[](https://github.com/bats-core/bats-core/blob/master/LICENSE.md)
+[](https://github.com/bats-core/bats-core/actions?query=workflow%3ATests)
+[](https://bats-core.readthedocs.io)
+
+[][gitter]
+
+
+
+
+
+
+
+
+# Bats-core: Bash Automated Testing System
+
+Bats is a [TAP](https://testanything.org/)-compliant testing framework for Bash
+3.2 or above. It provides a simple way to verify that the UNIX programs you
+write behave as expected.
+
+A Bats test file is a Bash script with special syntax for defining test cases.
+Under the hood, each test case is just a function with a description.
+
+```bash
+#!/usr/bin/env bats
+
+@test "addition using bc" {
+ result="$(echo 2+2 | bc)"
+ [ "$result" -eq 4 ]
+}
+
+@test "addition using dc" {
+ result="$(echo 2 2+p | dc)"
+ [ "$result" -eq 4 ]
+}
+```
+
+Bats is most useful when testing software written in Bash, but you can use it to
+test any UNIX program.
+
+Test cases consist of standard shell commands. Bats makes use of Bash's
+`errexit` (`set -e`) option when running test cases. If every command in the
+test case exits with a `0` status code (success), the test passes. In this way,
+each line is an assertion of truth.
+
+## Table of contents
+
+**NOTE** The documentation has moved to
+
+
+
+- [Testing](#testing)
+- [Support](#support)
+- [Contributing](#contributing)
+- [Contact](#contact)
+- [Version history](#version-history)
+- [Background](#background)
+ * [What's the plan and why?](#whats-the-plan-and-why)
+ * [Why was this fork created?](#why-was-this-fork-created)
+- [Copyright](#copyright)
+
+
+
+## Testing
+
+```sh
+bin/bats --tap test
+```
+
+See also the [CI](./.github/workflows/tests.yml) settings for the current test environment and
+scripts.
+
+## Support
+
+The Bats source code repository is [hosted on
+GitHub](https://github.com/bats-core/bats-core). There you can file bugs on the
+issue tracker or submit tested pull requests for review.
+
+For real-world examples from open-source projects using Bats, see [Projects
+Using Bats](https://github.com/bats-core/bats-core/wiki/Projects-Using-Bats) on
+the wiki.
+
+To learn how to set up your editor for Bats syntax highlighting, see [Syntax
+Highlighting](https://github.com/bats-core/bats-core/wiki/Syntax-Highlighting)
+on the wiki.
+
+## Contributing
+
+For now see the [`docs`](docs) folder for project guides, work with us on the wiki
+or look at the other communication channels.
+
+## Contact
+
+- You can find and chat with us on our [Gitter].
+
+## Version history
+
+See `docs/CHANGELOG.md`.
+
+## Background
+
+
+### Why was this fork created?
+
+
+There was an initial [call for maintainers][call-maintain] for the original Bats repository, but write access to it could not be obtained. With development activity stalled, this fork allowed ongoing maintenance and forward progress for Bats.
+
+**Tuesday, September 19, 2017:** This was forked from [Bats][bats-orig] at
+commit [0360811][]. It was created via `git clone --bare` and `git push
+--mirror`.
+
+As of **Thursday, April 29, 2021:** the original [Bats][bats-orig] has been
+archived by the owner and is now read-only.
+
+This [bats-core](https://github.com/bats-core/bats-core) repo is now the community-maintained Bats project.
+
+[call-maintain]: https://github.com/sstephenson/bats/issues/150
+[bats-orig]: https://github.com/sstephenson/bats
+[0360811]: https://github.com/sstephenson/bats/commit/03608115df2071fff4eaaff1605768c275e5f81f
+
+## Copyright
+
+The Bats Logo was created by [Vukory](https://www.artstation.com/vukory) ([Github](https://github.com/vukory)) and sponsored by [SethFalco](https://github.com/SethFalco). If you want to use our logo, have a look at our [guidelines](./docs/source/assets/README.md#Usage-Guide-for-Third-Parties).
+
+© 2017-2024 bats-core organization
+
+© 2011-2016 Sam Stephenson
+
+Bats is released under an MIT-style license; see `LICENSE.md` for details.
+
+See the [parent project](https://github.com/bats-core) at GitHub or the
+[AUTHORS](AUTHORS) file for the current project maintainer team.
+
+[gitter]: https://gitter.im/bats-core/bats-core
diff --git a/node_modules/bats/bin/bats b/node_modules/bats/bin/bats
new file mode 100755
index 00000000..25ad051b
--- /dev/null
+++ b/node_modules/bats/bin/bats
@@ -0,0 +1,75 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# Note: We first need to use POSIX's `[ ... ]' instead of Bash's `[[ ... ]]'
+# because this is the check for Bash, where the shell may not be Bash. Once we
+# confirm that we are in Bash, we can use [[ ... ]] and (( ... )). Note that
+# these [[ ... ]] and (( ... )) do not cause syntax errors in POSIX shells,
+# though they can be parsed differently.
+if [ -z "${BASH_VERSION-}" ] ||
+ [[ -z "${BASH_VERSINFO-}" ]] ||
+ ((BASH_VERSINFO[0] < 3 || (BASH_VERSINFO[0] == 3 && BASH_VERSINFO[1] < 2)))
+then
+ printf 'bats: this program needs to be run by Bash >= 3.2\n' >&2
+ exit 1
+fi
+
+if command -v greadlink >/dev/null; then
+ bats_readlinkf() {
+ greadlink -f "$1"
+ }
+else
+ bats_readlinkf() {
+ readlink -f "$1"
+ }
+fi
+
+fallback_to_readlinkf_posix() {
+ bats_readlinkf() {
+ [ "${1:-}" ] || return 1
+ max_symlinks=40
+ CDPATH='' # to avoid changing to an unexpected directory
+
+ target=$1
+ [ -e "${target%/}" ] || target=${1%"${1##*[!/]}"} # trim trailing slashes
+ [ -d "${target:-/}" ] && target="$target/"
+
+ cd -P . 2>/dev/null || return 1
+ while [ "$max_symlinks" -ge 0 ] && max_symlinks=$((max_symlinks - 1)); do
+ if [ ! "$target" = "${target%/*}" ]; then
+ case $target in
+ /*) cd -P "${target%/*}/" 2>/dev/null || break ;;
+ *) cd -P "./${target%/*}" 2>/dev/null || break ;;
+ esac
+ target=${target##*/}
+ fi
+
+ if [ ! -L "$target" ]; then
+ target="${PWD%/}${target:+/}${target}"
+ printf '%s\n' "${target:-/}"
+ return 0
+ fi
+
+ # `ls -dl` format: "%s %u %s %s %u %s %s -> %s\n",
+ # , , , ,
+ # , , ,
+ # https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
+ link=$(ls -dl -- "$target" 2>/dev/null) || break
+ target=${link#*" $target -> "}
+ done
+ return 1
+ }
+}
+
+if ! BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}" 2>/dev/null); then
+ fallback_to_readlinkf_posix
+ BATS_PATH=$(bats_readlinkf "${BASH_SOURCE[0]}")
+fi
+
+export BATS_SAVED_PATH=$PATH
+BATS_BASE_LIBDIR=lib # this will be patched with the true value in install.sh
+
+export BATS_ROOT=${BATS_PATH%/*/*}
+export -f bats_readlinkf
+exec env BATS_ROOT="$BATS_ROOT" BATS_LIBDIR="${BATS_BASE_LIBDIR:-lib}" "$BATS_ROOT/libexec/bats-core/bats" "$@"
diff --git a/node_modules/bats/install.sh b/node_modules/bats/install.sh
new file mode 100755
index 00000000..edc26af7
--- /dev/null
+++ b/node_modules/bats/install.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+set -e
+
+BATS_ROOT="${0%/*}"
+PREFIX="${1%/}"
+LIBDIR="${2:-lib}"
+
+if [[ -z "$PREFIX" ]]; then
+ printf '%s\n' \
+ "usage: $0 [base_libdir]" \
+ " e.g. $0 /usr/local" \
+ " $0 /usr/local lib64" >&2
+ exit 1
+fi
+
+install -d -m 755 "$PREFIX"/{bin,libexec/bats-core,"${LIBDIR}"/bats-core,share/man/man{1,7}}
+
+install -m 755 "$BATS_ROOT/bin"/* "$PREFIX/bin"
+install -m 755 "$BATS_ROOT/libexec/bats-core"/* "$PREFIX/libexec/bats-core"
+install -m 755 "$BATS_ROOT/lib/bats-core"/* "$PREFIX/${LIBDIR}/bats-core"
+install -m 644 "$BATS_ROOT/man/bats.1" "$PREFIX/share/man/man1"
+install -m 644 "$BATS_ROOT/man/bats.7" "$PREFIX/share/man/man7"
+
+read -rd '' BATS_EXE_CONTENTS <"$PREFIX/bin/bats" || true
+BATS_EXE_CONTENTS=${BATS_EXE_CONTENTS/"BATS_BASE_LIBDIR=lib"/"BATS_BASE_LIBDIR=${LIBDIR}"}
+printf "%s" "$BATS_EXE_CONTENTS" >| "$PREFIX/bin/bats"
+
+echo "Installed Bats to $PREFIX/bin/bats"
diff --git a/node_modules/bats/lib/bats-core/common.bash b/node_modules/bats/lib/bats-core/common.bash
new file mode 100644
index 00000000..2bd1a5b2
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/common.bash
@@ -0,0 +1,278 @@
+#!/usr/bin/env bash
+
+bats_prefix_lines_for_tap_output() {
+ while IFS= read -r line; do
+ printf '# %s\n' "$line" || break # avoid feedback loop when errors are redirected into BATS_OUT (see #353)
+ done
+ if [[ -n "$line" ]]; then
+ printf '# %s\n' "$line"
+ fi
+}
+
+function bats_replace_filename() {
+ local line
+ while read -r line; do
+ printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
+ done
+ if [[ -n "$line" ]]; then
+ printf "%s\n" "${line//$BATS_TEST_SOURCE/$BATS_TEST_FILENAME}"
+ fi
+}
+
+bats_quote_code() { #
+ printf -v "$1" -- "%s%s%s" "$BATS_BEGIN_CODE_QUOTE" "$2" "$BATS_END_CODE_QUOTE"
+}
+
+bats_check_valid_version() {
+ if [[ ! $1 =~ [0-9]+.[0-9]+.[0-9]+ ]]; then
+ printf "ERROR: version '%s' must be of format ..!\n" "$1" >&2
+ exit 1
+ fi
+}
+
+# compares two versions. Return 0 when version1 < version2
+bats_version_lt() { #
+ bats_check_valid_version "$1"
+ bats_check_valid_version "$2"
+
+ local -a version1_parts version2_parts
+ IFS=. read -ra version1_parts <<<"$1"
+ IFS=. read -ra version2_parts <<<"$2"
+
+ local -i i
+ for i in {0..2}; do
+ if ((version1_parts[i] < version2_parts[i])); then
+ return 0
+ elif ((version1_parts[i] > version2_parts[i])); then
+ return 1
+ fi
+ done
+ # if we made it this far, they are equal -> also not less then
+ return 2 # use other failing return code to distinguish equal from gt
+}
+
+# ensure a minimum version of bats is running or exit with failure
+bats_require_minimum_version() { #
+ local required_minimum_version=$1
+
+ if bats_version_lt "$BATS_VERSION" "$required_minimum_version"; then
+ printf "BATS_VERSION=%s does not meet required minimum %s\n" "$BATS_VERSION" "$required_minimum_version"
+ exit 1
+ fi
+
+ if bats_version_lt "$BATS_GUARANTEED_MINIMUM_VERSION" "$required_minimum_version"; then
+ BATS_GUARANTEED_MINIMUM_VERSION="$required_minimum_version"
+ fi
+}
+
+# returns 0 when search-value is found in array
+bats_linear_reverse_search() { #
+ local -r search_value=$1 array_name=$2
+ eval "local -ri array_length=\${#${array_name}[@]}"
+ # shellcheck disable=SC2154
+ for ((i=array_length - 1; i >=0; --i)); do
+ eval "local value=\"\${${array_name}[i]}\""
+ # shellcheck disable=SC2154
+ if [[ $value == "$search_value" ]]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+# returns 0 when search-value is found in array
+bats_binary_search() { #
+ if [[ $# -ne 2 ]]; then
+ printf "ERROR: bats_binary_search requires exactly 2 arguments: \n" >&2
+ return 2
+ fi
+
+ local -r search_value=$1 array_name=$2
+
+ # we'd like to test if array is set but we cannot distinguish unset from empty arrays, so we need to skip that
+
+ local start=0 mid end mid_value
+ # start is inclusive, end is exclusive ...
+ eval "end=\${#${array_name}[@]}"
+
+ # so start == end means empty search space
+ while ((start < end)); do
+ mid=$(((start + end) / 2))
+ eval "mid_value=\${${array_name}[$mid]}"
+ if [[ "$mid_value" == "$search_value" ]]; then
+ return 0
+ elif [[ "$mid_value" < "$search_value" ]]; then
+ # This branch excludes equality -> +1 to skip the mid element.
+ # This +1 also avoids endless recursion on odd sized search ranges.
+ start=$((mid + 1))
+ else
+ end=$mid
+ fi
+ done
+
+ # did not find it -> its not there
+ return 1
+}
+
+# store the values in ascending (string!) order in result array
+# Intended for short lists! (uses insertion sort)
+bats_sort() { #
+ local -r result_name=$1
+ shift
+
+ if (($# == 1)) && [[ $1 == "" ]]; then
+ shift # remove leading "" to deal with bash 3 expanding "${empty_array[@]}" to one ""
+ fi
+
+ if (($# == 0)); then
+ eval "$result_name=()"
+ return 0
+ fi
+
+ local -a sorted_array=()
+ local -i i
+ while (( $# > 0 )); do # loop over input values
+ local current_value="$1"
+ shift
+ for ((i = ${#sorted_array[@]}; i >= 0; --i)); do # loop over output array from end
+ if (( i == 0 )) || [[ ${sorted_array[i - 1]} < $current_value ]]; then
+ # insert new element at (freed) desired location
+ sorted_array[i]=$current_value
+ break
+ else
+ # shift bigger elements one position to the end
+ sorted_array[i]=${sorted_array[i - 1]}
+ fi
+ done
+ done
+
+ eval "$result_name=(\"\${sorted_array[@]}\")"
+}
+
+# check if all search values (must be sorted!) are in the (sorted!) array
+# Intended for short lists/arrays!
+bats_all_in() { #
+ local -r haystack_array=$1
+ shift
+
+ local -i haystack_length # just to appease shellcheck
+ eval "local -r haystack_length=\${#${haystack_array}[@]}"
+
+ local -i haystack_index=0 # initialize only here to continue from last search position
+ local search_value haystack_value # just to appease shellcheck
+ local -i i
+ for ((i = 1; i <= $#; ++i)); do
+ eval "local search_value=${!i}"
+ for (( ; haystack_index < haystack_length; ++haystack_index)); do
+ eval "local haystack_value=\${${haystack_array}[$haystack_index]}"
+ if [[ $haystack_value > "$search_value" ]]; then
+ # we passed the location this value would have been at -> not found
+ return 1
+ elif [[ $haystack_value == "$search_value" ]]; then
+ continue 2 # search value found -> try the next one
+ fi
+ done
+ return 1 # we ran of the end of the haystack without finding the value!
+ done
+
+ # did not return from loop above -> all search values were found
+ return 0
+}
+
+# check if any search value (must be sorted!) is in the (sorted!) array
+# intended for short lists/arrays
+bats_any_in() { #
+ local -r haystack_array=$1
+ shift
+
+ local -i haystack_length # just to appease shellcheck
+ eval "local -r haystack_length=\${#${haystack_array}[@]}"
+
+ local -i haystack_index=0 # initialize only here to continue from last search position
+ local search_value haystack_value # just to appease shellcheck
+ local -i i
+ for ((i = 1; i <= $#; ++i)); do
+ eval "local search_value=${!i}"
+ for (( ; haystack_index < haystack_length; ++haystack_index)); do
+ eval "local haystack_value=\${${haystack_array}[$haystack_index]}"
+ if [[ $haystack_value > "$search_value" ]]; then
+ continue 2 # search value not in array! -> try next
+ elif [[ $haystack_value == "$search_value" ]]; then
+ return 0 # search value found
+ fi
+ done
+ done
+
+ # did not return from loop above -> no search value was found
+ return 1
+}
+
+bats_trim() { #
+ local -r bats_trim_ltrimmed=${2#"${2%%[![:space:]]*}"} # cut off leading whitespace
+ # shellcheck disable=SC2034 # used in eval!
+ local -r bats_trim_trimmed=${bats_trim_ltrimmed%"${bats_trim_ltrimmed##*[![:space:]]}"} # cut off trailing whitespace
+ eval "$1=\$bats_trim_trimmed"
+}
+
+# a helper function to work around unbound variable errors with ${arr[@]} on Bash 3
+bats_append_arrays_as_args() { # --
+ local -a trailing_args=()
+ while (($# > 0)) && [[ $1 != -- ]]; do
+ local array=$1
+ shift
+
+ if eval "(( \${#${array}[@]} > 0 ))"; then
+ eval "trailing_args+=(\"\${${array}[@]}\")"
+ fi
+ done
+ shift # remove -- separator
+
+ if (($# == 0)); then
+ printf "Error: append_arrays_as_args is missing a command or -- separator\n" >&2
+ return 1
+ fi
+
+ if ((${#trailing_args[@]} > 0)); then
+ "$@" "${trailing_args[@]}"
+ else
+ "$@"
+ fi
+}
+
+bats_format_file_line_reference() { #
+ # shellcheck disable=SC2034 # will be used in subimplementation
+ local output="${1?}"
+ shift
+ "bats_format_file_line_reference_${BATS_LINE_REFERENCE_FORMAT?}" "$@"
+}
+
+bats_format_file_line_reference_comma_line() {
+ printf -v "$output" "%s, line %d" "$@"
+}
+
+bats_format_file_line_reference_colon() {
+ printf -v "$output" "%s:%d" "$@"
+}
+
+# approximate realpath without subshell
+bats_approx_realpath() { #
+ local output=$1 path=$2
+ if [[ $path != /* ]]; then
+ path="$PWD/$path"
+ fi
+ # x/./y -> x/y
+ path=${path//\/.\//\/}
+ printf -v "$output" "%s" "$path"
+}
+
+bats_format_file_line_reference_uri() {
+ local filename=${1?} line=${2?}
+ bats_approx_realpath filename "$filename"
+ printf -v "$output" "file://%s:%d" "$filename" "$line"
+}
+
+# execute command with backed up path
+# to prevent path mocks from interfering with our internals
+bats_execute() { #
+ PATH="${BATS_SAVED_PATH?}" "$@"
+}
diff --git a/node_modules/bats/lib/bats-core/formatter.bash b/node_modules/bats/lib/bats-core/formatter.bash
new file mode 100644
index 00000000..aaf8096b
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/formatter.bash
@@ -0,0 +1,151 @@
+#!/usr/bin/env bash
+
+# reads (extended) bats tap streams from stdin and calls callback functions for each line
+#
+# Segmenting functions
+# ====================
+# bats_tap_stream_plan -> when the test plan is encountered
+# bats_tap_stream_suite -> when a new file is begun WARNING: extended only
+# bats_tap_stream_begin -> when a new test is begun WARNING: extended only
+#
+# Test result functions
+# =====================
+# If timing was enabled, BATS_FORMATTER_TEST_DURATION will be set to their duration in milliseconds
+# bats_tap_stream_ok -> when a test was successful
+# bats_tap_stream_not_ok -> when a test has failed. If the failure was due to a timeout,
+# BATS_FORMATTER_TEST_TIMEOUT is set to the timeout duration in seconds
+# bats_tap_stream_skipped -> when a test was skipped
+#
+# Context functions
+# =================
+# bats_tap_stream_comment -> when a comment line was encountered,
+# scope tells the last encountered of plan, begin, ok, not_ok, skipped, suite
+# bats_tap_stream_unknown -> when a line is encountered that does not match the previous entries,
+# scope @see bats_tap_stream_comment
+# forwards all input as is, when there is no TAP test plan header
+function bats_parse_internal_extended_tap() {
+ local header_pattern='[0-9]+\.\.[0-9]+'
+ IFS= read -r header
+
+ if [[ "$header" =~ $header_pattern ]]; then
+ bats_tap_stream_plan "${header:3}"
+ else
+ # If the first line isn't a TAP plan, print it and pass the rest through
+ printf '%s\n' "$header"
+ exec cat
+ fi
+
+ ok_line_regexpr="ok ([0-9]+) (.*)"
+ skip_line_regexpr="ok ([0-9]+) (.*) # skip( (.*))?$"
+ timeout_line_regexpr="not ok ([0-9]+) (.*) # timeout after ([0-9]+)s$"
+ not_ok_line_regexpr="not ok ([0-9]+) (.*)"
+
+ timing_expr="in ([0-9]+)ms$"
+ local test_name begin_index last_begin_index try_index ok_index not_ok_index index scope
+ begin_index=0
+ last_begin_index=-1
+ try_index=0
+ index=0
+ scope=plan
+ while IFS= read -r line; do
+ unset BATS_FORMATTER_TEST_DURATION BATS_FORMATTER_TEST_TIMEOUT
+ case "$line" in
+ 'begin '*) # this might only be called in extended tap output
+ scope=begin
+ begin_index=${line#begin }
+ begin_index=${begin_index%% *}
+ if [[ $begin_index == "$last_begin_index" ]]; then
+ (( ++try_index ))
+ else
+ try_index=0
+ fi
+ test_name="${line#begin "$begin_index" }"
+ bats_tap_stream_begin "$begin_index" "$test_name"
+ ;;
+ 'ok '*)
+ ((++index))
+ if [[ "$line" =~ $ok_line_regexpr ]]; then
+ ok_index="${BASH_REMATCH[1]}"
+ test_name="${BASH_REMATCH[2]}"
+ if [[ "$line" =~ $skip_line_regexpr ]]; then
+ scope=skipped
+ test_name="${BASH_REMATCH[2]}" # cut off name before "# skip"
+ local skip_reason="${BASH_REMATCH[4]}"
+ if [[ "$test_name" =~ $timing_expr ]]; then
+ local BATS_FORMATTER_TEST_DURATION="${BASH_REMATCH[1]}"
+ test_name="${test_name% in "${BATS_FORMATTER_TEST_DURATION}"ms}"
+ bats_tap_stream_skipped "$ok_index" "$test_name" "$skip_reason"
+ else
+ bats_tap_stream_skipped "$ok_index" "$test_name" "$skip_reason"
+ fi
+ else
+ scope=ok
+ if [[ "$line" =~ $timing_expr ]]; then
+ local BATS_FORMATTER_TEST_DURATION="${BASH_REMATCH[1]}"
+ bats_tap_stream_ok "$ok_index" "${test_name% in "${BASH_REMATCH[1]}"ms}"
+ else
+ bats_tap_stream_ok "$ok_index" "$test_name"
+ fi
+ fi
+ else
+ printf "ERROR: could not match ok line: %s" "$line" >&2
+ exit 1
+ fi
+ ;;
+ 'not ok '*)
+ ((++index))
+ scope=not_ok
+ if [[ "$line" =~ $not_ok_line_regexpr ]]; then
+ not_ok_index="${BASH_REMATCH[1]}"
+ test_name="${BASH_REMATCH[2]}"
+ if [[ "$line" =~ $timeout_line_regexpr ]]; then
+ not_ok_index="${BASH_REMATCH[1]}"
+ test_name="${BASH_REMATCH[2]}"
+ # shellcheck disable=SC2034 # used in bats_tap_stream_ok
+ local BATS_FORMATTER_TEST_TIMEOUT="${BASH_REMATCH[3]}"
+ fi
+ if [[ "$test_name" =~ $timing_expr ]]; then
+ # shellcheck disable=SC2034 # used in bats_tap_stream_ok
+ local BATS_FORMATTER_TEST_DURATION="${BASH_REMATCH[1]}"
+ test_name="${test_name% in "${BASH_REMATCH[1]}"ms}"
+ fi
+ bats_tap_stream_not_ok "$not_ok_index" "$test_name"
+ else
+ printf "ERROR: could not match not ok line: %s" "$line" >&2
+ exit 1
+ fi
+ ;;
+ '# '*)
+ bats_tap_stream_comment "${line:2}" "$scope"
+ ;;
+ '#')
+ bats_tap_stream_comment "" "$scope"
+ ;;
+ 'suite '*)
+ scope=suite
+ # pass on the
+ bats_tap_stream_suite "${line:6}"
+ ;;
+ *)
+ bats_tap_stream_unknown "$line" "$scope"
+ ;;
+ esac
+ done
+}
+
+normalize_base_path() { #
+ # the relative path root to use for reporting filenames
+ # this is mainly intended for suite mode, where this will be the suite root folder
+ local base_path="$2"
+ # use the containing directory when --base-path is a file
+ if [[ ! -d "$base_path" ]]; then
+ base_path="$(dirname "$base_path")"
+ fi
+ # get the absolute path
+ base_path="$(cd "$base_path" && pwd)"
+ # ensure the path ends with / to strip that later on
+ if [[ "${base_path}" != *"/" ]]; then
+ base_path="$base_path/"
+ fi
+ printf -v "$1" "%s" "$base_path"
+}
diff --git a/node_modules/bats/lib/bats-core/preprocessing.bash b/node_modules/bats/lib/bats-core/preprocessing.bash
new file mode 100644
index 00000000..069cfd40
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/preprocessing.bash
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+bats_export_preprocess_source_BATS_TEST_SOURCE() {
+ # export to make it visible to bats_evaluate_preprocessed_source
+ # since the latter runs in bats-exec-test's bash while this runs in bats-exec-file's
+ export BATS_TEST_SOURCE="$BATS_RUN_TMPDIR/${BATS_TEST_FILE_NUMBER?}-${BATS_TEST_FILENAME##*/}.src"
+}
+
+bats_preprocess_source() { # index
+ bats_export_preprocess_source_BATS_TEST_SOURCE
+ # shellcheck disable=SC2153
+ CHECK_BATS_COMMENT_COMMANDS=1 "$BATS_ROOT/libexec/bats-core/bats-preprocess" "$BATS_TEST_FILENAME" >"$BATS_TEST_SOURCE"
+}
+
+bats_evaluate_preprocessed_source() {
+ # Dynamically loaded user files provided outside of Bats.
+ # shellcheck disable=SC1090
+ source "${BATS_TEST_SOURCE?}"
+}
diff --git a/node_modules/bats/lib/bats-core/semaphore.bash b/node_modules/bats/lib/bats-core/semaphore.bash
new file mode 100644
index 00000000..a196ac82
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/semaphore.bash
@@ -0,0 +1,113 @@
+#!/usr/bin/env bash
+
+bats_run_under_flock() {
+ flock "$BATS_SEMAPHORE_DIR" "$@"
+}
+
+bats_run_under_shlock() {
+ local lockfile="$BATS_SEMAPHORE_DIR/shlock.lock"
+ while ! shlock -p $$ -f "$lockfile"; do
+ sleep 1
+ done
+ # we got the lock now, execute the command
+ "$@"
+ local status=$?
+ # free the lock
+ rm -f "$lockfile"
+ return $status
+ }
+
+# setup the semaphore environment for the loading file
+bats_semaphore_setup() {
+ export -f bats_semaphore_get_free_slot_count
+ export -f bats_semaphore_acquire_while_locked
+ export BATS_SEMAPHORE_DIR="$BATS_RUN_TMPDIR/semaphores"
+
+ if command -v flock >/dev/null; then
+ BATS_LOCKING_IMPLEMENTATION=flock
+ elif command -v shlock >/dev/null; then
+ BATS_LOCKING_IMPLEMENTATION=shlock
+ else
+ printf "ERROR: flock/shlock is required for parallelization within files!\n" >&2
+ exit 1
+ fi
+}
+
+# $1 - output directory for stdout/stderr
+# $@ - command to run
+# run the given command in a semaphore
+# block when there is no free slot for the semaphore
+# when there is a free slot, run the command in background
+# gather the output of the command in files in the given directory
+bats_semaphore_run() {
+ local output_dir=$1
+ shift
+ local semaphore_slot
+ semaphore_slot=$(bats_semaphore_acquire_slot)
+ bats_semaphore_release_wrapper "$output_dir" "$semaphore_slot" "$@" &
+ printf "%d\n" "$!"
+}
+
+# $1 - output directory for stdout/stderr
+# $@ - command to run
+# this wraps the actual function call to install some traps on exiting
+bats_semaphore_release_wrapper() {
+ local output_dir="$1"
+ local semaphore_name="$2"
+ shift 2 # all other parameters will be use for the command to execute
+
+ # shellcheck disable=SC2064 # we want to expand the semaphore_name right now!
+ trap "status=$?; bats_semaphore_release_slot '$semaphore_name'; exit $status" EXIT
+
+ mkdir -p "$output_dir"
+ "$@" 2>"$output_dir/stderr" >"$output_dir/stdout"
+ local status=$?
+
+ # bash bug: the exit trap is not called for the background process
+ bats_semaphore_release_slot "$semaphore_name"
+ trap - EXIT # avoid calling release twice
+ return $status
+}
+
+bats_semaphore_acquire_while_locked() {
+ if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then
+ local slot=0
+ while [[ -e "$BATS_SEMAPHORE_DIR/slot-$slot" ]]; do
+ ((++slot))
+ done
+ if [[ $slot -lt $BATS_SEMAPHORE_NUMBER_OF_SLOTS ]]; then
+ touch "$BATS_SEMAPHORE_DIR/slot-$slot" && printf "%d\n" "$slot" && return 0
+ fi
+ fi
+ return 1
+}
+
+# block until a semaphore slot becomes free
+# prints the number of the slot that it received
+bats_semaphore_acquire_slot() {
+ mkdir -p "$BATS_SEMAPHORE_DIR"
+ # wait for a slot to become free
+ # TODO: avoid busy waiting by using signals -> this opens op prioritizing possibilities as well
+ while true; do
+ # don't lock for reading, we are fine with spuriously getting no free slot
+ if [[ $(bats_semaphore_get_free_slot_count) -gt 0 ]]; then
+ bats_run_under_"$BATS_LOCKING_IMPLEMENTATION" \
+ bash -c bats_semaphore_acquire_while_locked \
+ && break
+ fi
+ sleep 1
+ done
+}
+
+bats_semaphore_release_slot() {
+ # we don't need to lock this, since only our process owns this file
+ # and freeing a semaphore cannot lead to conflicts with others
+ rm "$BATS_SEMAPHORE_DIR/slot-$1" # this will fail if we had not acquired a semaphore!
+}
+
+bats_semaphore_get_free_slot_count() {
+ # find might error out without returning something useful when a file is deleted,
+ # while the directory is traversed -> only continue when there was no error
+ until used_slots=$(find "$BATS_SEMAPHORE_DIR" -name 'slot-*' 2>/dev/null | wc -l); do :; done
+ echo $((BATS_SEMAPHORE_NUMBER_OF_SLOTS - used_slots))
+}
diff --git a/node_modules/bats/lib/bats-core/test_functions.bash b/node_modules/bats/lib/bats-core/test_functions.bash
new file mode 100644
index 00000000..e6e9e261
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/test_functions.bash
@@ -0,0 +1,517 @@
+#!/usr/bin/env bash
+
+# this must be called for each test file!
+_bats_test_functions_setup() { #
+ BATS_TEST_DIRNAME="${BATS_TEST_FILENAME%/*}"
+ BATS_TEST_NAMES=()
+ # shellcheck disable=SC2034
+ BATS_TEST_NUMBER=${1?}
+}
+
+# shellcheck source=lib/bats-core/warnings.bash
+source "$BATS_ROOT/$BATS_LIBDIR/bats-core/warnings.bash"
+
+# find_in_bats_lib_path echoes the first recognized load path to
+# a library in BATS_LIB_PATH or relative to BATS_TEST_DIRNAME.
+#
+# Libraries relative to BATS_TEST_DIRNAME take precedence over
+# BATS_LIB_PATH.
+#
+# If no library is found find_in_bats_lib_path returns 1.
+find_in_bats_lib_path() { #
+ local return_var="${1:?}"
+ local library_name="${2:?}"
+
+ local -a bats_lib_paths
+ IFS=: read -ra bats_lib_paths <<<"$BATS_LIB_PATH"
+
+ for path in "${bats_lib_paths[@]}"; do
+ if [[ -f "$path/$library_name" ]]; then
+ printf -v "$return_var" "%s" "$path/$library_name"
+ # A library load path was found, return
+ return 0
+ elif [[ -f "$path/$library_name/load.bash" ]]; then
+ printf -v "$return_var" "%s" "$path/$library_name/load.bash"
+ # A library load path was found, return
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+# bats_internal_load expects an absolute path that is a library load path.
+#
+# If the library load path points to a file (a library loader) it is
+# sourced.
+#
+# If it points to a directory all files ending in .bash inside of the
+# directory are sourced.
+#
+# If the sourcing of the library loader or of a file in a library
+# directory fails bats_internal_load prints an error message and returns 1.
+#
+# If the passed library load path is not absolute or is not a valid file
+# or directory bats_internal_load prints an error message and returns 1.
+bats_internal_load() {
+ local library_load_path="${1:?}"
+
+ if [[ "${library_load_path:0:1}" != / ]]; then
+ printf "Passed library load path is not an absolute path: %s\n" "$library_load_path" >&2
+ return 1
+ fi
+
+ # library_load_path is a library loader
+ if [[ -f "$library_load_path" ]]; then
+ # shellcheck disable=SC1090
+ if ! source "$library_load_path"; then
+ printf "Error while sourcing library loader at '%s'\n" "$library_load_path" >&2
+ return 1
+ fi
+ return 0
+ fi
+
+ printf "Passed library load path is neither a library loader nor library directory: %s\n" "$library_load_path" >&2
+ return 1
+}
+
+# bats_load_safe accepts an argument called 'slug' and attempts to find and
+# source a library based on the slug.
+#
+# A slug can be an absolute path or a relative path.
+#
+# If the slug is not an absolute path it is resolved relative to
+# BATS_TEST_DIRNAME
+#
+# The resolved slug is passed to bats_internal_load.
+# If bats_internal_load fails bats_load_safe returns 1.
+#
+# If no library load path can be found bats_load_safe prints an error message
+# and returns 1.
+bats_load_safe() {
+ local slug="${1:?}"
+ if [[ ${slug:0:1} != / ]]; then # relative paths are relative to BATS_TEST_DIRNAME
+ slug="$BATS_TEST_DIRNAME/$slug"
+ fi
+
+ if [[ -f "$slug.bash" ]]; then
+ bats_internal_load "$slug.bash"
+ return $?
+ elif [[ -f "$slug" ]]; then
+ bats_internal_load "$slug"
+ return $?
+ fi
+
+ # loading from PATH (retained for backwards compatibility)
+ if [[ ! -f "$1" ]] && type -P "$1" >/dev/null; then
+ # shellcheck disable=SC1090
+ source "$1"
+ return $?
+ fi
+
+ # No library load path can be found
+ printf "bats_load_safe: Could not find '%s'[.bash]\n" "$slug" >&2
+ return 1
+}
+
+bats_load_library_safe() { #
+ local slug="${1:?}" library_path
+
+ # Check for library load paths in BATS_TEST_DIRNAME and BATS_LIB_PATH
+ if [[ ${slug:0:1} != / ]]; then
+ if ! find_in_bats_lib_path library_path "$slug"; then
+ printf "Could not find library '%s' relative to test file or in BATS_LIB_PATH\n" "$slug" >&2
+ return 1
+ fi
+ else
+ # absolute paths are taken as is
+ library_path="$slug"
+ if [[ ! -f "$library_path" ]]; then
+ printf "Could not find library on absolute path '%s'\n" "$library_path" >&2
+ return 1
+ fi
+ fi
+
+ bats_internal_load "$library_path"
+ return $?
+}
+
+# immediately exit on error, use bats_load_library_safe to catch and handle errors
+bats_load_library() { #
+ if ! bats_load_library_safe "$@"; then
+ exit 1
+ fi
+}
+
+# load acts like bats_load_safe but exits the shell instead of returning 1.
+load() {
+ if ! bats_load_safe "$@"; then
+ exit 1
+ fi
+}
+
+bats_redirect_stderr_into_file() {
+ "$@" 2>>"$bats_run_separate_stderr_file" # use >> to see collisions' content
+}
+
+bats_merge_stdout_and_stderr() {
+ "$@" 2>&1
+}
+
+# write separate lines from into
+bats_separate_lines() { #
+ local -r output_array_name="$1"
+ local -r input_var_name="$2"
+ local input="${!input_var_name}"
+ if [[ $keep_empty_lines ]]; then
+ local bats_separate_lines_lines=()
+ if [[ -n "$input" ]]; then # avoid getting an empty line for empty input
+ # remove one trailing \n if it exists to compensate its addition by <<<
+ input=${input%$'\n'}
+ while IFS= read -r line; do
+ bats_separate_lines_lines+=("$line")
+ done <<<"${input}"
+ fi
+ eval "${output_array_name}=(\"\${bats_separate_lines_lines[@]}\")"
+ else
+ # shellcheck disable=SC2034,SC2206
+ IFS=$'\n' read -d '' -r -a "$output_array_name" <<<"${!input_var_name}" || true # don't fail due to EOF
+ fi
+}
+
+bats_pipe() { # [-N] [--] command0 [ \| command1 [ \| command2 [...]]]
+ # This will run each command given, piping them appropriately.
+ # Meant to be used in combination with `run` helper to allow piped commands
+ # to be used.
+ # Note that `\|` must be used, not `|`.
+ # By default, the exit code of this command will be the last failure in the
+ # chain of piped commands (similar to `set -o pipefail`).
+ # Supplying -N (e.g. -0) will instead always use the exit code of the command
+ # at that position in the chain.
+ # --returned-status=N could be used as an alternative to -N. This also allows
+ # for negative values (which count from the end in reverse order).
+
+ local pipestatus_position=
+
+ # parse options starting with -
+ while [[ $# -gt 0 ]] && [[ $1 == -* ]]; do
+ case "$1" in
+ -[0-9]*)
+ pipestatus_position="${1#-}"
+ ;;
+ --returned-status*)
+ if [ "$1" = "--returned-status" ]; then
+ pipestatus_position="$2"
+ shift
+ elif [[ "$1" =~ ^--returned-status= ]]; then
+ pipestatus_position="${1#--returned-status=}"
+ else
+ printf "Usage error: unknown flag '%s'" "$1" >&2
+ return 1
+ fi
+ ;;
+ --)
+ shift # eat the -- before breaking away
+ break
+ ;;
+ *)
+ printf "Usage error: unknown flag '%s'" "$1" >&2
+ return 1
+ ;;
+ esac
+ shift
+ done
+
+ # parse and validate arguments, escape as necessary
+ local -a commands_and_args=("$@")
+ local -a escaped_args=()
+ local -i pipe_count=0
+ local -i previous_pipe_index=-1
+ local -i index=0
+ for (( index = 0; index < $#; index++ )); do
+ local current_command_or_arg="${commands_and_args[$index]}"
+ local escaped_arg="$current_command_or_arg"
+ if [[ "$current_command_or_arg" != '|' ]]; then
+ # escape args to protect them when eval'd (e.g. if they contain whitespace).
+ printf -v escaped_arg "%q" "$current_command_or_arg"
+ elif [ "$current_command_or_arg" = "|" ]; then
+ if [ "$index" -eq 0 ]; then
+ printf "Usage error: Cannot have leading \`\\|\`.\n" >&2
+ return 1
+ fi
+ if (( (previous_pipe_index + 1) >= index )); then
+ printf "Usage error: Cannot have consecutive \`\\|\`. Found at argument position '%s'.\n" "$index" >&2
+ return 1
+ fi
+ (( ++pipe_count ))
+ previous_pipe_index="$index"
+ fi
+ escaped_args+=("$escaped_arg")
+ done
+
+ if (( (previous_pipe_index > 0) && (previous_pipe_index == ($# - 1)) )); then
+ printf "Usage error: Cannot have trailing \`\\|\`.\n" >&2
+ return 1
+ fi
+
+ if (( pipe_count == 0 )); then
+ # Don't allow for no pipes. This might be a typo in the test,
+ # e.g. `run bats_pipe command0 | command1`
+ # instead of `run bats_pipe command0 \| command1`
+ # Unfortunately, we can't catch `run bats_pipe command0 \| command1 | command2`.
+ # But this check is better than just allowing no pipes.
+ printf "Usage error: No \`\\|\`s found. Is this an error?\n" >&2
+ return 1
+ fi
+
+ # there will be pipe_count + 1 entries in PIPE_STATUS (pipe_count number of \|'s between each entry).
+ # valid indices are [-(pipe_count + 1), pipe_count]
+ if [ -n "$pipestatus_position" ] && (( (pipestatus_position > pipe_count) || (-pipestatus_position > (pipe_count + 1)) )); then
+ printf "Usage error: Too large of -N argument (or --returned-status) given. Argument value: '%s'.\n" "$pipestatus_position" >&2
+ return 1
+ fi
+
+ # run commands and return appropriate pipe status
+ local -a __bats_pipe_eval_pipe_status=()
+ eval "${escaped_args[*]}" '; __bats_pipe_eval_pipe_status=(${PIPESTATUS[@]})'
+
+ local result_status=
+ if [ -z "$pipestatus_position" ]; then
+ # if we are performing default "last failure" behavior,
+ # iterate backwards through pipe_status to find the last error.
+ result_status=0
+ for index in "${!__bats_pipe_eval_pipe_status[@]}"; do
+ # OSX bash doesn't support negative indexing.
+ local backward_iter_index="$((${#__bats_pipe_eval_pipe_status[@]} - index - 1))"
+ local status_at_backward_iter_index="${__bats_pipe_eval_pipe_status[$backward_iter_index]}"
+ if (( status_at_backward_iter_index != 0 )); then
+ result_status="$status_at_backward_iter_index"
+ break;
+ fi
+ done
+ elif (( pipestatus_position >= 0 )); then
+ result_status="${__bats_pipe_eval_pipe_status[$pipestatus_position]}"
+ else
+ # Must use positive values for some bash's (like OSX).
+ local backward_iter_index="$((${#__bats_pipe_eval_pipe_status[@]} + pipestatus_position))"
+ result_status="${__bats_pipe_eval_pipe_status[$backward_iter_index]}"
+ fi
+
+ return "$result_status"
+}
+
+run() { # [!|-N] [--keep-empty-lines] [--separate-stderr] [--]
+ # This has to be restored on exit from this function to avoid leaking our trap INT into surrounding code.
+ # Non zero exits won't restore under the assumption that they will fail the test before it can be aborted,
+ # which allows us to avoid duplicating the restore code on every exit path
+ trap bats_interrupt_trap_in_run INT
+ local expected_rc=
+ local keep_empty_lines=
+ local output_case=merged
+ local has_flags=
+ # parse options starting with -
+ while [[ $# -gt 0 ]] && [[ $1 == -* || $1 == '!' ]]; do
+ has_flags=1
+ case "$1" in
+ '!')
+ expected_rc=-1
+ ;;
+ -[0-9]*)
+ expected_rc=${1#-}
+ if [[ $expected_rc =~ [^0-9] ]]; then
+ printf "Usage error: run: '-NNN' requires numeric NNN (got: %s)\n" "$expected_rc" >&2
+ return 1
+ elif [[ $expected_rc -gt 255 ]]; then
+ printf "Usage error: run: '-NNN': NNN must be <= 255 (got: %d)\n" "$expected_rc" >&2
+ return 1
+ fi
+ ;;
+ --keep-empty-lines)
+ keep_empty_lines=1
+ ;;
+ --separate-stderr)
+ output_case="separate"
+ ;;
+ --)
+ shift # eat the -- before breaking away
+ break
+ ;;
+ *)
+ printf "Usage error: unknown flag '%s'" "$1" >&2
+ return 1
+ ;;
+ esac
+ shift
+ done
+
+ if [[ -n $has_flags ]]; then
+ bats_warn_minimum_guaranteed_version "Using flags on \`run\`" 1.5.0
+ fi
+
+ local pre_command=
+
+ case "$output_case" in
+ merged) # redirects stderr into stdout and fills only $output/$lines
+ pre_command=bats_merge_stdout_and_stderr
+ ;;
+ separate) # splits stderr into own file and fills $stderr/$stderr_lines too
+ local bats_run_separate_stderr_file
+ bats_run_separate_stderr_file="$(mktemp "${BATS_TEST_TMPDIR}/separate-stderr-XXXXXX")"
+ pre_command=bats_redirect_stderr_into_file
+ ;;
+ esac
+
+ local origFlags="$-"
+ set +eET
+ if [[ $keep_empty_lines ]]; then
+ # 'output', 'status', 'lines' are global variables available to tests.
+ # preserve trailing newlines by appending . and removing it later
+ # shellcheck disable=SC2034
+ output="$(
+ "$pre_command" "$@"
+ status=$?
+ printf .
+ exit $status
+ )" && status=0 || status=$?
+ output="${output%.}"
+ else
+ # 'output', 'status', 'lines' are global variables available to tests.
+ # shellcheck disable=SC2034
+ output="$("$pre_command" "$@")" && status=0 || status=$?
+ fi
+
+ bats_separate_lines lines output
+
+ if [[ "$output_case" == separate ]]; then
+ # shellcheck disable=SC2034
+ read -d '' -r stderr <"$bats_run_separate_stderr_file" || true
+ bats_separate_lines stderr_lines stderr
+ else
+ unset stderr stderr_lines
+ fi
+
+ # shellcheck disable=SC2034
+ BATS_RUN_COMMAND="${*}"
+ set "-$origFlags"
+
+ bats_run_print_output() {
+ if [[ -n "$output" ]]; then
+ printf "%s\n" "$output"
+ fi
+ if [[ "$output_case" == separate && -n "$stderr" ]]; then
+ printf "stderr:\n%s\n" "$stderr"
+ fi
+ }
+
+ if [[ -n "$expected_rc" ]]; then
+ if [[ "$expected_rc" = "-1" ]]; then
+ if [[ "$status" -eq 0 ]]; then
+ BATS_ERROR_SUFFIX=", expected nonzero exit code!"
+ bats_run_print_output
+ return 1
+ fi
+ elif [ "$status" -ne "$expected_rc" ]; then
+ # shellcheck disable=SC2034
+ BATS_ERROR_SUFFIX=", expected exit code $expected_rc, got $status"
+ bats_run_print_output
+ return 1
+ fi
+ elif [[ "$status" -eq 127 ]]; then # "command not found"
+ bats_generate_warning 1 "$BATS_RUN_COMMAND"
+ fi
+
+ if [[ ${BATS_VERBOSE_RUN:-} ]]; then
+ bats_run_print_output
+ fi
+
+ # don't leak our trap into surrounding code
+ trap bats_interrupt_trap INT
+}
+
+setup() {
+ return 0
+}
+
+teardown() {
+ return 0
+}
+
+skip() {
+ # if this is a skip in teardown ...
+ if [[ -n "${BATS_TEARDOWN_STARTED-}" ]]; then
+ # ... we want to skip the rest of teardown.
+ # communicate to bats_exit_trap that the teardown was completed without error
+ # shellcheck disable=SC2034
+ BATS_TEARDOWN_COMPLETED=1
+ # if we are already in the exit trap (e.g. due to previous skip) ...
+ if [[ "$BATS_TEARDOWN_STARTED" == as-exit-trap ]]; then
+ # ... we need to do the rest of the tear_down_trap that would otherwise be skipped after the next call to exit
+ bats_exit_trap
+ # and then do the exit (at the end of this function)
+ fi
+ # if we aren't in exit trap, the normal exit handling should suffice
+ else
+ # ... this is either skip in test or skip in setup.
+ # Following variables are used in bats-exec-test which sources this file
+ # shellcheck disable=SC2034
+ BATS_TEST_SKIPPED="${1:-1}"
+ # shellcheck disable=SC2034
+ BATS_TEST_COMPLETED=1
+ fi
+ exit 0
+}
+
+bats_test_function() {
+ local tags=() current_tags=()
+ while (( $# > 0 )); do
+ case "$1" in
+ --description)
+ local test_description=
+ # use eval to resolve variable references in test names
+ eval "printf -v test_description '%s' \"$2\""
+ shift 2
+ ;;
+ --tags)
+ if [[ "$2" != "" ]]; then # avoid unbound variable with set -u Bash 3
+ IFS=',' read -ra current_tags <<<"$2"
+ tags+=("${current_tags[@]}")
+ fi
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ printf "ERROR: unknown option %s for bats_test_function" "$1" >&2
+ exit 1
+ ;;
+ esac
+ done
+
+ if (( ${#tags[@]} > 1 )); then # avoid unbound variable with set -u Bash 3
+ bats_sort tags "${tags[@]}"
+ fi
+
+ BATS_TEST_NAMES+=("$*")
+ local quoted_parameters
+ printf -v quoted_parameters " %q" "$@"
+ quoted_parameters=${quoted_parameters:1} # cut off leading space
+
+ # if this is the currently selected test, set tags and name
+ # this should only be entered from bats-exec-test
+ if [[ ${BATS_TEST_NAME-} == "$quoted_parameters" ]]; then
+ # shellcheck disable=SC2034
+ BATS_TEST_TAGS=("${tags[@]+${tags[@]}}")
+ export BATS_TEST_DESCRIPTION="${test_description-$*}"
+ # shellcheck disable=SC2034
+ BATS_TEST_COMMAND=("$@")
+ fi
+}
+
+# decides whether a failed test should be run again
+bats_should_retry_test() {
+ # test try number starts at 1
+ # 0 retries means run only first try
+ ((BATS_TEST_TRY_NUMBER <= BATS_TEST_RETRIES))
+}
diff --git a/node_modules/bats/lib/bats-core/tracing.bash b/node_modules/bats/lib/bats-core/tracing.bash
new file mode 100644
index 00000000..0fc12102
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/tracing.bash
@@ -0,0 +1,425 @@
+#!/usr/bin/env bash
+
+# shellcheck source=lib/bats-core/common.bash
+source "$BATS_ROOT/$BATS_LIBDIR/bats-core/common.bash"
+
+# set limit such that traces are only captured for calls at the same depth as this function in the calltree
+bats_set_stacktrace_limit() {
+ BATS_STACK_TRACE_LIMIT=$(( ${#FUNCNAME[@]} - 1 )) # adjust by -1 to account for call to this functions
+}
+
+bats_capture_stack_trace() {
+ local test_file
+ local funcname
+ local i
+
+ BATS_DEBUG_LAST_STACK_TRACE=()
+ local limit=$(( ${#FUNCNAME[@]} - ${BATS_STACK_TRACE_LIMIT-0} ))
+ # TODO: why is the line number off by one in @test "--trace recurses into functions but not into run"
+ for ((i = 2; i < limit ; ++i)); do
+ # Use BATS_TEST_SOURCE if necessary to work around Bash < 4.4 bug whereby
+ # calling an exported function erases the test file's BASH_SOURCE entry.
+ test_file="${BASH_SOURCE[$i]:-$BATS_TEST_SOURCE}"
+ funcname="${FUNCNAME[$i]}"
+ BATS_DEBUG_LAST_STACK_TRACE+=("${BASH_LINENO[$((i - 1))]} $funcname $test_file")
+ done
+}
+
+bats_get_failure_stack_trace() {
+ local stack_trace_var
+ # See bats_debug_trap for details.
+ if [[ -n "${BATS_DEBUG_LAST_STACK_TRACE_IS_VALID:-}" ]]; then
+ stack_trace_var=BATS_DEBUG_LAST_STACK_TRACE
+ else
+ stack_trace_var=BATS_DEBUG_LASTLAST_STACK_TRACE
+ fi
+ # shellcheck disable=SC2016
+ eval "$(printf \
+ '%s=(${%s[@]+"${%s[@]}"})' \
+ "${1}" \
+ "${stack_trace_var}" \
+ "${stack_trace_var}")"
+}
+
+bats_print_stack_trace() {
+ local frame
+ local index=1
+ local count="${#@}"
+ local filename
+ local lineno
+
+ for frame in "$@"; do
+ bats_frame_filename "$frame" 'filename'
+ bats_trim_filename "$filename" 'filename'
+ bats_frame_lineno "$frame" 'lineno'
+
+ printf '%s' "${BATS_STACK_TRACE_PREFIX-# }"
+ if [[ $index -eq 1 ]]; then
+ printf '('
+ else
+ printf ' '
+ fi
+
+ local fn
+ bats_frame_function "$frame" 'fn'
+ if [[ "$fn" != "${BATS_TEST_NAME-}" ]] &&
+ # don't print "from function `source'"",
+ # when failing in free code during `source $test_file` from bats-exec-file
+ ! [[ "$fn" == 'source' && $index -eq $count ]]; then
+ local quoted_fn
+ bats_quote_code quoted_fn "$fn"
+ printf "from function %s " "$quoted_fn"
+ fi
+
+ local reference
+ bats_format_file_line_reference reference "$filename" "$lineno"
+ if [[ $index -eq $count ]]; then
+ printf 'in test file %s)\n' "$reference"
+ else
+ printf 'in file %s,\n' "$reference"
+ fi
+
+ ((++index))
+ done
+}
+
+bats_print_failed_command() {
+ local stack_trace=("${@}")
+ if [[ ${#stack_trace[@]} -eq 0 ]]; then
+ return 0
+ fi
+ local frame="${stack_trace[${#stack_trace[@]} - 1]}"
+ local filename
+ local lineno
+ local failed_line
+ local failed_command
+
+ bats_frame_filename "$frame" 'filename'
+ bats_frame_lineno "$frame" 'lineno'
+ bats_extract_line "$filename" "$lineno" 'failed_line'
+ bats_strip_string "$failed_line" 'failed_command'
+ local quoted_failed_command
+ bats_quote_code quoted_failed_command "$failed_command"
+ printf '# %s ' "${quoted_failed_command}"
+
+ if [[ "${BATS_TIMED_OUT-NOTSET}" != NOTSET ]]; then
+ # the other values can be safely overwritten here,
+ # as the timeout is the primary reason for failure
+ BATS_ERROR_SUFFIX=" due to timeout"
+ fi
+
+ if [[ "$BATS_ERROR_STATUS" -eq 1 ]]; then
+ printf 'failed%s\n' "$BATS_ERROR_SUFFIX"
+ else
+ printf 'failed with status %d%s\n' "$BATS_ERROR_STATUS" "$BATS_ERROR_SUFFIX"
+ fi
+}
+
+bats_frame_lineno() {
+ printf -v "$2" '%s' "${1%% *}"
+}
+
+bats_frame_function() {
+ local __bff_function="${1#* }"
+ printf -v "$2" '%s' "${__bff_function%% *}"
+}
+
+bats_frame_filename() {
+ local __bff_filename="${1#* }"
+ __bff_filename="${__bff_filename#* }"
+
+ if [[ "$__bff_filename" == "${BATS_TEST_SOURCE-}" ]]; then
+ __bff_filename="$BATS_TEST_FILENAME"
+ fi
+ printf -v "$2" '%s' "$__bff_filename"
+}
+
+bats_extract_line() {
+ local __bats_extract_line_line
+ local __bats_extract_line_index=0
+
+ while IFS= read -r __bats_extract_line_line; do
+ if [[ "$((++__bats_extract_line_index))" -eq "$2" ]]; then
+ printf -v "$3" '%s' "${__bats_extract_line_line%$'\r'}"
+ break
+ fi
+ done <"$1"
+}
+
+bats_strip_string() {
+ [[ "$1" =~ ^[[:space:]]*(.*)[[:space:]]*$ ]]
+ printf -v "$2" '%s' "${BASH_REMATCH[1]}"
+}
+
+bats_trim_filename() {
+ printf -v "$2" '%s' "${1#"$BATS_CWD"/}"
+}
+
+# normalize a windows path from e.g. C:/directory to /c/directory
+# The path must point to an existing/accessible directory, not a file!
+bats_normalize_windows_dir_path() { #
+ local output_var="$1" path="$2"
+ if [[ "$output_var" != NORMALIZED_INPUT ]]; then
+ local NORMALIZED_INPUT
+ fi
+ if [[ $path == ?:* ]]; then
+ NORMALIZED_INPUT="$(
+ cd "$path" || exit 1
+ pwd
+ )"
+ else
+ NORMALIZED_INPUT="$path"
+ fi
+ printf -v "$output_var" "%s" "$NORMALIZED_INPUT"
+}
+
+bats_emit_trace_context() {
+ local padding='$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
+ local reference
+ bats_format_file_line_reference reference "${file##*/}" "$line"
+ printf '%s [%s]\n' "${padding::${#BASH_LINENO[@]}-limit-3}" "$reference" >&4
+}
+
+bats_emit_trace_command() {
+ local padding='$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
+ printf '%s %s\n' "${padding::${#BASH_LINENO[@]}-limit-3}" "$BASH_COMMAND" >&4
+
+ # keep track of printed commands
+ BATS_LAST_BASH_COMMAND="$BASH_COMMAND"
+ BATS_LAST_BASH_LINENO="$line"
+}
+
+BATS_EMIT_TRACE_LAST_STACK_DIFF=0
+
+bats_emit_trace() {
+ if [[ ${BATS_TRACE_LEVEL:-0} -gt 0 ]]; then
+ local line=${BASH_LINENO[1]} limit=${BATS_STACK_TRACE_LIMIT-0}
+ # shellcheck disable=SC2016
+ if (( ${#FUNCNAME[@]} > limit + 2 )) # only emit below BATS_STRACK_TRACE_LIMIT (adjust by 2 for trap+this function call)
+ # avoid printing the same line twice on errexit
+ [[ $BASH_COMMAND != "$BATS_LAST_BASH_COMMAND" || $line != "$BATS_LAST_BASH_LINENO" ]]; then
+ local file="${BASH_SOURCE[2]}" # index 2: skip over bats_emit_trace and bats_debug_trap
+ if [[ $file == "${BATS_TEST_SOURCE:-}" ]]; then
+ file="$BATS_TEST_FILENAME"
+ fi
+ # stack size difference since last call of this function
+ # <0: means new function call
+ # >0: means return
+ # =0: in same function as before (assuming we did not skip return/call)
+ local stack_diff=$(( BATS_LAST_STACK_DEPTH - ${#BASH_LINENO[@]} ))
+ # show context immediately when returning or on second command in new function
+ # as the first "command" is the function itself
+ if (( stack_diff > 0 )) || (( BATS_EMIT_TRACE_LAST_STACK_DIFF < 0 )); then
+ bats_emit_trace_context
+ fi
+ # only print command when moving up or staying in same function
+ # again, avoids printing the first command (the function itself) in new function
+ if (( stack_diff >= 0 )); then
+ bats_emit_trace_command
+ fi
+
+ BATS_EMIT_TRACE_LAST_STACK_DIFF=$stack_diff
+ fi
+ # always update to detect stack depth changes regardless of printing
+ BATS_LAST_STACK_DEPTH="${#BASH_LINENO[@]}"
+ fi
+}
+
+# bats_debug_trap tracks the last line of code executed within a test. This is
+# necessary because $BASH_LINENO is often incorrect inside of ERR and EXIT
+# trap handlers.
+#
+# Below are tables describing different command failure scenarios and the
+# reliability of $BASH_LINENO within different the executed DEBUG, ERR, and EXIT
+# trap handlers. Naturally, the behaviors change between versions of Bash.
+#
+# Table rows should be read left to right. For example, on bash version
+# 4.0.44(2)-release, if a test executes `false` (or any other failing external
+# command), bash will do the following in order:
+# 1. Call the DEBUG trap handler (bats_debug_trap) with $BASH_LINENO referring
+# to the source line containing the `false` command, then
+# 2. Call the DEBUG trap handler again, but with an incorrect $BASH_LINENO, then
+# 3. Call the ERR trap handler, but with a (possibly-different) incorrect
+# $BASH_LINENO, then
+# 4. Call the DEBUG trap handler again, but with $BASH_LINENO set to 1, then
+# 5. Call the EXIT trap handler, with $BASH_LINENO set to 1.
+#
+# bash version 4.4.20(1)-release
+# command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT
+# -------------+-------------+--------------+---------+-------------+--------
+# false | OK | OK | OK | BAD[1] | BAD[1]
+# [[ 1 = 2 ]] | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1]
+# (( 1 = 2 )) | OK | BAD[2] | BAD[2] | BAD[1] | BAD[1]
+# ! true | OK | --- | BAD[4] | --- | BAD[1]
+# $var_dne | OK | --- | --- | BAD[1] | BAD[1]
+# source /dne | OK | --- | --- | BAD[1] | BAD[1]
+#
+# bash version 4.0.44(2)-release
+# command | first DEBUG | second DEBUG | ERR | third DEBUG | EXIT
+# -------------+-------------+--------------+---------+-------------+--------
+# false | OK | BAD[3] | BAD[3] | BAD[1] | BAD[1]
+# [[ 1 = 2 ]] | OK | --- | BAD[3] | --- | BAD[1]
+# (( 1 = 2 )) | OK | --- | BAD[3] | --- | BAD[1]
+# ! true | OK | --- | BAD[3] | --- | BAD[1]
+# $var_dne | OK | --- | --- | BAD[1] | BAD[1]
+# source /dne | OK | --- | --- | BAD[1] | BAD[1]
+#
+# [1] The reported line number is always 1.
+# [2] The reported source location is that of the beginning of the function
+# calling the command.
+# [3] The reported line is that of the last command executed in the DEBUG trap
+# handler.
+# [4] The reported source location is that of the call to the function calling
+# the command.
+bats_debug_trap() {
+ # on windows we sometimes get a mix of paths (when install via nmp install -g)
+ # which have C:/... or /c/... comparing them is going to be problematic.
+ # We need to normalize them to a common format!
+ local NORMALIZED_INPUT
+ bats_normalize_windows_dir_path NORMALIZED_INPUT "${1%/*}"
+ local path
+ for path in "${BATS_DEBUG_EXCLUDE_PATHS[@]}"; do
+ if [[ "$NORMALIZED_INPUT" == "$path"* ]]; then
+ return # skip this call
+ fi
+ done
+
+ # don't update the trace within library functions or we get backtraces from inside traps
+ # also don't record new stack traces while handling interruptions, to avoid overriding the interrupted command
+ if [[ "${BATS_INTERRUPTED-NOTSET}" == NOTSET &&
+ "${BATS_TIMED_OUT-NOTSET}" == NOTSET ]]; then
+ BATS_DEBUG_LASTLAST_STACK_TRACE=(
+ ${BATS_DEBUG_LAST_STACK_TRACE[@]+"${BATS_DEBUG_LAST_STACK_TRACE[@]}"}
+ )
+
+ BATS_DEBUG_LAST_LINENO=(${BASH_LINENO[@]+"${BASH_LINENO[@]}"})
+ BATS_DEBUG_LAST_SOURCE=(${BASH_SOURCE[@]+"${BASH_SOURCE[@]}"})
+ bats_capture_stack_trace
+ bats_emit_trace
+ fi
+}
+
+# For some versions of Bash, the `ERR` trap may not always fire for every
+# command failure, but the `EXIT` trap will. Also, some command failures may not
+# set `$?` properly. See #72 and #81 for details.
+#
+# For this reason, we call `bats_check_status_from_trap` at the very beginning
+# of `bats_teardown_trap` and check the value of `$BATS_TEST_COMPLETED` before
+# taking other actions. We also adjust the exit status value if needed.
+#
+# See `bats_exit_trap` for an additional EXIT error handling case when `$?`
+# isn't set properly during `teardown()` errors.
+bats_check_status_from_trap() {
+ local status="$?"
+ if [[ -z "${BATS_TEST_COMPLETED:-}" ]]; then
+ BATS_ERROR_STATUS="${BATS_ERROR_STATUS:-$status}"
+ if [[ "$BATS_ERROR_STATUS" -eq 0 ]]; then
+ BATS_ERROR_STATUS=1
+ fi
+ trap - DEBUG
+ fi
+}
+
+bats_add_debug_exclude_path() { #
+ if [[ -z "$1" ]]; then # don't exclude everything
+ printf "bats_add_debug_exclude_path: Exclude path must not be empty!\n" >&2
+ return 1
+ fi
+ if [[ "$OSTYPE" == cygwin || "$OSTYPE" == msys ]]; then
+ local normalized_dir
+ bats_normalize_windows_dir_path normalized_dir "$1"
+ BATS_DEBUG_EXCLUDE_PATHS+=("$normalized_dir")
+ else
+ BATS_DEBUG_EXCLUDE_PATHS+=("$1")
+ fi
+}
+
+bats_setup_tracing() {
+ # Variables for capturing accurate stack traces. See bats_debug_trap for
+ # details.
+ #
+ # BATS_DEBUG_LAST_LINENO, BATS_DEBUG_LAST_SOURCE, and
+ # BATS_DEBUG_LAST_STACK_TRACE hold data from the most recent call to
+ # bats_debug_trap.
+ #
+ # BATS_DEBUG_LASTLAST_STACK_TRACE holds data from two bats_debug_trap calls
+ # ago.
+ #
+ # BATS_DEBUG_LAST_STACK_TRACE_IS_VALID indicates that
+ # BATS_DEBUG_LAST_STACK_TRACE contains the stack trace of the test's error. If
+ # unset, BATS_DEBUG_LAST_STACK_TRACE is unreliable and
+ # BATS_DEBUG_LASTLAST_STACK_TRACE should be used instead.
+ BATS_DEBUG_LASTLAST_STACK_TRACE=()
+ BATS_DEBUG_LAST_LINENO=()
+ BATS_DEBUG_LAST_SOURCE=()
+ BATS_DEBUG_LAST_STACK_TRACE=()
+ BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=
+ BATS_ERROR_SUFFIX=
+ BATS_DEBUG_EXCLUDE_PATHS=()
+ # exclude some paths by default
+ bats_add_debug_exclude_path "$BATS_ROOT/$BATS_LIBDIR/"
+ bats_add_debug_exclude_path "$BATS_ROOT/libexec/"
+
+ exec 4<&1 # used for tracing
+ if [[ "${BATS_TRACE_LEVEL:-0}" -gt 0 ]]; then
+ # avoid undefined variable errors
+ BATS_LAST_BASH_COMMAND=
+ BATS_LAST_BASH_LINENO=
+ BATS_LAST_STACK_DEPTH=
+ # try to exclude helper libraries if found, this is only relevant for tracing
+ while read -r path; do
+ bats_add_debug_exclude_path "$path"
+ done < <(find "$PWD" -type d -name bats-assert -o -name bats-support)
+ fi
+
+ local exclude_paths path
+ # exclude user defined libraries
+ IFS=':' read -r exclude_paths <<<"${BATS_DEBUG_EXCLUDE_PATHS:-}"
+ for path in "${exclude_paths[@]}"; do
+ if [[ -n "$path" ]]; then
+ bats_add_debug_exclude_path "$path"
+ fi
+ done
+
+ # turn on traps after setting excludes to avoid tracing the exclude setup
+ trap 'bats_debug_trap "$BASH_SOURCE"' DEBUG
+ trap 'bats_error_trap' ERR
+}
+
+# predefine to avoid problems when the user does not declare one
+bats::on_failure() {
+ :
+}
+
+bats_error_trap() {
+ bats_check_status_from_trap
+ bats::on_failure "$BATS_ERROR_STATUS"
+
+ # If necessary, undo the most recent stack trace captured by bats_debug_trap.
+ # See bats_debug_trap for details.
+ if [[ "${BASH_LINENO[*]}" = "${BATS_DEBUG_LAST_LINENO[*]:-}" &&
+ "${BASH_SOURCE[*]}" = "${BATS_DEBUG_LAST_SOURCE[*]:-}" &&
+ -z "$BATS_DEBUG_LAST_STACK_TRACE_IS_VALID" ]]; then
+ BATS_DEBUG_LAST_STACK_TRACE=(
+ ${BATS_DEBUG_LASTLAST_STACK_TRACE[@]+"${BATS_DEBUG_LASTLAST_STACK_TRACE[@]}"}
+ )
+ fi
+ BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=1
+}
+
+bats_interrupt_trap() {
+ # mark the interruption, to handle during exit
+ BATS_INTERRUPTED=true
+ BATS_ERROR_STATUS=130
+ # debug trap fires before interrupt trap but gets wrong linenumber (line 1)
+ # -> use last stack trace instead of BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=true
+}
+
+# this is used inside run()
+bats_interrupt_trap_in_run() {
+ # mark the interruption, to handle during exit
+ BATS_INTERRUPTED=true
+ BATS_ERROR_STATUS=130
+ BATS_DEBUG_LAST_STACK_TRACE_IS_VALID=true
+ exit 130
+}
diff --git a/node_modules/bats/lib/bats-core/validator.bash b/node_modules/bats/lib/bats-core/validator.bash
new file mode 100644
index 00000000..59fc2c1e
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/validator.bash
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+bats_test_count_validator() {
+ trap '' INT # continue forwarding
+ header_pattern='[0-9]+\.\.[0-9]+'
+ IFS= read -r header
+ # repeat the header
+ printf "%s\n" "$header"
+
+ # if we detect a TAP plan
+ if [[ "$header" =~ $header_pattern ]]; then
+ # extract the number of tests ...
+ local expected_number_of_tests="${header:3}"
+ # ... count the actual number of [not ] oks...
+ local actual_number_of_tests=0
+ while IFS= read -r line; do
+ # forward line
+ printf "%s\n" "$line"
+ case "$line" in
+ 'ok '*)
+ ((++actual_number_of_tests))
+ ;;
+ 'not ok'*)
+ ((++actual_number_of_tests))
+ ;;
+ esac
+ done
+ # ... and error if they are not the same
+ if [[ "${actual_number_of_tests}" != "${expected_number_of_tests}" ]]; then
+ printf '# bats warning: Executed %s instead of expected %s tests\n' "$actual_number_of_tests" "$expected_number_of_tests"
+ return 1
+ fi
+ else
+ # forward output unchanged
+ cat
+ fi
+}
diff --git a/node_modules/bats/lib/bats-core/warnings.bash b/node_modules/bats/lib/bats-core/warnings.bash
new file mode 100644
index 00000000..5762d743
--- /dev/null
+++ b/node_modules/bats/lib/bats-core/warnings.bash
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+# shellcheck source=lib/bats-core/tracing.bash
+source "$BATS_ROOT/$BATS_LIBDIR/bats-core/tracing.bash"
+
+# generate a warning report for the parent call's call site
+bats_generate_warning() { # [--no-stacktrace] [...]
+ local warning_number="${1-}" padding="00"
+ shift
+ local no_stacktrace=
+ if [[ ${1-} == --no-stacktrace ]]; then
+ no_stacktrace=1
+ shift
+ fi
+ if [[ $warning_number =~ [0-9]+ ]] && ((warning_number < ${#BATS_WARNING_SHORT_DESCS[@]})); then
+ {
+ printf "BW%s: ${BATS_WARNING_SHORT_DESCS[$warning_number]}\n" "${padding:${#warning_number}}${warning_number}" "$@"
+ if [[ -z "$no_stacktrace" ]]; then
+ bats_capture_stack_trace
+ BATS_STACK_TRACE_PREFIX=' ' bats_print_stack_trace "${BATS_DEBUG_LAST_STACK_TRACE[@]}"
+ fi
+ } >>"$BATS_WARNING_FILE" 2>&3
+ else
+ printf "Invalid Bats warning number '%s'. It must be an integer between 1 and %d." "$warning_number" "$((${#BATS_WARNING_SHORT_DESCS[@]} - 1))" >&2
+ exit 1
+ fi
+}
+
+# generate a warning if the BATS_GUARANTEED_MINIMUM_VERSION is not high enough
+bats_warn_minimum_guaranteed_version() { #
+ if bats_version_lt "$BATS_GUARANTEED_MINIMUM_VERSION" "$2"; then
+ bats_generate_warning 2 "$1" "$2" "$2"
+ fi
+}
+
+# put after functions to avoid line changes in tests when new ones get added
+BATS_WARNING_SHORT_DESCS=(
+ # to start with 1
+ 'PADDING'
+ # see issue #578 for context
+ "\`run\`'s command \`%s\` exited with code 127, indicating 'Command not found'. Use run's return code checks, e.g. \`run -127\`, to fix this message."
+ "%s requires at least BATS_VERSION=%s. Use \`bats_require_minimum_version %s\` to fix this message."
+ "\`setup_suite\` is visible to test file '%s', but was not executed. It belongs into 'setup_suite.bash' to be picked up automatically."
+)
diff --git a/node_modules/bats/libexec/bats-core/bats b/node_modules/bats/libexec/bats-core/bats
new file mode 100755
index 00000000..d30f799f
--- /dev/null
+++ b/node_modules/bats/libexec/bats-core/bats
@@ -0,0 +1,525 @@
+#!/usr/bin/env bash
+set -e
+
+export BATS_VERSION='1.13.0'
+VALID_FORMATTERS="pretty, junit, tap, tap13"
+
+version() {
+ printf 'Bats %s\n' "$BATS_VERSION"
+}
+
+abort() {
+ local print_usage=1
+ if [[ ${1:-} == --no-print-usage ]]; then
+ print_usage=
+ shift
+ fi
+ printf 'Error: %s\n' "$1" >&2
+ if [[ -n $print_usage ]]; then
+ usage >&2
+ fi
+ exit 1
+}
+
+usage() {
+ local cmd="${0##*/}"
+ local line
+
+ cat <
+ ${cmd} [-h | -v]
+
+HELP_TEXT_HEADER
+
+ cat <<'HELP_TEXT_BODY'
+ is the path to a Bats test file, or the path to a directory
+ containing Bats test files (ending with ".bats")
+
+ --abort Stop execution of suite on first failed test
+ -c, --count Count test cases without running any tests
+ --code-quote-style