Skip to content

Commit

Permalink
1.0.0 :: enex -> nx
Browse files Browse the repository at this point in the history
  • Loading branch information
evnp committed Jun 7, 2023
1 parent dae1577 commit e619847
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 132 deletions.
153 changes: 83 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,102 +1,115 @@
A minimalist command runner for npm packages, with a focus on developer ergonomics.

```
______ __ __ ______ __ __
/\ ___\ /\ `. /\ \ /\ ___\ /\_\_\_\
\ \ ___\ \ \ `. \ \ \ \ ___\ \/_/\_\/_
\ \_____\ \ \_\ `.\_\ \ \_____\ /\_\/\_\
\/_____/ \/_/ \/_/ \/_____/ \/_/\/_/ n(pm) execute
__ __ __ __
/\ `./\ \ /\_\_\_\
\ \ .`.` \ \/_/\_\/_
\ \_\ `._\ /\_\/\_\
\/_/ \/_/ \/_/\/_/ npm execute
```

[![shellcheck](https://github.com/evnp/enex/workflows/shellcheck/badge.svg)](https://github.com/evnp/enex/actions)
[![latest release](https://img.shields.io/github/release/evnp/enex.svg)](https://github.com/evnp/enex/releases/latest)
[![npm package](https://img.shields.io/npm/v/enex.svg)](https://www.npmjs.com/package/enex)
[![license](https://img.shields.io/github/license/evnp/enex.svg?color=blue)](https://github.com/evnp/enex/blob/master/LICENSE.md)
[![shellcheck](https://github.com/evnp/nx/workflows/shellcheck/badge.svg)](https://github.com/evnp/nx/actions)
[![latest release](https://img.shields.io/github/release/evnp/nx.svg)](https://github.com/evnp/nx/releases/latest)
[![npm package](https://img.shields.io/npm/v/nx.svg)](https://www.npmjs.com/package/nx)
[![license](https://img.shields.io/github/license/evnp/nx.svg?color=blue)](https://github.com/evnp/nx/blob/master/LICENSE.md)

`enex` lets you interact with any NPM package — that is, anything with a `package.json` — in as few keystrokes as you want (or as possible!). It's eminently configurable, but with a default setup of `source $HOME/enex/enex.sh` in your dotfile of choice, it will add these aliases to any shell:
`nx` lets you interact with any NPM package (anything with a `package.json`) in as few keystrokes as as possible.<br>
With a default setup of `source $HOME/nx/nx.sh` in your dotfile of choice, it will add these aliases to any shell:

```sh
n <cmd> -> npm <cmd> OR npm run <cmd> # enex intelligently adds `run`
# only when necessary, but you
ns <opts> -> npm run start <opts> # may use it if you prefer
n -> # show list of currently configured nx aliases
n <cmd> -> npm <cmd> OR npm run <cmd> # nx intelligently adds `run`
# only when necessary, but you
ns <opts> -> npm run start <opts> # may use it if you prefer
nb <opts> -> npm run build <opts>
nf <opts> -> npm run format <opts>
nl <opts> -> npm run lint <opts>
nk <opts> -> npm run link <opts>
nt <opts> -> npm run test <opts>
ntw <opts> -> npm run test -- --watch <opts>

ni <opts> -> npm install <opts>
nu <opts> -> npm uninstall <opts>
nis <opts> -> npm install --save <opts>
nus <opts> -> npm uninstall --save <opts>
nid <opts> -> npm install --save-dev <opts>
nud <opts> -> npm uninstall --save-dev <opts>
nt w <opts> -> npm run test --watch <opts>
# `w` may be added to any nx command to produce `--watch`

ni <pkg> -> npm install <pkg>
nu <pkg> -> npm uninstall <pkg>
nis <pkg> -> npm install --save <pkg>
nus <pkg> -> npm uninstall --save <pkg>
nid <pkg> -> npm install --save-dev <pkg>
nud <pkg> -> npm uninstall --save-dev <pkg>
nig <pkg> -> npm install --global <pkg>
nug <pkg> -> npm uninstall --glboal <pkg>
```

`enex` is only 50 lines of code (with comments!) — if you're interested in knowing exactly what will be running on your system, peruse it [here](https://github.com/evnp/enex/blob/main/enex.sh). Any project that touts minimalism should strive to be understood completely within a few minutes; this is, and will remain, a goal of `enex`.
Of these aliases, only `nl` exists as a pre-existing Bash command (<https://ss64.com/bash/nl.html>), used for prefixing file lines with line numbers. If you'd like to disable this particular `nx` alias so that the built-in `nl` is not overridden, use this configuration in your shell rc file:

```bash
export NX_ALIASES=install,uninstall,start,test,build,format,k/link,help; source "$HOME/nx/nx.sh"
```

`nx` is only 50 lines of code (with comments!) — if you're interested in knowing exactly what will be running on your system, peruse it [here](https://github.com/evnp/nx/blob/main/nx.sh). Any project that touts minimalism should strive to be understood completely within a few minutes; this is, and will remain, a goal of `nx`.

Setup
-----
```sh
npm install -g enex
which enex
> /some/path/to/node_modules/.bin/enex.sh
npm install -g nx
which nx
> /some/path/to/node_modules/.bin/nx.sh

# add to your .bashrc / .zshrc / etc. ->
source "/some/path/to/node_modules/.bin/enex.sh"
source "/some/path/to/node_modules/.bin/nx.sh"
```
Or if you prefer, install by checking out the repository manually:
```sh
git clone https://github.com/evnp/enex.git
git clone https://github.com/evnp/nx.git

# add to your .bashrc / .zshrc / etc. ->
source "$HOME/enex/enex.sh"
source "$HOME/nx/nx.sh"

# or if you didn't check the repository in $HOME directory:
source "/your/path/to/repository/enex/enex.sh"
source "/your/path/to/repository/nx/nx.sh"
```
Open a new shell instance and `enex` will have initialized these aliases:
Open a new shell instance and `nx` will have initialized these aliases:
```sh
alias n="enex" # -> contextually equivalent to `npm ...` or `npm run ...`

alias ns="enex start" # -> npm start
alias nt="enex test" # -> npm test; also ntw -> npm run test -- --watch
alias nb="enex build" # -> npm run build
alias nf="enex format" # -> npm run format
alias ni="enex install" # -> npm install
alias nu="enex uninstall" # -> npm uninstall
alias n="nx" # -> contextually equivalent to `npm ...` or `npm run ...`

alias ns="nx start" # -> npm start
alias nt="nx test" # -> npm test; also ntw -> npm run test -- --watch
alias nb="nx build" # -> npm run build
alias nf="nx format" # -> npm run format
alias ni="nx install" # -> npm install
alias nu="nx uninstall" # -> npm uninstall
# also nis, nid, nus, nud for install/uninstall --save/--save-dev combinations, see above
```
If you'd like to opt out of these default aliases or customize them, use env vars when initializing `enex` to configure:
If you'd like to opt out of these default aliases or customize them, use env vars when initializing `nx` to configure:
```sh
# to opt out of `n` alias and simply use the full command `enex`:
export ENEX_COMMAND=0; source "$HOME/enex/enex.sh"

# to opt out of enex aliasing altogether:
export ENEX_COMMAND=0; export ENEX_ALIASES=0; source "$HOME/enex/enex.sh"

# to use the custom command `myencmd` to invoke enex instead of `n`:
export ENEX_COMMAND=myencmd; source "$HOME/enex/enex.sh"
> alias myencmd="enex"

# to define your own custom set of enex aliases:
export ENEX_ALIASES=build,push,deploy; source "$HOME/enex/enex.sh"
> alias n="enex"
> alias nb="enex build"
> alias np="enex push"
> alias nd="enex deploy"
# to opt out of `n` alias and simply use the full command `nx`:
export NX_COMMAND=0; source "$HOME/nx/nx.sh"

# to opt out of nx aliasing altogether:
export NX_COMMAND=0; export NX_ALIASES=0; source "$HOME/nx/nx.sh"

# to use the custom command `myencmd` to invoke nx instead of `n`:
export NX_COMMAND=myencmd; source "$HOME/nx/nx.sh"
> alias myencmd="nx"

# to define your own custom set of nx aliases:
export NX_ALIASES=build,push,deploy; source "$HOME/nx/nx.sh"
> alias n="nx"
> alias nb="nx build"
> alias np="nx push"
> alias nd="nx deploy"
# note: this overrides the set of default aliases entirely, so you
# will need to redefine them explicitly if some are desired

# to define an alias whose shortcut does not match its first letter:
export ENEX_ALIASES=build,x/specialthing,deploy; source "$HOME/enex/enex.sh"
> alias n="enex"
> alias nb="enex build"
> alias nx="enex specialthing"
> alias nd="enex deploy"
export NX_ALIASES=build,x/specialthing,deploy; source "$HOME/nx/nx.sh"
> alias n="nx"
> alias nb="nx build"
> alias nx="nx specialthing"
> alias nd="nx deploy"
```


By default, if enex does not detect a `package.json` file within the directory it is being invoked from, it will search for one within directories up to 2 levels below, and an arbitary number of levels above, exiting immediately if it reaches your home directory. This allows you to run enex commands from anywhere within a project with this very common directory structure, or similar project structures:
By default, if nx does not detect a `package.json` file within the directory it is being invoked from, it will search for one within directories up to 2 levels below, and an arbitary number of levels above, exiting immediately if it reaches your home directory. This allows you to run nx commands from anywhere within a project with this very common directory structure, or similar project structures:
```sh
$HOME/
└─project/
Expand All @@ -106,26 +119,26 @@ $HOME/
├─src/
└─dir/
```
Normally, you'd need to first navigate to the `frontend/` before invoking any `npm` command; enex handles this step invisibly for you in a subshell, so that you remain in the same directory you started in after the operation is complete.
Normally, you'd need to first navigate to the `frontend/` before invoking any `npm` command; nx handles this step invisibly for you in a subshell, so that you remain in the same directory you started in after the operation is complete.

If for any reason you prefer to skip this "auto-find" step, add the following env var to your enex configuration:
If for any reason you prefer to skip this "auto-find" step, add the following env var to your nx configuration:
```sh
export ENEX_FIND=0; source "$HOME/enex/enex.sh"
export NX_FIND=0; source "$HOME/nx/nx.sh"
```

If you use [nvm](https://github.com/nvm-sh/nvm), enex can be configured to call `nvm use` before each command invocation to ensure NodeJS and NPM versions matching the current directory's `.nvmrc` are used. To enable this behavior, add the following env var to your enex configuration:
If you use [nvm](https://github.com/nvm-sh/nvm), nx can be configured to call `nvm use` before each command invocation to ensure NodeJS and NPM versions matching the current directory's `.nvmrc` are used. To enable this behavior, add the following env var to your nx configuration:
```sh
export ENEX_NVM=1; source "$HOME/enex/enex.sh"
export NX_NVM=1; source "$HOME/nx/nx.sh"
```

If you'd like enex to await confirmation of current node+npm versions before executing commands, add the following env var to your enex configuration:
If you'd like nx to await confirmation of current node+npm versions before executing commands, add the following env var to your nx configuration:
```sh
export ENEX_CONFIRM=1; source "$HOME/enex/enex.sh"
export NX_CONFIRM=1; source "$HOME/nx/nx.sh"
```

While sorting out configuration, it may be useful to have enex output the complete set of aliases that are generated when a new shell session begins. To do so, add:
While sorting out configuration, it may be useful to have nx output the complete set of aliases that are generated when a new shell session begins. To do so, add:
```sh
export ENEX_VERBOSE=1; source "$HOME/enex/enex.sh"
export NX_VERBOSE=1; source "$HOME/nx/nx.sh"
```

That's it!
Expand Down
49 changes: 0 additions & 49 deletions enex.sh

This file was deleted.

43 changes: 43 additions & 0 deletions nx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# : nx 0.0.8 ::
# shellcheck disable=SC2139 # shellcheck.net/wiki/SC2139 # allow parameter expansion within alias strings #
function nx() ( local pkg="" cmd="" npmcmds=""
npmcmds="$( npm -h | awk '/access/,/whoami/' | sed -E 's/ (help|start|test),//g' | xargs | sed 's/, /|/g' )"
# :: print current aliases and exit when "n" is run with no arguments ::
[[ -z "$1" ]] && alias | grep "='nx " | sed 's/^alias //' | sed 's/=/ · /' | sed "s/nx /npm run /" | sed -E "s/run (${npmcmds})/\1/" | tr -d "'" && exit 0
[[ "${npmcmds}" == *"|$1|"* || "${npmcmds}" == "$1|"* || "${npmcmds}" == *"|$1" ]] && cmd=('npm' "$1") || cmd=('npm' 'run' "$1" "${2:+--}")
[[ "$2" == 'w' ]] && set -- "$1" "--watch" "${@:3}" # :: rewrite 'w' to '--watch' if provided as second arg ""
# :: find closest package.json (file path containing fewest "/" characters) :: export NX_FIND=0; source "$HOME/nx/nx.sh" (to disable) ::
while [[ ! "${NX_FIND}" =~ ^(0|false|FALSE)$ && ! -f "./package.json" ]] && [[ "$2" != '--global' ]]; do
[[ "$( pwd )" == "$HOME" ]] && echo "No package.json found." && exit 1
pkg="$( find . -name package.json -maxdepth 3 | grep -v node_modules | awk -F/ '{print NF,$0}' | sort -n | cut -d' ' -f2- | head -1 )"
cd "$( [[ -n "${pkg}" ]] && dirname "${pkg}" || echo '..' )" || exit 1
done
# :: call "nvm use" automatically before running commands :: export NX_NVM=1; source "$HOME/nx/nx.sh" (to enable) ::
[[ "${NX_NVM}" =~ ^(1|true|TRUE)$ ]] && nvm use &>/dev/null
# :: await confirmation of current node+npm versions before executing command :: export NX_CONFIRM=1; source "$HOME/nx/nx.sh" (to enable) ::
if [[ "${NX_CONFIRM}" =~ ^(1|true|TRUE)$ ]]; then
read -rsn1 -p "${cmd[*]} ${*:2} "$'\n'"Press any key to run · CTRL+C to cancel · node $( node -v ) · npm $( npm -v )"$'\n\n'
fi
"${cmd[@]}" "${@:2}" # :: execute constructed npm command ::
)
# :: default command alias :: n -> nx :: eg. n install -> npm install, n build -> npm run build, etc.
# :: export NX_COMMAND=0; source "$HOME/nx/nx.sh" (to disable) ::
if ! [[ "${NX_COMMAND}" =~ ^(0|false|FALSE)$ ]]; then
alias "${NX_COMMAND:-n}"="nx"
fi
# :: default sub-command aliases ::
# nb -> npm run build nt -> npm test nf -> npm run format nl -> npm run lint nh -> npm run help
# ns -> npm start nk -> npm link ni -> npm install nu -> npm uninstall nis, nid, nus, nud -> npm [un]install --save[-dev]
# :: export NX_ALIASES=0; source "$HOME/nx/nx.sh" (to disable) ::
if ! [[ "${NX_ALIASES}" =~ ^(0|false|FALSE)$ ]]; then
for word in $( tr -cs '[:alnum:]._-/' ' ' <<< "${NX_ALIASES:-install,uninstall,start,test,build,format,lint,k/link,help}" ); do
[[ "${NX_COMMAND}" =~ ^(0|false|FALSE)$ ]] && NX_COMMAND='nx'
alias "${NX_COMMAND:-n}${word:0:1}"="nx ${word#[a-z]/}"; [[ -n "${NX_VERBOSE}" ]] && alias "${NX_COMMAND:-n}${word:0:1}"
if [[ "${word}" =~ ^(un)?install$ ]]; then
alias "${NX_COMMAND:-n}${word:0:1}s"="nx ${word#[a-z]/} --save"; [[ -n "${NX_VERBOSE}" ]] && alias "${NX_COMMAND:-n}${word:0:1}s"
alias "${NX_COMMAND:-n}${word:0:1}d"="nx ${word#[a-z]/} --save-dev"; [[ -n "${NX_VERBOSE}" ]] && alias "${NX_COMMAND:-n}${word:0:1}d"
alias "${NX_COMMAND:-n}${word:0:1}g"="nx ${word#[a-z]/} --global"; [[ -n "${NX_VERBOSE}" ]] && alias "${NX_COMMAND:-n}${word:0:1}g"
fi
done
fi
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
{
"name": "enex",
"version": "0.0.8",
"name": "nx.sh",
"version": "1.0.0",
"description": "A minimalist command runner for npm packages, with a focus on developer ergonomics.",
"main": "enex",
"main": "nx.sh",
"files": [
"enex.sh"
"nx.sh"
],
"bin": {
"enex": "enex"
"nx": "nx"
},
"scripts": {
"lint": "shellcheck enex.sh"
"lint": "shellcheck nx.sh"
},
"repository": {
"type": "git",
"url": "https://github.com/evnp/enex.git"
"url": "https://github.com/evnp/nx.git"
},
"homepage": "https://github.com/evnp/enex",
"homepage": "https://nx.evnp.sh",
"author": "Evan Purcer <[email protected]> (http://evnp.ca)",
"license": "MIT",
"devDependencies": {
Expand Down

0 comments on commit e619847

Please sign in to comment.