{
  "_args": [
    [
      "liftoff@https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
      "/Users/nw/flint/packages/flint"
    ]
  ],
  "_from": "liftoff@>=2.1.0 <3.0.0",
  "_id": "liftoff@2.2.0",
  "_inCache": true,
  "_location": "/liftoff",
  "_phantomChildren": {},
  "_requested": {
    "name": "liftoff",
    "raw": "liftoff@https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
    "rawSpec": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
    "scope": null,
    "spec": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
    "type": "remote"
  },
  "_requiredBy": [
    "/gulp"
  ],
  "_resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
  "_shasum": "f5fcfa4583113159d12935a8a0616f50128b5753",
  "_shrinkwrap": null,
  "_spec": "liftoff@https://registry.npmjs.org/liftoff/-/liftoff-2.2.0.tgz",
  "_where": "/Users/nw/flint/packages/flint",
  "author": {
    "name": "Tyler Kellen",
    "url": "http://goingslowly.com/"
  },
  "bugs": {
    "url": "https://github.com/tkellen/node-liftoff/issues"
  },
  "dependencies": {
    "extend": "^2.0.1",
    "findup-sync": "^0.3.0",
    "flagged-respawn": "^0.3.1",
    "rechoir": "^0.6.0",
    "resolve": "^1.1.6"
  },
  "description": "Launch your command line tool with ease.",
  "devDependencies": {
    "chai": "^2.3.0",
    "coffee-script": "^1.9.2",
    "istanbul": "^0.3.14",
    "jscs": "^1.13.1",
    "jshint": "^2.7.0",
    "mocha": "^2.1.0",
    "sinon": "~1.12.2"
  },
  "engines": {
    "node": ">= 0.8"
  },
  "homepage": "https://github.com/tkellen/node-liftoff",
  "keywords": [
    "command line"
  ],
  "license": "MIT",
  "main": "index.js",
  "name": "liftoff",
  "optionalDependencies": {},
  "readme": "<p align=\"center\">\n  <a href=\"http://liftoffjs.com\">\n    <img height=\"100\" width=\"297\" src=\"https://cdn.rawgit.com/tkellen/js-liftoff/master/artwork/liftoff.svg\"/>\n  </a>\n</p>\n\n# liftoff [![Build Status](https://secure.travis-ci.org/tkellen/js-liftoff.svg)](http://travis-ci.org/tkellen/js-liftoff) [![Build status](https://ci.appveyor.com/api/projects/status/5a6w8xuq8ed1ilc4/branch/master?svg=true)](https://ci.appveyor.com/project/tkellen/js-liftoff/branch/master)\n\n> Launch your command line tool with ease.\n\n[![NPM](https://nodei.co/npm/liftoff.png)](https://nodei.co/npm/liftoff/)\n\n## What is it?\n[See this blog post](http://weblog.bocoup.com/building-command-line-tools-in-node-with-liftoff/), [check out this proof of concept](http://github.com/tkellen/node-hacker), or read on.\n\nSay you're writing a CLI tool.  Let's call it [hacker](http://github.com/tkellen/node-hacker).  You want to configure it using a `Hackerfile`.  This is node, so you install `hacker` locally for each project you use it in.  But, in order to get the `hacker` command in your PATH, you also install it globally.\n\nNow, when you run `hacker`, you want to configure what it does using the `Hackerfile` in your current directory, and you want it to execute using the local installation of your tool.  Also, it'd be nice if the `hacker` command was smart enough to traverse up your folders until it finds a `Hackerfile`&mdash;for those times when you're not in the root directory of your project.  Heck, you might even want to launch `hacker` from a folder outside of your project by manually specifying a working directory.  Liftoff manages this for you.\n\nSo, everything is working great.  Now you can find your local `hacker` and `Hackerfile` with ease.  Unfortunately, it turns out you've authored your `Hackerfile` in coffee-script, or some other JS variant.  In order to support *that*, you have to load the compiler for it, and then register the extension for it with node.  Good news, Liftoff can do that, and a whole lot more, too.\n\n## API\n\n### constructor(opts)\n\nCreate an instance of Liftoff to invoke your application.\n\nAn example utilizing all options:\n```js\nconst Hacker = new Liftoff({\n  name: 'hacker',\n  processTitle: 'hacker',\n  moduleName: 'hacker',\n  configName: 'hackerfile',\n  extensions: {\n    '.js': null,\n    '.json': null,\n    '.coffee': 'coffee-script/register'\n  },\n  v8flags: ['--harmony'] // or v8flags: require('v8flags');\n});\n```\n\n#### opts.name\n\nSugar for setting `processTitle`, `moduleName`, `configName` automatically.\n\nType: `String`  \nDefault: `null`\n\nThese are equivalent:\n```js\nconst Hacker = Liftoff({\n  processTitle: 'hacker',\n  moduleName: 'hacker',\n  configName: 'hackerfile'\n});\n```\n```js\nconst Hacker = Liftoff({name:'hacker'});\n```\n\n#### opts.moduleName\n\nSets which module your application expects to find locally when being run.\n\nType: `String`  \nDefault: `null`\n\n#### opts.configName\n\nSets the name of the configuration file Liftoff will attempt to find.  Case-insensitive.\n\nType: `String`  \nDefault: `null`\n\n#### opts.extensions\n\nSet extensions to include when searching for a configuration file.  If an external module is needed to load a given extension (e.g. `.coffee`), the module name should be specified as the value for the key.\n\nType: `Object`  \nDefault: `{\".js\":null,\".json\":null}`\n\n**Examples:**\n\nIn this example Liftoff will look for `myappfile{.js,.json,.coffee}`.  If a config with the extension `.coffee` is found, Liftoff will try to require `coffee-script/require` from the current working directory.\n```js\nconst MyApp = new Liftoff({\n  name: 'myapp'\n  extensions: {\n    '.js': null,\n    '.json': null,\n    '.coffee': 'coffee-script/register'\n  }\n});\n```\n\nIn this example, Liftoff will look for `.myapp{rc}`.\n```js\nconst MyApp = new Liftoff({\n  name: 'myapp',\n  configName: '.myapp',\n  extensions: {\n    'rc': null\n  }\n});\n```\n\nIn this example, Liftoff will automatically attempt to load the correct module for any javascript variant supported by [node-interpret](https://github.com/tkellen/node-interpret) (as long as it does not require a register method).\n\n```js\nconst MyApp = new Liftoff({\n  name: 'myapp',\n  extensions: require('interpret').jsVariants\n});\n```\n#### opts.v8flags\n\nAny flag specified here will be applied to node, not your program.  Useful for supporting invocations like `myapp --harmony command`, where `--harmony` should be passed to node, not your program. This functionality is implemented using [flagged-respawn](http://github.com/tkellen/node-flagged-respawn). To support all v8flags, see [node-v8flags](https://github.com/tkellen/node-v8flags).\n\nType: `Array|Function`  \nDefault: `null`\n\nIf this method is a function, it should take a node-style callback that yields an array of flags.\n\n#### opts.processTitle\n\nSets what the [process title](http://nodejs.org/api/process.html#process_process_title) will be.\n\nType: `String`  \nDefault: `null`\n\n#### opts.completions(type)\n\nA method to handle bash/zsh/whatever completions.\n\nType: `Function`  \nDefault: `null`\n\n## launch(opts, callback(env))\nLaunches your application with provided options, builds an environment, and invokes your callback, passing the calculated environment as the first argument.\n\n##### Example Configuration w/ Options Parsing:\n```js\nconst Liftoff = require('liftoff');\nconst MyApp = new Liftoff({name:'myapp'});\nconst argv = require('minimist')(process.argv.slice(2));\nconst invoke = function (env) {\n  console.log('my environment is:', env);\n  console.log('my cli options are:', argv);\n  console.log('my liftoff config is:', this);\n};\nMyApp.launch({\n  cwd: argv.cwd,\n  configPath: argv.myappfile,\n  require: argv.require,\n  completion: argv.completion\n}, invoke);\n```\n\n#### opts.cwd\n\nChange the current working directory for this launch. Relative paths are calculated against `process.cwd()`.\n\nType: `String`  \nDefault: `process.cwd()`\n\n**Example Configuration:**\n```js\nconst argv = require('minimist')(process.argv.slice(2));\nMyApp.launch({\n  cwd: argv.cwd\n}, invoke);\n```\n\n**Matching CLI Invocation:**\n```\nmyapp --cwd ../\n```\n\n#### opts.configPath\n\nDon't search for a config, use the one provided. **Note:** Liftoff will assume the current working directory is the directory containing the config file unless an alternate location is explicitly specified using `cwd`.\n\nType: `String`  \nDefault: `null`\n\n**Example Configuration:**\n```js\nvar argv = require('minimist')(process.argv.slice(2));\nMyApp.launch({\n  configPath: argv.myappfile\n}, invoke);\n```\n\n**Matching CLI Invocation:**\n```\nmyapp --myappfile /var/www/project/Myappfile.js\n```\n\n**Examples using `cwd` and `configPath` together:**\n\nThese are functionally identical:\n```\nmyapp --myappfile /var/www/project/Myappfile.js\nmyapp --cwd /var/www/project\n```\n\nThese can run myapp from a shared directory as though it were located in another project:\n```\nmyapp --myappfile /Users/name/Myappfile.js --cwd /var/www/project1\nmyapp --myappfile /Users/name/Myappfile.js --cwd /var/www/project2\n```\n\n#### opts.require\n\nA string or array of modules to attempt requiring from the local working directory before invoking the launch callback.\n\nType: `String|Array`  \nDefault: `null`\n\n**Example Configuration:**\n```js\nvar argv = require('minimist')(process.argv.slice(2));\nMyApp.launch({\n  require: argv.require\n}, invoke);\n```\n\n**Matching CLI Invocation:**\n```js\nmyapp --require coffee-script/register\n```\n\n#### callback(env)\n\nA function to start your application.  When invoked, `this` will be your instance of Liftoff. The `env` param will contain the following keys:\n\n- `cwd`: the current working directory\n- `require`: an array of modules that liftoff tried to pre-load\n- `configNameSearch`: the config files searched for\n- `configPath`: the full path to your configuration file (if found)\n- `configBase`: the base directory of your configuration file (if found)\n- `modulePath`: the full path to the local module your project relies on (if found)\n- `modulePackage`: the contents of the local module's package.json (if found)\n\n### events\n\n#### require(name, module)\n\nEmitted when a module is pre-loaded.\n\n```js\nvar Hacker = new Liftoff({name:'hacker'});\nHacker.on('require', function (name, module) {\n  console.log('Requiring external module: '+name+'...');\n  // automatically register coffee-script extensions\n  if (name === 'coffee-script') {\n    module.register();\n  }\n});\n```\n\n#### requireFail(name, err)\n\nEmitted when a requested module cannot be preloaded.\n\n```js\nvar Hacker = new Liftoff({name:'hacker'});\nHacker.on('requireFail', function (name, err) {\n  console.log('Unable to load:', name, err);\n});\n```\n\n#### respawn(flags, child)\n\nEmitted when Liftoff re-spawns your process (when a [`nodeFlag`](#optsnodeflags) is detected).\n\n```js\nvar Hacker = new Liftoff({\n  name: 'hacker',\n  nodeFlags: ['--harmony']\n});\nHacker.on('respawn', function (flags, child) {\n  console.log('Detected node flags:', flags);\n  console.log('Respawned to PID:', child.pid);\n});\n```\n\nEvent will be triggered for this command:\n`hacker --harmony commmand`\n\n## Examples\n\nCheck out how [gulp](https://github.com/gulpjs/gulp/blob/master/bin/gulp.js) uses Liftoff.\n\nFor a bare-bones example, try [the hacker project](https://github.com/tkellen/node-hacker/blob/master/bin/hacker.js).\n\nTo try the example, do the following:\n\n1. Install the sample project `hacker` with `npm install -g hacker`.\n2. Make a `Hackerfile.js` with some arbitrary javascript it.\n3. Install hacker next to it with `npm install hacker`.\n3. Run `hacker` while in the same parent folder.\n",
  "readmeFilename": "README.md",
  "repository": {
    "type": "git",
    "url": "git://github.com/tkellen/node-liftoff.git"
  },
  "scripts": {
    "test": "jshint lib index.js && jscs lib index.js && mocha -t 5000 -b -R spec test/index"
  },
  "version": "2.2.0"
}
