aboutsummaryrefslogtreecommitdiff
path: root/scripts/formatters/apheleia-npx
blob: 8f6a3663bcba0c8a0a6f438e98d4bf089c973592 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/env bash

# This script is like npx but also works for yarn pnp projects, and
# never tries to install anything. It is very fast.
#
# The script takes as arguments a command to execute and the arguments
# to pass to it. If the command is installed as a binary by an npm
# module in the current project, then that binary is used. Otherwise,
# the script is execed as normal from $PATH. In either case, the
# working directory is preserved.

if (( "$#" == 0 )); then
    echo >&2 "usage: apheleia-npx CMD [ARG...]"
    exit 1
fi

# location of this script
scripts_dir="$(cd $(dirname ${BASH_SOURCE[0]}) &>/dev/null && pwd)"
pnp_bin="${scripts_dir}/pnp-bin.js"

# This function prints the name of the current directory if it
# contains a file or directory named after the first argument, or the
# parent directory if it contains such a file, or the parent's parent,
# and so on. If no such file is found it returns nonzero.
# https://unix.stackexchange.com/a/22215
find_upwards() {
    fname="$1"

    path="${PWD}"
    while [[ -n "${path}" && ! -e "${path}/${fname}" ]]; do
        path="${path%/*}"
    done
    [[ -n "${path}" ]] && echo "${path}"
}

dir="$(find_upwards package.json)"

if [[ -d $dir ]]; then
    cd $dir

    pnp_root=$(find_upwards '.pnp.cjs')
    npm_root=$(find_upwards 'node_modules')

    if [[ -n ${pnp_root} && ${#pnp_root} -gt ${#npm_root} ]]; then
        # trying pnp
        pnp_path="${pnp_root}/.pnp.cjs"
        bin="$(${pnp_bin} ${pnp_path} $1)"
        # note: $bin might not be on the real filesystem,
        #   might be in a zip archive
        if [[ -n $bin ]]; then
            if [[ -f "${pnp_path}/.pnp.loader.mjs" ]]; then
                loader_opt="--loader ${pnp_path}/.pnp.loader.mjs"
            fi
            node=$(which node)
            command="${node} --require ${pnp_path} ${loader_opt} ${bin} ${@:2}"
            exec ${command}
        fi
    elif [[ -n ${npm_root} ]]; then
        # trying npm
        node_modules_paths=(\
            $(node -e 'console.log(require.resolve.paths("").join("\n"))'))
        for path in ${node_modules_paths[@]}; do
            if [[ -x "${path}/.bin/$1" ]]; then
                exec "${path}/.bin/$1" "${@:2}"
            fi
        done
    fi
fi

# Fall back to executing the command if it's installed and on the user's $PATH
exec "$@"