Skip to content
/ p-s Public
forked from sezna/nps

All the benefits of npm scripts without the cost of a bloated package.json and limits of json

License

Notifications You must be signed in to change notification settings

jisaacks/p-s

Β 
Β 

Repository files navigation

package-scripts (aka p-s)

All the benefits of npm scripts without the cost of a bloated package.json and limits of json

Build Status Code Coverage version downloads MIT License All Contributors

PRs Welcome Donate Code of Conduct Roadmap Examples

The problem

Even though npm scripts have a ton of advantages (learn more), it can grow into an unmaintainable mess in your package.json file. Part of the problem is we're configuring scripts in json which has fundamental issues (like no comments).

This solution

Put all of your scripts in a file called package-scripts.js and use p-s in a single package.json script:

package.json

{
  "scripts": {
    "start": "package-scripts"
  }
}

package-scripts.js

module.exports = {
  scripts: {
    lint: 'eslint .',
    test: {
      default: 'ava',
      watch: {
        script: 'ava -w',
        description: 'run in the amazingly intelligent AVA watch mode'
      }
    },
    build: {
      default: 'webpack',
      prod: 'webpack -p',
    }
  }
}

Then you can run:

npm start lint
npm start test.watch

But the fun doesn't end there! You can use a prefix:

npm start b # will run the build script

And these prefixes can go as deep as you like!

npm start b.p # will run the production build script

And if you want to speed things up even more, you can install npm-quick-run and then:

nr s build.prod

Cool stuff right? And there's more on the roadmap.

Also check out the examples. You'll find some good stuff in there (including how to deal with windows and other cross-platform issues).

Note: You don't have to use the start script of course. If you're writing a node application, you're likely using this for starting your server. You could easily create a p-s script and do: npm run p-s b.

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's devDependencies:

npm install --save-dev p-s

API

CLI

The CLI is fairly simple. It allows for a few options. The p-s binary is available in your node_modules/.bin directory when you install it locally in a project so you can use it in your npm scripts. We also expose a package-scripts alias binary so you can use that as well if you'd like the script to be more clear.

$ p-s --help

  Usage: p-s [options]

  Options:

    -h, --help                                  output usage information
    -V, --version                               output the version number
    -s, --silent                                Silent p-s output
    -p, --parallel <script-name1,script-name2>  Scripts to run in parallel (comma seprated)
    -c, --config <filepath>                     Config file to use (defaults to nearest package-scripts.js)
    -l, --log-level <level>                     The log level to use (error, warn, info [default])
    -r, --require <module>                      Module to preload

Available scripts (camel or kebab case accepted)

lint - Lint all files with eslint. Configuration is in package.json - eslint .
test - Run tests with AVA. See package.json for config - ava
test.watch - Run in the amazingly intelligent AVA watch mode - ava -w
build - The normal webpack UMD build for development - webpack
build.prod - The production webpack build - webpack -p

help

Will print out the help you see above (the available scripts are colored 🌈 and come from the config specified/default config).

silent

By default, p-s will log out to the console before running the command. You can add -s to your command to silence this.

parallel

Run the given scripts in parallel. This enables handy workflows like this:

npm start -p lint,build,cover && npm start check-coverage && npm start report-coverage

config

Use a different config

npm start -c ./other/package-scripts.js lint

Normally, p-s will look for a package-scripts.js file and load that to get the scripts. Generally you'll want to have this at the root of your project (next to the package.json). But by specifying -c or --config, p-s will use that file instead.

log-level

Specify the log level to use

require

You can specify a module which will be loaded before the config file is loaded. This allows you to preload for example babel-register so you can use all babel presets you like.

args

You can pass additional arguments to the script(s) that are being spawned:

npm start lint --fix # --fix will be passed on to the lint script

scripts

If you don't use -p (because you don't need parallelism) then you can simply provide the name of the script like so:

npm start cover

That's all for the CLI.

package-scripts.js

p-s expects to your package-scripts.js file to module.exports an object with the following properties:

scripts

This can be an object or a function that returns an object. See the annotated example below for what this object can look like (and different ways to run them):

module.exports = {
  scripts: {
    // you can assign a script property to a string
    simple: 'echo "this is easy"', // npm start simple
    test: {
      default: {
        script: 'echo "test things!"', // npm start test
        description: 'just pass it on to npm... Do not take this config very seriously :-)',
      },
      otherStuff: {
        // this one can be executed two different ways:
        // 1. npm start test.otherStuff
        // 2. npm start test.other-stuff
        script: 'echo "testing other things"',
        description: 'this is a handy description',
      },
    },
    // this one can be executed a few different ways:
    // 1. npm start k
    // 2. npm start kebab-case
    // 3. npm start kebabCase
    'kebab-case': 'echo "kebab-case"'
  },
}

Remember, I find it considerably nicer to just use npm-quick-run and then I can do:

nr s k # runs npm start kebab-case

options

This object is used to configure p-s with the following options:

silent

Setting this to true will prevent p-s from outputting anything for your script (normally you'll get simple output indicating the command that's being executed). This effectively sets the logLevel to disable.

logLevel

This sets the logLevel of p-s.

ENV variables

LOG_LEVEL

By setting LOG_LEVEL environment variable you can control the log level for p-s

Log level

Log levels available:

  • error - errors only
  • warn - errors and warnings only
  • info - info, errors, and warnings (default)

FAQ

Why npm start?

Just to be clear: You do not have to use the start script. You can use whatever you like. But I recommend using the start. npm scripts are generally run with npm run <script-name>. There are some exceptions to this. For example:

  1. npm run test === npm test === npm t
  2. npm run start === npm start

So, while you could use a script called script and run npm run script build, I just think it reads more clearly to just use the start script and run npm start build. It's also nice that it's fewer things to type. You could also use the test script and then type even less: npm t build, but thats just... odd.

Inspiration

This was inspired by a tweet by @sindresorhus.

Other Solutions

  • scripty has a solution for this problem as well. The reason I didn't go with that though is you still need a line for every script (one of the pains I'm trying to solve) and a each script requires its own file (one of the benefits of npm scripts I wanted to keep).

In the wild

  • react-component-template uses p-s to implement shareable npm scripts. See then how dependent react-swap can reuse them.

    GOTCHAS:

    • use process.cwd() as the base for all paths
    • you cannot recursively call p-s and need to use npm start <whatever>
  • Hypercubed/EventsSpeedTests uses p-s to automate benchmark running and reporting in node and the browser. package-scripts.js enables us to keep our scripts DRY. Combined with grunion allows benchmarks to be run, serially or concurrently, on glob patterns.

Contributors

Thanks goes to these people (emoji key):


Kent C. Dodds

πŸ’» πŸ“– πŸš‡ πŸ’‘

David Wells

πŸ’»

Abhishek Shende

πŸ’» ⚠️

Rowan Oulton

πŸ’» πŸ“– ⚠️

Gilad Goldberg

πŸ’»

Tim McGee

πŸ’» πŸ“–

Nik Butenko

πŸ’‘

Tommy

πŸ› πŸ’» ⚠️

Jayson Harshbarger

πŸ’‘

JD Isaacks

πŸ’» ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

LICENSE

MIT

About

All the benefits of npm scripts without the cost of a bloated package.json and limits of json

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%