builder
Advanced tools
Comparing version 2.4.0 to 2.5.0
History | ||
======= | ||
## 2.5.0 | ||
* Add `builder -v|--version`. | ||
* Add `builder -h|--help` shortcuts. | ||
* Make `builder` (with no args) display help. | ||
[#61](https://github.com/FormidableLabs/builder/issues/61) | ||
## 2.4.0 | ||
@@ -5,0 +12,0 @@ |
@@ -10,2 +10,3 @@ "use strict"; | ||
var chalk = require("chalk"); | ||
var pkg = require("../package.json"); | ||
@@ -38,2 +39,12 @@ // Generic flags: | ||
}; | ||
var FLAG_HELP = { | ||
desc: "Display help and exit", | ||
types: [Boolean], | ||
default: false | ||
}; | ||
var FLAG_VERSION = { | ||
desc: "Display version and exit", | ||
types: [Boolean], | ||
default: false | ||
}; | ||
@@ -48,3 +59,5 @@ // Option flags. | ||
default: ".builderrc" | ||
} | ||
}, | ||
help: FLAG_HELP, | ||
version: FLAG_VERSION | ||
}, | ||
@@ -100,2 +113,11 @@ | ||
/** | ||
* Retrieve version. | ||
* | ||
* @returns {String} Version string | ||
*/ | ||
var version = function () { | ||
return pkg.version; | ||
}; | ||
// Option parser. | ||
@@ -145,3 +167,4 @@ var createFn = function (flags) { | ||
FLAGS: FLAGS, | ||
help: help | ||
help: help, | ||
version: version | ||
}, _.mapValues(FLAGS, function (flags) { | ||
@@ -148,0 +171,0 @@ // Add in `KEY()` methods. |
@@ -41,3 +41,12 @@ "use strict"; | ||
} | ||
if (!_.contains(this.ACTIONS, this._action)) { | ||
// Special flags that short circuit. | ||
if (parsed.help === true || remain.length === 0) { | ||
this._action = "help"; | ||
} else if (parsed.version === true) { | ||
this._action = "version"; | ||
} | ||
// Infer action. | ||
if (!_.contains(this.ACTIONS.concat(["version"]), this._action)) { | ||
throw new Error("Invalid action: " + this._action + | ||
@@ -48,3 +57,3 @@ " - Valid actions: " + this.ACTIONS.join(", ")); | ||
Task.prototype.ACTIONS = ["help", "run", "concurrent", "envs"]; | ||
Task.prototype.ACTIONS = ["run", "concurrent", "envs", "help"]; | ||
@@ -55,5 +64,7 @@ Task.prototype.toString = function () { | ||
cmd = this._commands.join(", "); | ||
} else if (_.contains(["help", "version"], this._action)) { | ||
cmd = null; | ||
} | ||
return this._action + " " + cmd; | ||
return this._action + (cmd ? " " + cmd : ""); | ||
}; | ||
@@ -132,2 +143,4 @@ | ||
* $ builder help <archetype1> <archetype2> | ||
* $ builder --help | ||
* $ builder -h | ||
* ``` | ||
@@ -167,2 +180,18 @@ * | ||
/** | ||
* Version. | ||
* | ||
* ```sh | ||
* $ builder --version | ||
* $ builder -v | ||
* ``` | ||
* | ||
* @param {Function} callback Callback function `(err)` | ||
* @returns {void} | ||
*/ | ||
Task.prototype.version = function (callback) { | ||
process.stdout.write(args.version() + "\n"); | ||
callback(); | ||
}; | ||
/** | ||
* Run. | ||
@@ -169,0 +198,0 @@ * |
{ | ||
"name": "builder", | ||
"version": "2.4.0", | ||
"version": "2.5.0", | ||
"description": "An NPM-based task runner", | ||
@@ -5,0 +5,0 @@ "repository": { |
268
README.md
@@ -111,14 +111,64 @@ [![Travis Status][trav_img]][trav_site] | ||
However, to call `builder` from the command line you will either need to | ||
augment your `PATH` variable with a shell configuration (Mac/Linux) like: | ||
However, to call `builder` from the command line you will either need to either | ||
augment `PATH` or call the long form of the command: | ||
##### PATH Augmentation | ||
Our recommended approach is to augment your `PATH` variable with a shell | ||
configuration as follows: | ||
**Mac / Linux** | ||
```sh | ||
# Safer version, but if you _have_ global installs, those come first. | ||
export PATH="${PATH}:./node_modules/.bin" | ||
# (OR) Less safe, but guarantees local node modules come first. | ||
export PATH="./node_modules/.bin:${PATH}" | ||
# ... OR ... | ||
export PATH="${PATH}:./node_modules/.bin" | ||
# Check results with: | ||
echo $PATH | ||
``` | ||
or call the longer `./node_modules/.bin/builder` instead of `builder` from the | ||
command line. | ||
To make these changes **permanent**, add the `export` command to your `.bashrc` | ||
or analogous shell configuration file. | ||
**Windows** | ||
```sh | ||
# Safer version, but if you _have_ global installs, those come first. | ||
set PATH=%PATH%;node_modules\.bin | ||
# (OR) Less safe, but guarantees local node modules come first. | ||
set PATH=node_modules\.bin;%PATH% | ||
# Check results with: | ||
echo %PATH% | ||
``` | ||
To make these changes **permanent**, please see this multi-OS article on | ||
changing the `PATH` variable: https://www.java.com/en/download/help/path.xml | ||
(the article is targeted for a Java executable, but it's analogous to our | ||
situation). You'll want to paste in `;node_modules\.bin` at the end _or_ | ||
`node_modules\.bin;` at the beginning of the PATH field in the gui. If there | ||
is no existing `PATH` then add a user entry with `node_modules\.bin` as a value. | ||
(It is unlikely to be empty because an `npm` installation on Windows sets the | ||
user `PATH` analogously.) | ||
##### Full Path Invocation | ||
Or you can run the complete path to the builder script with: | ||
**Mac / Linux** | ||
```sh | ||
node_modules/.bin/builder <action> <task> | ||
``` | ||
**Windows** | ||
```sh | ||
node_modules\.bin\builder <action> <task> | ||
``` | ||
#### Configuration | ||
@@ -143,8 +193,16 @@ | ||
```sh | ||
$ builder help | ||
$ builder [-h|--help|help] | ||
$ builder help <action> | ||
$ builder help <archetype> | ||
``` | ||
Run `builder help <action>` for all available options. For a quick overview: | ||
Run `builder help <action>` for all available options. Version information is | ||
available with: | ||
```sh | ||
$ builder [-v|--version] | ||
``` | ||
Let's dive a little deeper into the main builder actions: | ||
##### builder run | ||
@@ -382,2 +440,196 @@ | ||
### Creating an Archetype | ||
Moving common tasks into an archetype is fairly straightforward and requires | ||
just a few tweaks to the paths defined in configuration and scripts in order | ||
to work correctly. | ||
#### Initializing your project | ||
An archetype is simply a standard npm module with a valid `package.json`. To set | ||
up a new archetype from scratch, make a directory for your new archetype, | ||
initialize NPM and link it for ease of development. | ||
```sh | ||
$ cd path/to/new/archetype | ||
$ npm init | ||
$ npm link | ||
``` | ||
From your consuming project, you can now link to the archetype directly for ease | ||
of development after including it in your `dependencies` and creating a | ||
`.builderrc` as outlined above in [configuration](#configuration). | ||
```sh | ||
$ cd path/to/consuming/project | ||
$ npm link new-archetype-name | ||
``` | ||
#### Managing the `dev` archetype | ||
Because `builder` archetypes are included as simple npm modules, two separate | ||
npm modules are required for archetypes: one for normal dependencies and one for | ||
dev dependencies. Whereas in a non-builder-archetype project you'd specify dev | ||
dependencies in `devDependencies`, with `builder` all dev dependencies must be | ||
regular `dependencies` on a separate dev npm module. | ||
`builder` is designed so that when defining which archetypes to use in a | ||
consuming project's `.builderrc`, `builder` will look for two modules, one named | ||
appropriately in `dependencies` (ex: `my-archetype`) and one in | ||
`devDependencies` but with `-dev` appended to the name (ex: `my-archetype-dev`). | ||
To help with managing these while building a builder archetype, install | ||
[`builder-support`](https://github.com/FormidableLabs/builder-support) | ||
to create and manage a `dev/` directory within your archetype project with it's | ||
own `package.json` which can be published as a separate npm module. | ||
`builder-support` will not only create a `dev/package.json` with an appropriate | ||
package name, but will also keep all the other information from your archetype's | ||
primary `package.json` up to date as well as keep `README.md` and `.gitignore` | ||
in parity for hosting the project as a separate npm module. | ||
Get started by installing and running `builder-support gen-dev`: | ||
```sh | ||
$ npm install builder-support --save-dev | ||
$ ./node_modules/.bin/builder-support gen-dev | ||
``` | ||
_TIP: Create a task called `"builder:gen-dev": "builder-support gen-dev"` in | ||
your archetype to avoid having to type out the full path each time you update | ||
your project's details._ | ||
For ease of development, `npm link` the dev dependency separately: | ||
```sh | ||
$ cd dev | ||
$ npm link | ||
``` | ||
Then from your consuming project, you can link to the dev package. | ||
```sh | ||
$ cd path/to/consuming/project | ||
$ npm link new-archetype-name-dev | ||
``` | ||
Read the [`builder-support` docs](https://github.com/FormidableLabs/builder-support) | ||
to learn more about how dev archetypes are easily managed with | ||
`builder-support gen-dev`. | ||
#### Workflow for moving dependencies and scripts to your new archetype | ||
Once everything is configured and `npm link`'d, it should be easy to move | ||
scripts to your archetype and quickly test them out from a consuming project. | ||
##### Moving `dependencies` and `devDependencies` from an existing `package.json` | ||
* copy `dependencies` to `package.json` `dependencies`. | ||
* copy `devDependencies` to `dev/package.json` `dependencies`. | ||
##### Moving scripts and config files | ||
All scripts defined in archetypes will be run from the root of the project | ||
consuming the archetype. This means you have to change all paths in your scripts | ||
to reference their new location within the archetype. | ||
An example script and config you may be moving to an archetype would look like: | ||
```js | ||
"test-server-unit": "mocha --opts test/server/mocha.opts test/server/spec" | ||
``` | ||
When moving this script to an archetype, we'd also move the config from | ||
`test/server/mocha.opts` within the original project to within the | ||
archetype such as `config/mocha/server/mocha.opts`. | ||
For this example script, we'd need to update the path to `mocha.opts` as so: | ||
```js | ||
"test-server-unit": "mocha --opts node_modules/new-archetype-name/config/mocha/server/mocha.opts test/server/spec" | ||
``` | ||
Any paths that reference files expected in the consuming app (in this example | ||
`test/server/spec`) do not need to change. | ||
##### Updating path and module references within your script configs | ||
Any JavaScript files run from within an archetype (such as config files) require | ||
a few changes related to paths now that the files are being run from within | ||
an npm module. This includes all `require()` calls referencing npm modules and | ||
all paths to files that aren't relative. | ||
For example, `karma.conf.js`: | ||
```js | ||
module.exports = function (config) { | ||
require("./karma.conf.dev")(config); | ||
config.set({ | ||
preprocessors: { | ||
"test/client/main.js": ["webpack"] | ||
}, | ||
files: [ | ||
"sinon/pkg/sinon", | ||
"test/client/main.js" | ||
], | ||
}); | ||
}; | ||
``` | ||
All non-relative paths to files and npm modules need to be full paths, even ones | ||
not in the archetype directory. For files expected to be in the consuming | ||
project, this can be achieved by prepending `process.cwd()` to all paths. For | ||
npm modules, full paths can be achieved by using | ||
[`require.resolve()`](https://nodejs.org/api/globals.html#globals_require_resolve). | ||
An updated config might look like: | ||
```js | ||
var path = require("path"); | ||
var ROOT = process.cwd(); | ||
var MAIN_PATH = path.join(ROOT, "test/client/main.js"); | ||
module.exports = function (config) { | ||
require("./karma.conf.dev")(config); | ||
config.set({ | ||
preprocessors: { | ||
[MAIN_PATH]: ["webpack"] | ||
}, | ||
files: [ | ||
require.resolve("sinon/pkg/sinon"), | ||
MAIN_PATH | ||
], | ||
}); | ||
}; | ||
``` | ||
#### Example `builder` archetype project structure | ||
``` | ||
. | ||
├── CONTRIBUTING.md | ||
├── HISTORY.md | ||
├── LICENSE.txt | ||
├── README.md | ||
├── config | ||
│ ├── eslint | ||
│ ├── karma | ||
│ ├── mocha | ||
│ │ ├── func | ||
│ │ │ ├── mocha.dev.opts | ||
│ │ │ └── mocha.opts | ||
│ │ └── server | ||
│ │ └── mocha.opts | ||
│ └── webpack | ||
│ ├── webpack.config.coverage.js | ||
│ ├── webpack.config.dev.js | ||
│ ├── webpack.config.hot.js | ||
│ ├── webpack.config.js | ||
│ └── webpack.config.test.js | ||
├── dev | ||
│ └── package.json | ||
└── package.json | ||
``` | ||
## Tips, Tricks, & Notes | ||
@@ -384,0 +636,0 @@ |
64717
1088
756