Compare commits
168 Commits
v2.0.0-rc.16
...
v0.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 5dc698be9d | |||
| 1bf334399b | |||
| a30db5fc5d | |||
| 77cfcf0da4 | |||
| d8541a82ac | |||
| 489bd0f0fe | |||
| a3f30bf783 | |||
| 61ff0b1052 | |||
| e02d39a6bf | |||
| ca414f03db | |||
| 4200724316 | |||
| 686f67fac2 | |||
| 494618cca1 | |||
| 86fe200bfd | |||
| c272f52994 | |||
| 93ed48a537 | |||
| 740e3f441d | |||
| 8204feadaa | |||
| cdf53e133b | |||
| 65c07d4e4a | |||
| 4c3443655e | |||
| 6d20d4da22 | |||
| b72b14b6c3 | |||
| 9134bcf351 | |||
| 1c0d8d0fc0 | |||
| a7c3fda721 | |||
| 7d75480a6f | |||
| 67361b27e1 | |||
| 3b6f9ff4b7 | |||
| 6fcfb10e38 | |||
| 06cab4f43b | |||
| 2cacd8340b | |||
| 0e90ac9f16 | |||
| efd3f78c9d | |||
| 54967d1ab0 | |||
| bb489a3cb7 | |||
| 6097c20204 | |||
| 39665a8d5c | |||
| f49ece0c86 | |||
| 5aca22d28e | |||
| e79b0fb23e | |||
| cac698609c | |||
| b040337a94 | |||
| 06d7730802 | |||
| ad4da1d193 | |||
| 5927b45e70 | |||
| e4155c8fed | |||
| e91f5b52af | |||
| 3b1d5a9fe1 | |||
| 3ac298fe4f | |||
| 229f0516c6 | |||
| 29d5f6aaeb | |||
| 174599df30 | |||
| 3ca6bbbda2 | |||
| 97dbd37068 | |||
| b615e125c0 | |||
| c34f6719b5 | |||
| 2342fe6fdd | |||
| 333cc697c3 | |||
| ece4b2d62a | |||
| ba62973dca | |||
| 9b5892e6ad | |||
| f7ad9a8e83 | |||
| 7c1331bed8 | |||
| e55dacf8c8 | |||
| ec79ff85d4 | |||
| 99a8cbe9b3 | |||
| f458298ffb | |||
| c3fa94a2e5 | |||
| 961f72b1d9 | |||
| d91d91fc2b | |||
| 273bfa3e4d | |||
| 31b01469c7 | |||
| b94d0c3719 | |||
| 275a7b025b | |||
| 71d7b97736 | |||
| faf0a85b36 | |||
| 56578c09b1 | |||
| 6ad1ec436c | |||
| 62461dbc41 | |||
| 7f34aa8854 | |||
| 76072f6df9 | |||
| 83daa5553b | |||
| ff09ef6755 | |||
| 85c8831248 | |||
| 3d2ae606ef | |||
| d4f27aea7f | |||
| 87abd1a295 | |||
| 9fd462da2f | |||
| 60849404a2 | |||
| 00fa37fff0 | |||
| 270350fda6 | |||
| dd2aa5a831 | |||
| afc7140b6b | |||
| 1d47091304 | |||
| 36bbdd4aa9 | |||
| e73804a4dd | |||
| bd1152357e | |||
| c53f229848 | |||
| 3cb81249d8 | |||
| 518fbc7280 | |||
| dd5607886a | |||
| 666774b5b5 | |||
| 3f75ae462e | |||
| dacb31fd67 | |||
| d4e62c668e | |||
| b267d9ba41 | |||
| 75932723ac | |||
| 28442e6714 | |||
| 9bb3b76a65 | |||
| 6702ce326a | |||
| 27075a778d | |||
| 368195be77 | |||
| b11ce7540c | |||
| 069c910b7b | |||
| 934c7bb3d5 | |||
| 8c8a1eddd7 | |||
| 3eea6784dd | |||
| cef44e9b77 | |||
| b6f555c223 | |||
| 87cacafd3e | |||
| 9caa365a3e | |||
| e7e80f5a2c | |||
| 4284c399dd | |||
| 89eeeda575 | |||
| 3b1b82dc40 | |||
| a9a97fefe1 | |||
| 12a7069a32 | |||
| 533ed8c500 | |||
| 875d6d0ff7 | |||
| ea2cfdf5ee | |||
| 60ebde86cc | |||
| d927887355 | |||
| 04280a3016 | |||
| 3c084b9573 | |||
| 708851cc40 | |||
| 2214dccd4a | |||
| ca9fced819 | |||
| 684b285217 | |||
| 1dc6243b75 | |||
| f1a8a7269f | |||
| 4e8830365e | |||
| 34e6f79096 | |||
| e58e22a329 | |||
| 4866e04c13 | |||
| bedcdfe26f | |||
| 5fe8618236 | |||
| 127377a92b | |||
| d6a083778a | |||
| a52eae6665 | |||
| 75ecf22ba9 | |||
| 7f444e93de | |||
| 818da103a8 | |||
| b565aaafc0 | |||
| 67282e2506 | |||
| 3c432a0d3a | |||
| a831244c3d | |||
| ad5532eaad | |||
| 8b03984ca8 | |||
| 953d57240f | |||
| dfb751ca12 | |||
| 0813ef0f67 | |||
| 1e12cad040 | |||
| 015b60ee24 | |||
| 66d3454129 | |||
| b385069ebb | |||
| 51879ed636 | |||
| c018684658 |
@@ -1,2 +1,4 @@
|
||||
[commands]
|
||||
proj = subl --project project.sublime-project
|
||||
proj = subl .
|
||||
.DS_Store
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
*.nex
|
||||
src
|
||||
nexe.exe
|
||||
nexe
|
||||
npm-debug.log
|
||||
examples/**/src
|
||||
examples/**/out.nex
|
||||
@@ -0,0 +1,59 @@
|
||||
# Nexe ChangeLog
|
||||
|
||||
## 2015-02-20, Version v0.3.7, @jaredallard
|
||||
|
||||
### Noteable Changes
|
||||
|
||||
* Fixed #103.
|
||||
* Made not-available require not a fatal error.
|
||||
* Stub and system to ignore certain requires.
|
||||
* Added 'sys' to ignore list.
|
||||
* We have a gitter!
|
||||
* Gave win32 a 100 length progress bar.
|
||||
|
||||
### Commits
|
||||
|
||||
* [**2cacd83**] Update README.md (@crcn)
|
||||
* [**0e90ac9**] Update README.md (@crcn)
|
||||
* [**54967d1**] Added Gitter badge (@jaredallard)
|
||||
* [**bb489a3**] Fixes #98 by giving win32 a 100 length progress bar. (@jaredallard)
|
||||
* [**39665a8**] Lighter weight way to accomplish the exclusion of the sys module (@CKarper)
|
||||
* [**5aca22d**] This handles embedding 'bin' scripts with shebang interpreter... (@CKarper)
|
||||
* [**e79b0fb**] Stub to ignore require('sys') (@CKarper)
|
||||
|
||||
## 2015-02-15, Version v0.3.6, @jaredallard
|
||||
|
||||
### Noteable Changes
|
||||
|
||||
* Now support .json in require.
|
||||
* Fixed a major --python flag bug.
|
||||
|
||||
### Commits
|
||||
|
||||
* [**cac6986**] V bump to solve critical error. (@jaredallard)
|
||||
* [**b040337**] Fixes #99, resolves #97 by warning on missing file. New examples... (@jaredallard)
|
||||
* [**ad4da1d**] Support .json extensions in require() resolution (@CKarper)
|
||||
|
||||
## 2015-02-14, Version v0.3.5, @jaredallard
|
||||
|
||||
|
||||
### Noteable Changes
|
||||
|
||||
* Added new flag: `--python </path/to/python>`
|
||||
* Added resourceFiles option which allows embedding files and getting them via embed.js
|
||||
* Updated a bunch of the dependencies.
|
||||
* `process.argv` is now consistent in a child fork case.
|
||||
* Added `child_process.fork` support.
|
||||
* Added new collaborators:
|
||||
* Jared Allard (@jaredallard)
|
||||
|
||||
### Commits
|
||||
|
||||
* [**e4155c8**] Version bump 0.3.5, update depends (@jaredallard)
|
||||
* [**e91f5b5**] Add example, fix outdated examples (@jaredallard)
|
||||
* [**3b1d5a9**] Modify README, implement cross-plat `--python <loc>` closes #94 (@jaredallard)
|
||||
* [**29d5f6a**] Make `process.argv` consistent in the child fork case (@LorenzGardner)
|
||||
* [**97dbd37**] Add support for embedded files. (@LorenzGardner)
|
||||
* [**b615e12**] Make the example code demonstrate forked process and dynamic require (@LorenzGardner)
|
||||
* [**333cc69**] update read me mentioning usage of `child_process.fork` (@LorenzGardner)
|
||||
* [**ece4b2d**] Add `child_process.fork` support. (@LorenzGardner)
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2013 Craig Condon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,58 +1,177 @@
|
||||
Compile javascript **with** node.js. This allows you to move your executable around *without* needing to install the node.js runtime.
|
||||
### Nexe
|
||||
|
||||
## Requirements
|
||||
[](https://gitter.im/crcn/nexe?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://david-dm.org/crcn/nexe)
|
||||
[](http://waffle.io/crcn/nexe)
|
||||
|
||||
- Linux / Mac
|
||||
Nexe is a command-line utility that compiles your Node.js application into a single executable file.
|
||||
|
||||

|
||||
|
||||
|
||||
### Motivation
|
||||
|
||||
- Ability to run multiple applications with *different* node.js runtimes.
|
||||
- Distributable binaries without needing node / npm.
|
||||
- Starts faster.
|
||||
- Lockdown specific application versions, and easily rollback.
|
||||
- Faster deployments.
|
||||
|
||||
## Building Requirements
|
||||
|
||||
- Linux / Mac / BSD / Windows
|
||||
- Python 2.6 or 2.7 (use --python if not in PATH)
|
||||
- Windows: Visual Studio 2010+
|
||||
|
||||
## Caveats
|
||||
|
||||
### Doesn't support native modules
|
||||
|
||||
- Use the techniques below for working around dynamic require statements to exclude the module from the bundling, and deploy along side the executable in a node_module folder so your app can find it. Note: On windows you may need to have your app be named node.exe if .node file depends on node.
|
||||
|
||||
### Doesn't support dynamic require statements
|
||||
|
||||
Such As:
|
||||
|
||||
```javascript
|
||||
var x = require(someVar);
|
||||
```
|
||||
|
||||
In this case nexe won't bundle the file
|
||||
|
||||
```javascript
|
||||
var x;
|
||||
if (someCheck) {
|
||||
x = require("./ver1.js");
|
||||
} else {
|
||||
x = require("./var2.js");
|
||||
}
|
||||
```
|
||||
|
||||
In this case nexe will bundle both files.
|
||||
|
||||
Workarounds:
|
||||
1) for dynamic requires that you want bundled add the following into your project
|
||||
|
||||
```javascript
|
||||
var dummyToForceIncludeForBundle = false;
|
||||
if (dummyToForceIncludeForBundle) {
|
||||
require("./loadedDynamicallyLater.js");
|
||||
// ...
|
||||
}
|
||||
```
|
||||
this will trick the bundler into including them.
|
||||
|
||||
2) for dynamic files getting included that you don't want to be
|
||||
|
||||
```javascript
|
||||
var moduleName = "./ver2.js";
|
||||
if (someCheck) {
|
||||
moduleName = "./ver1.js";
|
||||
}
|
||||
var x = require(moduleName);
|
||||
```
|
||||
Note: neither file will be bundled.
|
||||
|
||||
Using these two techniques you can change your application code so modules are not bundles, and generate a includes.js file as part of your build process so that the right files get bundled for your build configuration.
|
||||
|
||||
### __dirname
|
||||
|
||||
Once the module is bundled it is part of the executable. __dirname is therefore the executable dir (process.execPath). Thus if you put resources on a relative path from the the executable your app will be able to access them.
|
||||
|
||||
If you had a data file at `/dev/myNodeApp/stateManager/handler/data/some.csv`
|
||||
and a file at `/dev/myNodeApp/stateManager/handler/loader.js`
|
||||
|
||||
```javascript
|
||||
module.exports = fw.readFileSync(path.join(__dirname, "./data/some.csv"));
|
||||
```
|
||||
You would need to deploy some.csv in a sub dir `data/` along side your executable
|
||||
|
||||
There are potential use cases for __dirname where the executable path is not the correct substitution, and could result in a silent error (possibly even in a dependency that you are unaware of).
|
||||
|
||||
Note: __filename will be 'undefined'
|
||||
|
||||
### child_process.fork
|
||||
|
||||
child_process.spawn works is unmodified, but child_process.fork will make an attempt to launch a new instance of your executable and run the bundled module.
|
||||
|
||||
## Installation
|
||||
|
||||
Via NPM:
|
||||
|
||||
```bash
|
||||
npm install nexe
|
||||
npm install nexe [-g]
|
||||
```
|
||||
|
||||
Or git:
|
||||
|
||||
```bash
|
||||
git clone
|
||||
git clone https://github.com/crcn/nexe.git
|
||||
```
|
||||
|
||||
|
||||
### Motivation
|
||||
|
||||
- Developing client-side utilities without requiring to install a bunch of dependencies first (node.js, npm).
|
||||
- Ability to run multiple node.js applications with *different* node.js runtimes.
|
||||
|
||||
|
||||
### CLI Usage
|
||||
|
||||
````text
|
||||
|
||||
Commands:
|
||||
-i the input javascript files
|
||||
-o the output executable
|
||||
--runtime the runtime version of node.js to compile with
|
||||
```text
|
||||
|
||||
Examples:
|
||||
-i input.js -o my-binary --runtime=0.6.2 compile javascript file with node
|
||||
Usage: nexe -i [sources] -o [binary] [options]
|
||||
|
||||
````
|
||||
Options:
|
||||
-i, --input The entry javascript files [default: cwd]
|
||||
-o, --output The output binary [default: out.nex]
|
||||
-r, --runtime The node.js runtime to use [default: "latest"]
|
||||
-t, --temp The path to store node.js sources [default: ./tmp/nexe]
|
||||
-f, --flags Don't parse node and v8 flags, pass through app flags [default: false]
|
||||
-v, --version Display version number
|
||||
-p, --python Set path of python to use. [default: "python"]
|
||||
-F, --framework Set the framework to use. [default: "nodejs"]
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Code usage
|
||||
### Code Usage
|
||||
|
||||
````javascript
|
||||
```javascript
|
||||
|
||||
var nexe = require('nexe');
|
||||
var nexe = require('nexe');
|
||||
|
||||
nexe.compile('input.js', 'output.bin', function() {
|
||||
|
||||
});
|
||||
|
||||
````
|
||||
nexe.compile({
|
||||
input: 'input.js',
|
||||
output: 'path/to/bin',
|
||||
nodeVersion: '0.12.5',
|
||||
nodeTempDir: 'src',
|
||||
python: 'path/to/python',
|
||||
resourceFiles: [ 'path/to/a/file' ],
|
||||
flags: true,
|
||||
framework: "nodejs"
|
||||
}, function(err) {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
### package.json inclusion
|
||||
|
||||
As of 0.4.0 you can now embed nexe options into package.json. Note that this Format
|
||||
is still in works, so it is likely to change.
|
||||
|
||||
```
|
||||
"nexe": {
|
||||
"input": "./bin/nexe",
|
||||
"output": "nexe^$",
|
||||
"temp": "src",
|
||||
"runtime": {
|
||||
"framework": "iojs",
|
||||
"version": "2.3.1",
|
||||
"ignoreFlags": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* output: can use ^$ for platform specific file extension
|
||||
|
||||
## Maintainers
|
||||
|
||||
* __Jared Allard__ ([@jaredallard](https://github.com/jaredallard)) <[jaredallard@outlook.com](mailto:jaredallard@outlook.com)> (Active)
|
||||
* __Christopher Karper__ ([@ckarper](https://github.com/CKarper)) <[Christopher.Karper@gmail.com](mailto:Christopher.Karper@gmail.com)> (Active)
|
||||
* __Craig Jefferds__ ([@crcn](https://github.com/crcn)) <[craig.j.condon@gmail.com](mailto:craig.j.condon@gmail.com)> (Not Active)
|
||||
|
||||
@@ -1,2 +1,96 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
nexe = require('../lib'),
|
||||
_log = require("../lib/log"),
|
||||
cli = require('yargs').
|
||||
usage('Usage: $0 -i [sources] -o [binary]').
|
||||
options('i', {
|
||||
demand: true,
|
||||
alias: 'input',
|
||||
desc: 'The entry javascript files',
|
||||
default: process.cwd()
|
||||
}).
|
||||
options('o', {
|
||||
demand: true,
|
||||
alias: 'output',
|
||||
desc: 'The output binary',
|
||||
default: "out.nex"
|
||||
}).
|
||||
options('r', {
|
||||
alias: 'runtime',
|
||||
default: 'latest',
|
||||
description: 'The node.js runtime to use'
|
||||
}).
|
||||
options('t', {
|
||||
alias: 'temp',
|
||||
default: './tmp/nexe',
|
||||
description: 'The path to store node.js sources'
|
||||
}).
|
||||
options('f', {
|
||||
alias: 'flags',
|
||||
description: 'Don\'t parse node and v8 flags, pass through app flags',
|
||||
default: false
|
||||
}).
|
||||
options('v', {
|
||||
alias: 'version',
|
||||
description: 'Display version number'
|
||||
}).
|
||||
options('p', {
|
||||
alias: 'python',
|
||||
description: 'Set path of python to use.',
|
||||
default: 'python'
|
||||
}).
|
||||
options('F', {
|
||||
alias: 'framework',
|
||||
description: 'Set the framework to use',
|
||||
default: 'nodejs'
|
||||
});
|
||||
|
||||
var argv = cli.argv;
|
||||
if(argv.h || argv.help) {
|
||||
cli.showHelp();
|
||||
process.exit();
|
||||
} else if (argv.v || argv.version) {
|
||||
var pkginfo = require('../package.json');
|
||||
console.log(pkginfo.version);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Support network shares?
|
||||
**/
|
||||
function toAbsolute(pt) {
|
||||
if(pt.substr(0, 1) == "/") return pt;
|
||||
if(pt.substr(1, 3) == ":/") return pt; // for windows "c:/"
|
||||
return path.join(process.cwd(), pt);
|
||||
}
|
||||
|
||||
if(fs.lstatSync(argv.i).isDirectory()) {
|
||||
opts = nexe.package(path.join(argv.i, "package.json"), argv);
|
||||
nexe.compile(opts, function(error) {
|
||||
if(error) {
|
||||
console.log(error.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
/**
|
||||
* Call the core
|
||||
**/
|
||||
nexe.compile({
|
||||
input : require.resolve(toAbsolute(argv.i)),
|
||||
output : toAbsolute(argv.o),
|
||||
flags : argv.f,
|
||||
nodeVersion : argv.r,
|
||||
python : argv.python,
|
||||
nodeTempDir : toAbsolute(argv.t),
|
||||
framework : argv.F
|
||||
},
|
||||
function(error) {
|
||||
if(error) {
|
||||
console.log(error.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
console.log("hello browser!");
|
||||
@@ -0,0 +1,19 @@
|
||||
var nexe = require('../..');
|
||||
|
||||
nexe.compile(
|
||||
{
|
||||
input: "./index.js",
|
||||
output: "./out.nex",
|
||||
nodeVersion: "3.0.0",
|
||||
framework: "iojs",
|
||||
nodeTempDir: "src",
|
||||
python: "python",
|
||||
flags: true,
|
||||
resourceFiles: ["./message.txt"]
|
||||
},
|
||||
function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
Hello World!!!
|
||||
@@ -0,0 +1,23 @@
|
||||
var http = require("http"),
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
nexeres = require("nexeres"),
|
||||
childProc = require("child_process"),
|
||||
port = 1337;
|
||||
|
||||
//Fork a new process to execute the broser.js
|
||||
childProc.fork(path.join(__dirname, "browser.js"));
|
||||
if (false) {
|
||||
require("./browser.js"); //force the bundler to include the .js file
|
||||
}
|
||||
|
||||
//start a web server on specified port (or default if not given)
|
||||
console.log("started HTTP server on port %d", port = Number(process.argv.concat().pop()) || port);
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
//return the embeded file in response to any request
|
||||
|
||||
res.write(nexeres.get("message.txt"));
|
||||
|
||||
res.end();
|
||||
}).listen(port);
|
||||
@@ -0,0 +1 @@
|
||||
hello world!
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "./index.js",
|
||||
"browser": "./index.js"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
console.log("hello browser!");
|
||||
@@ -0,0 +1,18 @@
|
||||
var nexe = require('../..');
|
||||
|
||||
nexe.compile(
|
||||
{
|
||||
input: "./index.js",
|
||||
output: "./out.nex",
|
||||
nodeVersion: "3.0.0",
|
||||
nodeTempDir: "./src",
|
||||
framework: "iojs",
|
||||
python: 'python',
|
||||
flags: true
|
||||
},
|
||||
function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
var http = require("http"),
|
||||
fs = require("fs"),
|
||||
path = require("path"),
|
||||
nexeres = require("nexeres"),
|
||||
childProc = require("child_process"),
|
||||
port = 1337;
|
||||
|
||||
//Fork a new process to execute the broser.js
|
||||
childProc.fork(path.join(__dirname, "browser.js"));
|
||||
if (false) {
|
||||
require("./browser.js"); //force the bundler to include the .js file
|
||||
}
|
||||
|
||||
//start a web server on specified port (or default if not given)
|
||||
console.log("started HTTP server on port %d", port = Number(process.argv.concat().pop()) || port);
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
//return the embeded file in response to any request
|
||||
|
||||
res.write("Hello, world!");
|
||||
|
||||
res.end();
|
||||
}).listen(port);
|
||||
@@ -0,0 +1 @@
|
||||
hello world!
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"main": "./index.js",
|
||||
"browser": "./index.js"
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Craig Condon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**/
|
||||
var mdeps = require("module-deps"),
|
||||
through = require("through"),
|
||||
async = require("async"),
|
||||
builtins = require("builtins");
|
||||
|
||||
var _log = require("./log");
|
||||
|
||||
function bundle (input, complete) {
|
||||
|
||||
async.waterfall([
|
||||
|
||||
/**
|
||||
* first we resolve all of the deps
|
||||
*/
|
||||
|
||||
function resolveDeps (next) {
|
||||
|
||||
|
||||
var deps = [];
|
||||
|
||||
|
||||
var md = mdeps({
|
||||
xtransform: function (tr, file) {
|
||||
|
||||
var buffer = [];
|
||||
console.log(tr);
|
||||
|
||||
|
||||
return through(write, end);
|
||||
|
||||
var self = this;
|
||||
|
||||
|
||||
function write (chunk) {
|
||||
buffer.push(chunk.toString());
|
||||
// console.log(chunk.toString(""))
|
||||
console.log(tr);
|
||||
}
|
||||
|
||||
function end() {
|
||||
var content = buffer.join("");
|
||||
// console.log(content);
|
||||
/*
|
||||
// TODO add uglify flag
|
||||
var source = uglify.parse(content, {
|
||||
strict: false
|
||||
});
|
||||
source.figure_out_scope();
|
||||
source.compute_char_frequency();
|
||||
source.mangle_names();
|
||||
|
||||
// TODO - production
|
||||
content = source.print_to_string({
|
||||
ascii_only: true,
|
||||
quote_keys: true
|
||||
});*/
|
||||
|
||||
this.queue(content);
|
||||
this.queue(null);
|
||||
}
|
||||
|
||||
},
|
||||
filter: function (id) {
|
||||
if ([ 'nexeres', 'sys', 'readline' ].indexOf(id) > -1) { return false; }
|
||||
return !~builtins.indexOf(id);
|
||||
},
|
||||
extensions: [ '.js', '.json' ],
|
||||
ignoreMissing: true
|
||||
});
|
||||
|
||||
/** event for missing packages, fixes conditional requires **/
|
||||
md.on('missing', function(id, parent) {
|
||||
_log("warn", "couldn't find require '" + id + "', errors may occur.");
|
||||
});
|
||||
|
||||
md.pipe(through(function (chunk) {
|
||||
deps.push(chunk);
|
||||
}, function () {
|
||||
next(null, deps);
|
||||
}));
|
||||
|
||||
md.end({ file: input })
|
||||
|
||||
},
|
||||
|
||||
function bundleScript (deps, next) {
|
||||
var buffer = [loader.toString()];
|
||||
var dbuffer = [];
|
||||
|
||||
for (var i = deps.length; i--;) {
|
||||
var dep = deps[i];
|
||||
|
||||
var req = "function (require, module, exports, __dirname) { \n"
|
||||
if (dep.id.toLowerCase().indexOf(".json", dep.id.length - 5) !== -1) {
|
||||
//this is the result of require("someFile.json"), so we need to export it from the function
|
||||
req += "module.exports = "
|
||||
}
|
||||
if ((/^\#\!/).test(dep.source)) {
|
||||
dep.source = '//' + dep.source;
|
||||
}
|
||||
|
||||
req += dep.source + "}";
|
||||
|
||||
dbuffer.push(JSON.stringify(dep.id) + ": ["+req+", "+!!dep.entry+", "+JSON.stringify(dep.deps)+"]")
|
||||
}
|
||||
|
||||
buffer = ["(" + loader.toString() + ").call(null, {"+dbuffer.join(",")+"}," + JSON.stringify(deps[deps.length-1].id) + ")"].toString();
|
||||
|
||||
next(null, buffer);
|
||||
}
|
||||
], complete)
|
||||
}
|
||||
|
||||
|
||||
var loader = function (deps, key) {
|
||||
var pathModule = global.require("path");
|
||||
var darr = [];
|
||||
var dir = global.require("path").dirname(process.execPath);
|
||||
|
||||
var argv3 = process.argv[3];
|
||||
if (argv3) {
|
||||
argv3 = pathModule.relative(pathModule.dirname(process.execPath), argv3);
|
||||
argv3 = pathModule.resolve(pathModule.dirname(key), argv3);
|
||||
}
|
||||
if (process.argv[2] == "--child_process" && deps[argv3]) {
|
||||
//we've been forked and should run the module specified by argv3[3] instead of the start up module
|
||||
key = argv3;
|
||||
process.argv.splice(2, 2); //restore the argv to [0] = executable, [1] = nexejs
|
||||
}
|
||||
else if (process.argv[2] == "--child_process") {
|
||||
//fork called, but for a module not bundled.
|
||||
argv3 = process.argv[3];
|
||||
process.argv.splice(1, 2); //restore the argv to [0] = executable, [1] = script
|
||||
global.require(argv3);
|
||||
return;
|
||||
}
|
||||
darr.push(deps[key]); //start up module.
|
||||
|
||||
function initModule (dep) {
|
||||
if (dep.module) return dep.module.exports;
|
||||
dep.module = { exports: {} };
|
||||
|
||||
dep[0](function (path) {
|
||||
var rdep = deps[dep[2][path]];
|
||||
var exports = rdep ? rdep.module ? rdep.module.exports : initModule(rdep) : global.require(path);
|
||||
return exports;
|
||||
}, dep.module, dep.module.exports, dir);
|
||||
|
||||
return dep.module.exports;
|
||||
}
|
||||
|
||||
//run the startup module
|
||||
darr.forEach(initModule);
|
||||
|
||||
return darr.filter(function (dep) {
|
||||
return dep[1];
|
||||
}).map(function (dep) {
|
||||
return dep.module || {};
|
||||
}).pop();
|
||||
}
|
||||
|
||||
module.exports = bundle;
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Craig Condon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**/
|
||||
|
||||
var path = require("path"),
|
||||
fs = require("fs");
|
||||
|
||||
/**
|
||||
* TODO: Optimize this code. (more like document it so I understand it better.)
|
||||
**/
|
||||
function embed(resourceFiles, resourceRoot, complete) {
|
||||
function encode(filePath) {
|
||||
return fs.readFileSync(filePath).toString('base64');
|
||||
}
|
||||
|
||||
resourceFiles = resourceFiles || [];
|
||||
resourceRoot = resourceRoot || "";
|
||||
|
||||
if (!Array.isArray(resourceFiles)) {
|
||||
throw new Error("Bad Argument: resourceFiles is not an array");
|
||||
}
|
||||
|
||||
var buffer = "var embeddedFiles = {\n";
|
||||
for (var i = 0; i < resourceFiles.length; ++i) {
|
||||
buffer += JSON.stringify(path.relative(resourceRoot, resourceFiles[i])) + ': "';
|
||||
buffer += encode(resourceFiles[i]) + '",\n';
|
||||
}
|
||||
|
||||
buffer += "\n};\n\nmodule.exports.keys = function () { return Object.keys(embeddedFiles); }\n\nmodule.exports.get = ";
|
||||
buffer += accessor.toString();
|
||||
complete(null, buffer);
|
||||
}
|
||||
|
||||
var accessor = function (key) {
|
||||
if (embeddedFiles.hasOwnProperty(key)) {
|
||||
return new Buffer(embeddedFiles[key], 'base64');
|
||||
}
|
||||
else {
|
||||
//file was not embedded, throw err.
|
||||
throw new Error('Embedded file not found');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = embed;
|
||||
+674
@@ -0,0 +1,674 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Craig Condon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**/
|
||||
var async = require("async"),
|
||||
outcome = require("outcome"),
|
||||
mkdirp = require("mkdirp"),
|
||||
request = require("request"),
|
||||
path = require("path"),
|
||||
fs = require("fs"),
|
||||
ncp = require("ncp").ncp,
|
||||
ProgressBar = require("progress"),
|
||||
child_process = require("child_process"),
|
||||
glob = require("glob"),
|
||||
bundle = require("./bundle"),
|
||||
embed = require("./embed"),
|
||||
os = require("os"),
|
||||
targz = require('tar.gz'),
|
||||
_log = require("./log"),
|
||||
_monkeypatch = require("./monkeypatch"),
|
||||
spawn = child_process.spawn;
|
||||
|
||||
var isWin = /^win/.test(process.platform);
|
||||
var isPy;
|
||||
var framework;
|
||||
var version;
|
||||
|
||||
var option_list = [
|
||||
"python",
|
||||
"input",
|
||||
"output",
|
||||
"nodeTempDir",
|
||||
"flags",
|
||||
"framework",
|
||||
"nodeVersion"
|
||||
]
|
||||
|
||||
/**
|
||||
* Compiliation process.
|
||||
*/
|
||||
|
||||
exports.compile = function (options, complete) {
|
||||
|
||||
var nodeCompiler, nexeEntryPath;
|
||||
|
||||
async.waterfall([
|
||||
/**
|
||||
*check relevant options
|
||||
*/
|
||||
function checkOpts (next) {
|
||||
/* failsafe */
|
||||
if(options === undefined) {
|
||||
_log("error", "no options given to .compile()");
|
||||
process.exit()
|
||||
}
|
||||
|
||||
option_list.forEach(function(v) {
|
||||
if(options[v] === undefined) {
|
||||
_log("error", "option "+v+" was empty")
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Have we been given a custom flag for python executable?
|
||||
**/
|
||||
if(options.python!=='python' && options.python!==""
|
||||
&& options.python!==undefined) {
|
||||
if(isWin) {
|
||||
isPy=options.python.replace(/\//gm, "\\"); // use windows file paths, batch is sensitive.
|
||||
} else {
|
||||
isPy=options.python;
|
||||
}
|
||||
|
||||
_log("set python as "+isPy);
|
||||
} else {
|
||||
isPy="python";
|
||||
}
|
||||
|
||||
// remove dots
|
||||
options.framework = options.framework.replace(/\./g, "");
|
||||
|
||||
// set outter-scope framework variable.
|
||||
framework = options.framework;
|
||||
_log("framework => "+framework);
|
||||
|
||||
version = options.nodeVersion; // better framework vc
|
||||
|
||||
// check iojs version
|
||||
if (framework === "iojs" && version === "latest" ) {
|
||||
_log("fetching iojs versions");
|
||||
mkdirp(options.nodeTempDir); // make temp dir, probably repetive.
|
||||
|
||||
// create write stream so we have control over events
|
||||
var output = fs.createWriteStream(path.join(options.nodeTempDir,
|
||||
"iojs-versions.json"));
|
||||
|
||||
request.get("https://iojs.org/dist/index.json")
|
||||
.pipe(output);
|
||||
|
||||
output.on('close', function() {
|
||||
_log("done");
|
||||
var f = fs.readFileSync(path.join(options.nodeTempDir,
|
||||
"iojs-versions.json"));
|
||||
f = JSON.parse(f);
|
||||
version = f[0].version.replace("v", "");
|
||||
|
||||
_log("iojs latest => "+version);
|
||||
|
||||
// continue down along the async road
|
||||
next();
|
||||
})
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* first download node
|
||||
*/
|
||||
function downloadNode (next) {
|
||||
_downloadNode(version, options.nodeTempDir, next);
|
||||
},
|
||||
|
||||
/**
|
||||
* bundle the application into one script
|
||||
*/
|
||||
|
||||
function combineProject (nc, next) {
|
||||
nodeCompiler = nc;
|
||||
_log("bundle %s", options.input);
|
||||
bundle(options.input, next);
|
||||
},
|
||||
|
||||
/**
|
||||
* write the bundle to the lib directory of the target node version
|
||||
*/
|
||||
|
||||
function writeBundle (source, next) {
|
||||
bundlePath = path.join(nodeCompiler.dir, "lib", "nexe.js");
|
||||
_log("bundle -> %s", bundlePath);
|
||||
|
||||
//Remove all non-ascii code from sources
|
||||
source = source.replace(/[^\x00-\x7F]/g, "");
|
||||
// same path as all the other JS files
|
||||
fs.writeFile(bundlePath, source, next);
|
||||
},
|
||||
|
||||
function embedResources(next) {
|
||||
_log("embedResources %s", options.resourceFiles);
|
||||
embed(options.resourceFiles, options.resourceRoot, next);
|
||||
},
|
||||
|
||||
function writeResources (resources, next) {
|
||||
resourcePath = path.join(nodeCompiler.dir, "lib", "nexeres.js");
|
||||
_log("resource -> %s", resourcePath);
|
||||
|
||||
fs.writeFile(resourcePath, resources, next);
|
||||
},
|
||||
|
||||
/**
|
||||
* monkeypatch some files so that the nexe.js file is loaded when the app runs
|
||||
*/
|
||||
|
||||
function monkeyPatchNodeConfig (next) {
|
||||
_monkeyPatchNodeConfig(nodeCompiler, next);
|
||||
},
|
||||
|
||||
/**
|
||||
* monkeypatch node.cc to prevent v8 and node from processing CLI flags
|
||||
*/
|
||||
function monkeyPatchNodeCc (next) {
|
||||
if (options.flags) {
|
||||
_monkeyPatchMainCc(nodeCompiler, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* monkeypatch child_process.js so nexejs knows when it is a forked process
|
||||
*/
|
||||
function monkeyPatchChildProc(next) {
|
||||
_monkeyPatchChildProcess(nodeCompiler, next);
|
||||
},
|
||||
|
||||
/**
|
||||
* compile the node application
|
||||
*/
|
||||
|
||||
function makeExe (next) {
|
||||
if(isWin) {
|
||||
_log("vcbuild [make stage]");
|
||||
} else {
|
||||
_log("make");
|
||||
}
|
||||
nodeCompiler.make(next);
|
||||
},
|
||||
|
||||
/**
|
||||
* we create the output directory if needed
|
||||
*/
|
||||
|
||||
function makeOutputDirectory (next) {
|
||||
mkdirp(path.dirname(options.output), function(){ next(); });
|
||||
},
|
||||
|
||||
/**
|
||||
* Copy the compilied binary to the output specified.
|
||||
*/
|
||||
|
||||
function copyBinaryToOutput (next) {
|
||||
_log("cp %s %s", nodeCompiler.releasePath, options.output);
|
||||
ncp(nodeCompiler.releasePath, options.output, function (err) {
|
||||
if (err) {
|
||||
_log("error", "Couldn't copy binary.");
|
||||
throw err; // dump raw error object
|
||||
}
|
||||
_log('copied');
|
||||
|
||||
next();
|
||||
});
|
||||
}
|
||||
], complete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a version of node
|
||||
*
|
||||
* @param {string} version, version of node to download
|
||||
* @param {string} directory, where to store the downloaded src
|
||||
* @param {function} complete, callback
|
||||
*/
|
||||
|
||||
function _downloadNode (version, directory, complete) {
|
||||
|
||||
var nodeFileDir = path.resolve(path.join(directory, framework, version)), // fixes #107, was process.cwd(), + rest.
|
||||
nodeFilePath = path.resolve(path.join(nodeFileDir, framework + "-" + version + ".tar.gz"));
|
||||
|
||||
|
||||
// might already be downloaded, and unzipped
|
||||
if (_getNodeCompiler(nodeFileDir, complete)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
async.waterfall([
|
||||
|
||||
/**
|
||||
* first make the directory where the zip file will live
|
||||
*/
|
||||
|
||||
function makeDirectory (next) {
|
||||
mkdirp.sync(path.dirname(nodeFilePath));
|
||||
next();
|
||||
},
|
||||
|
||||
/**
|
||||
* download node into the target directory
|
||||
*/
|
||||
|
||||
function downloadNode (next) {
|
||||
if (fs.existsSync(nodeFilePath)) return next();
|
||||
|
||||
var type = global.type;
|
||||
var url, prefix = "https://"+framework+".org/dist";
|
||||
|
||||
// pick which url depending on the version
|
||||
if(framework==="nodejs") framework = "node"; // cmon node why can't you stay the same
|
||||
|
||||
if (version === "latest") {
|
||||
url = prefix + "/" + framework + "-" + version + ".tar.gz";
|
||||
} else {
|
||||
url = prefix + "/v" + version + "/"+framework+"-v" + version + ".tar.gz";
|
||||
}
|
||||
|
||||
_log("downloading %s", url);
|
||||
|
||||
var output = fs.createWriteStream(nodeFilePath, { "flags": "w+" });
|
||||
|
||||
// need to set user-agent to bypass some corporate firewalls
|
||||
var requestOptions = {
|
||||
url: url,
|
||||
headers: {
|
||||
"User-Agent": "Node.js"
|
||||
}
|
||||
}
|
||||
|
||||
_logProgress(request(requestOptions)).pipe(output);
|
||||
|
||||
output.on("close", function () { next(); });
|
||||
},
|
||||
|
||||
/**
|
||||
* unzip in the same directory
|
||||
*/
|
||||
|
||||
function unzipNodeTarball (next) {
|
||||
if(isWin) {
|
||||
_log("Extracting the .tar.gz.");
|
||||
new targz().extract(nodeFilePath, nodeFileDir, next);
|
||||
} else {
|
||||
var cmd = ["tar", "-xf", nodeFilePath, "-C", nodeFileDir];
|
||||
_log(cmd.join(" "));
|
||||
|
||||
var tar = spawn(cmd.shift(), cmd);
|
||||
tar.stdout.pipe(process.stdout);
|
||||
tar.stderr.pipe(process.stderr);
|
||||
|
||||
tar.on("close", function () { next(); })
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* return the compiler object for the node version
|
||||
*/
|
||||
|
||||
function (next, type) {
|
||||
_getNodeCompiler(nodeFileDir, next, type)
|
||||
},
|
||||
|
||||
], complete);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the compilier we will use for whatever platform we may be on and configure
|
||||
* it.
|
||||
*/
|
||||
|
||||
function _getNodeCompiler (nodeFileDir, complete, type) {
|
||||
var dir = _getFirstDirectory(nodeFileDir);
|
||||
|
||||
// standard
|
||||
var executable = "node.exe";
|
||||
var binary = "node";
|
||||
|
||||
// iojs specifics.
|
||||
if(framework === "iojs") {
|
||||
executable = "iojs.exe";
|
||||
binary = "iojs";
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
if(isWin) {
|
||||
complete(null, {
|
||||
dir: dir,
|
||||
version: path.basename(nodeFileDir),
|
||||
releasePath: path.join(dir, "Release", executable),
|
||||
make: function(next) {
|
||||
// create a new env with minimal impact on old one
|
||||
var newEnv = process.env
|
||||
|
||||
if(isPy!=="python") {
|
||||
// add the dir of the suposed python exe to path
|
||||
newEnv.path = process.env.PATH+";"+path.dirname(isPy)
|
||||
}
|
||||
|
||||
// spawn a vcbuild process with our custom enviroment.
|
||||
var vcbuild = spawn("vcbuild.bat", ["nosign", "release"], {
|
||||
cwd: dir,
|
||||
env: newEnv
|
||||
});
|
||||
vcbuild.stdout.pipe(process.stdout);
|
||||
vcbuild.stderr.pipe(process.stderr);
|
||||
vcbuild.on("close", function() {
|
||||
next();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
complete(null, {
|
||||
dir: dir,
|
||||
version: path.basename(nodeFileDir),
|
||||
releasePath: path.join(dir, "out", "Release", binary),
|
||||
make: function (next) {
|
||||
var cfg = "./configure", configure;
|
||||
if(isPy !== "python") {
|
||||
configure = spawn(isPy, [cfg], { cwd: dir });
|
||||
} else {
|
||||
configure = spawn(cfg, [], { cwd: dir });
|
||||
}
|
||||
|
||||
// local function, move to top eventually
|
||||
function _loop(dir) {
|
||||
/* eventually try every python file */
|
||||
var pdir = fs.readdirSync(dir);
|
||||
|
||||
pdir.forEach(function(v, i) {
|
||||
var stat = fs.statSync(dir+"/"+v);
|
||||
if(stat.isFile()) {
|
||||
// only process Makefiles and .mk targets.
|
||||
if(v !== "Makefile" && path.extname(v) !== ".mk") {
|
||||
return;
|
||||
}
|
||||
|
||||
_log("patching "+v);
|
||||
|
||||
/* patch the file */
|
||||
var py = fs.readFileSync(dir+"/"+v, {encoding: 'utf8'});
|
||||
py = py.replace(/([a-z]|\/)*python(\w|)/gm, isPy); // this is definently needed
|
||||
fs.writeFileSync(dir+"/"+v, py, {encoding: 'utf8'}); // write to file
|
||||
|
||||
delete pv;
|
||||
} else if(stat.isDirectory()) {
|
||||
// must be dir?
|
||||
// skip tests because we don't need them here
|
||||
if(v !== "test") {
|
||||
_loop(dir+"/"+v)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
configure.stdout.pipe(process.stdout);
|
||||
configure.stderr.pipe(process.stderr);
|
||||
configure.on("close", function () {
|
||||
if(isPy !== "python") {
|
||||
/**
|
||||
* Originally I thought this only applied to io.js,
|
||||
* however I soon found out this affects node.js,
|
||||
* so it is now mainstream.
|
||||
*/
|
||||
_log("preparing python");
|
||||
|
||||
// loop over depends
|
||||
_loop(dir);
|
||||
}
|
||||
var platformMake = "make";
|
||||
if (os.platform().match(/bsd$/) != null) {
|
||||
platformMake = "gmake";
|
||||
}
|
||||
var make = spawn(platformMake, [], { cwd: dir });
|
||||
make.stdout.pipe(process.stdout);
|
||||
make.stderr.pipe(process.stderr);
|
||||
make.on("close", function () {
|
||||
next();
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
function _monkeyPatchNodeConfig (compiler, complete) {
|
||||
async.waterfall([
|
||||
/**
|
||||
* monkeypatch the gyp file to include the nexe.js and nexeres.js files
|
||||
*/
|
||||
function (next) {
|
||||
_monkeyPatchGyp(compiler, next)
|
||||
},
|
||||
|
||||
/**
|
||||
* monkeypatch main entry point
|
||||
*/
|
||||
function (next) {
|
||||
_monkeyPatchMainJs(compiler, next)
|
||||
}
|
||||
], complete);
|
||||
}
|
||||
|
||||
/**
|
||||
* patch the gyp file to allow our custom includes
|
||||
*/
|
||||
|
||||
function _monkeyPatchGyp (compiler, complete) {
|
||||
|
||||
var gypPath = path.join(compiler.dir, "node.gyp");
|
||||
|
||||
_monkeypatch(
|
||||
gypPath,
|
||||
function (content) {
|
||||
return ~content.indexOf("nexe.js");
|
||||
},
|
||||
function (content, next) {
|
||||
next(null, content.replace("'lib/fs.js',", "'lib/fs.js', 'lib/nexe.js', 'lib/nexeres.js', "))
|
||||
},
|
||||
complete
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
function _monkeyPatchMainJs (compiler, complete) {
|
||||
var mainPath = path.join(compiler.dir, "src", "node.js");
|
||||
|
||||
_monkeypatch(
|
||||
mainPath,
|
||||
function (content) {
|
||||
return ~content.indexOf("nexe");
|
||||
},
|
||||
function (content, next) {
|
||||
next(null, content.replace(/\(function\(process\) \{/,'(function(process) {\n process._eval = \'require("nexe");\';\n process.argv.splice(1, 0, "nexe.js");\n'))
|
||||
},
|
||||
complete
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
function _monkeyPatchChildProcess(compiler, complete) {
|
||||
var childProcPath = path.join(compiler.dir, "lib", "child_process.js");
|
||||
|
||||
_monkeypatch(
|
||||
childProcPath,
|
||||
function (content) {
|
||||
return ~content.indexOf("--child_process");
|
||||
},
|
||||
function (content, next) {
|
||||
next(null, content.replace(/return spawn\(/, 'args.unshift("--child_process");\n return spawn('));
|
||||
},
|
||||
complete
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch node.cc to not check the internal arguments.
|
||||
*/
|
||||
|
||||
function _monkeyPatchMainCc(compiler, complete) {
|
||||
var mainPath = path.join(compiler.dir, "src", "node.cc");
|
||||
_monkeypatch(
|
||||
mainPath,
|
||||
function (content) {
|
||||
return ~content.indexOf('// // TODO use parse opts');
|
||||
},
|
||||
function (content, next) {
|
||||
var lines = content.split('\n');
|
||||
var endLine = lines.indexOf(' option_end_index = i;'); // pre node 0.11.6 compat
|
||||
|
||||
if(endLine !== -1) { // check if it succedded or not.
|
||||
lines[endLine] = ' option_end_index = 1;';
|
||||
_log("patched node.cc")
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the new method of passing the args. Tested on node.js 0.12.5
|
||||
* and iojs 2.3.1
|
||||
**/
|
||||
if(endLine === -1) { // only if the pre-0.12.5 failed.
|
||||
var startLine = lines.indexOf(' while (index < nargs && argv[index][0] == \'-\') {'); // beginning of the function
|
||||
endLine = lines.indexOf(' // Copy remaining arguments.');
|
||||
endLine = endLine-1; // space, then it's at the }
|
||||
|
||||
// remove the offending lines
|
||||
if(startLine !== -1) {
|
||||
for (var i = startLine; i < endLine; i++) {
|
||||
lines[i] = undefined; // set the value to undefined so it's skipped by the join
|
||||
}
|
||||
_log('patched node.cc');
|
||||
}
|
||||
}
|
||||
|
||||
lines = lines.join('\n');
|
||||
next(null, lines);
|
||||
},
|
||||
complete
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
function _getFirstDirectory (dir) {
|
||||
var files = glob.sync(dir + "/*");
|
||||
|
||||
for (var i = files.length; i--;) {
|
||||
var file = files[i];
|
||||
if (fs.statSync(file).isDirectory()) return file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
|
||||
function _logProgress (req) {
|
||||
|
||||
req.on("response", function (resp) {
|
||||
|
||||
var len = parseInt(resp.headers["content-length"], 10),
|
||||
bar = new ProgressBar("[:bar]", {
|
||||
complete: "=",
|
||||
incomplete: " ",
|
||||
total: len,
|
||||
width: ((isWin) ? 100 : process.stdout.columns - 2) // windows doesn't output colums correctly
|
||||
});
|
||||
|
||||
req.on("data", function (chunk) {
|
||||
bar.tick(chunk.length);
|
||||
});
|
||||
});
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to parse the package.json for nexe information.
|
||||
*
|
||||
* @param {string} path - path to package.json
|
||||
* @param {object} options - fallback options
|
||||
*
|
||||
* @todo implement options overriding package defaults.
|
||||
*
|
||||
* @return {object} nexe.compile options object
|
||||
**/
|
||||
exports.package = function(path, options) {
|
||||
var _package; // scope
|
||||
|
||||
// check if the file exists
|
||||
if(fs.existsSync(path)===false) {
|
||||
_log("warn", "no package.json found.");
|
||||
} else {
|
||||
_package = require(path);
|
||||
}
|
||||
|
||||
// replace ^$ w/ os specific extension on output
|
||||
if(isWin) {
|
||||
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '.exe') // exe
|
||||
} else {
|
||||
_package.nexe.output = _package.nexe.output.replace(/\^\$/, '') // none
|
||||
}
|
||||
|
||||
// construct the object
|
||||
var obj = {
|
||||
input: (_package.nexe.input || options.i),
|
||||
output: (_package.nexe.output || options.o),
|
||||
flags: (_package.nexe.runtime.ignoreFlags || options.f),
|
||||
resourceFiles: (_package.nexe.resourceFiles),
|
||||
nodeVersion: (_package.nexe.runtime.version || options.r),
|
||||
python: (_package.nexe.python || options.p),
|
||||
nodeTempDir: (_package.nexe.temp || options.t),
|
||||
framework: (_package.nexe.runtime.framework || options.f)
|
||||
}
|
||||
|
||||
Object.keys(_package.nexe).forEach(function(v,i) {
|
||||
if(v!=="runtime") {
|
||||
_log("log", v+" => '"+_package.nexe[v]+"'");
|
||||
}
|
||||
});
|
||||
Object.keys(_package.nexe.runtime).forEach(function(v,i) {
|
||||
_log("log", "runtime."+v+" => '"+_package.nexe.runtime[v]+"'");
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
+1
-3
@@ -1,3 +1 @@
|
||||
exports.compile = function(ops, callback) {
|
||||
|
||||
}
|
||||
module.exports = require("./exe");
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Craig Condon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
* standard output, takes 3 different types.
|
||||
* log, error, and warn
|
||||
*
|
||||
* @param {any} arguments - Text to output.
|
||||
* @return undefined
|
||||
**/
|
||||
function _log () {
|
||||
|
||||
var colors = require('colors');
|
||||
|
||||
var args = Array.prototype.slice.call(arguments, 0),
|
||||
level = args.shift();
|
||||
|
||||
if (!~["log", "error", "warn"].indexOf(level)) {
|
||||
args.unshift(level);
|
||||
level = "log";
|
||||
}
|
||||
|
||||
if(level == "log") {
|
||||
args[0] = "----> " + args[0];
|
||||
} else if(level == "error") {
|
||||
args[0] = "....> " + colors.red("ERROR: ") + args[0]
|
||||
} else if(level == "warn") {
|
||||
args[0] = "....> " + colors.yellow("WARNING: ") + args[0]
|
||||
}
|
||||
|
||||
console[level].apply(console, args);
|
||||
}
|
||||
|
||||
// export the log function, for require()
|
||||
module.exports = _log;
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Craig Condon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**/
|
||||
|
||||
var async = require("async"),
|
||||
fs = require("fs"),
|
||||
_log = require("./log");
|
||||
|
||||
/**
|
||||
* Monkey patch a file.
|
||||
*
|
||||
* @param {string} filePath - path to file.
|
||||
* @param {function} monkeyPatched - function to process contents
|
||||
* @param {function} processor - TODO: detail what this is
|
||||
* @param {function} complete - callback
|
||||
*
|
||||
* @return undefined
|
||||
*/
|
||||
function _monkeypatch (filePath, monkeyPatched, processor, complete) {
|
||||
|
||||
async.waterfall([
|
||||
|
||||
function read (next) {
|
||||
fs.readFile(filePath, "utf8", next);
|
||||
},
|
||||
|
||||
// TODO - need to parse gyp file - this is a bit hacker
|
||||
function monkeypatch (content, next) {
|
||||
|
||||
if (monkeyPatched(content)) return complete();
|
||||
|
||||
_log("monkey patch %s", filePath);
|
||||
processor(content, next);
|
||||
},
|
||||
|
||||
function write (content, next) {
|
||||
fs.writeFile(filePath, content, "utf8", next);
|
||||
}
|
||||
], complete);
|
||||
}
|
||||
|
||||
// export the function for require()
|
||||
module.exports = _monkeypatch;
|
||||
Generated
-2
@@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
node_modules/*
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
lib-cov/*
|
||||
*.swp
|
||||
*.swo
|
||||
node_modules
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
Copyright 2010 James Halliday (mail@substack.net)
|
||||
|
||||
This project is free software released under the MIT/X11 license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-474
@@ -1,474 +0,0 @@
|
||||
optimist
|
||||
========
|
||||
|
||||
Optimist is a node.js library for option parsing for people who hate option
|
||||
parsing. More specifically, this module is for people who like all the --bells
|
||||
and -whistlz of program usage but think optstrings are a waste of time.
|
||||
|
||||
With optimist, option parsing doesn't have to suck (as much).
|
||||
|
||||
examples
|
||||
========
|
||||
|
||||
With Optimist, the options are just a hash! No optstrings attached.
|
||||
-------------------------------------------------------------------
|
||||
|
||||
xup.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
|
||||
if (argv.rif - 5 * argv.xup > 7.138) {
|
||||
console.log('Buy more riffiwobbles');
|
||||
}
|
||||
else {
|
||||
console.log('Sell the xupptumblers');
|
||||
}
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./xup.js --rif=55 --xup=9.52
|
||||
Buy more riffiwobbles
|
||||
|
||||
$ ./xup.js --rif 12 --xup 8.1
|
||||
Sell the xupptumblers
|
||||
|
||||

|
||||
|
||||
But wait! There's more! You can do short options:
|
||||
-------------------------------------------------
|
||||
|
||||
short.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
console.log('(%d,%d)', argv.x, argv.y);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./short.js -x 10 -y 21
|
||||
(10,21)
|
||||
|
||||
And booleans, both long and short (and grouped):
|
||||
----------------------------------
|
||||
|
||||
bool.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var util = require('util');
|
||||
var argv = require('optimist').argv;
|
||||
|
||||
if (argv.s) {
|
||||
util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
|
||||
}
|
||||
console.log(
|
||||
(argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
|
||||
);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./bool.js -s
|
||||
The cat says: meow
|
||||
|
||||
$ ./bool.js -sp
|
||||
The cat says: meow.
|
||||
|
||||
$ ./bool.js -sp --fr
|
||||
Le chat dit: miaou.
|
||||
|
||||
And non-hypenated options too! Just use `argv._`!
|
||||
-------------------------------------------------
|
||||
|
||||
nonopt.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
console.log('(%d,%d)', argv.x, argv.y);
|
||||
console.log(argv._);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./nonopt.js -x 6.82 -y 3.35 moo
|
||||
(6.82,3.35)
|
||||
[ 'moo' ]
|
||||
|
||||
$ ./nonopt.js foo -x 0.54 bar -y 1.12 baz
|
||||
(0.54,1.12)
|
||||
[ 'foo', 'bar', 'baz' ]
|
||||
|
||||
Plus, Optimist comes with .usage() and .demand()!
|
||||
-------------------------------------------------
|
||||
|
||||
divide.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.usage('Usage: $0 -x [num] -y [num]')
|
||||
.demand(['x','y'])
|
||||
.argv;
|
||||
|
||||
console.log(argv.x / argv.y);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./divide.js -x 55 -y 11
|
||||
5
|
||||
|
||||
$ node ./divide.js -x 4.91 -z 2.51
|
||||
Usage: node ./divide.js -x [num] -y [num]
|
||||
|
||||
Options:
|
||||
-x [required]
|
||||
-y [required]
|
||||
|
||||
Missing required arguments: y
|
||||
|
||||
EVEN MORE HOLY COW
|
||||
------------------
|
||||
|
||||
default_singles.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.default('x', 10)
|
||||
.default('y', 10)
|
||||
.argv
|
||||
;
|
||||
console.log(argv.x + argv.y);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./default_singles.js -x 5
|
||||
15
|
||||
|
||||
default_hash.js:
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.default({ x : 10, y : 10 })
|
||||
.argv
|
||||
;
|
||||
console.log(argv.x + argv.y);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./default_hash.js -y 7
|
||||
17
|
||||
|
||||
And if you really want to get all descriptive about it...
|
||||
---------------------------------------------------------
|
||||
|
||||
boolean_single.js
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.boolean('v')
|
||||
.argv
|
||||
;
|
||||
console.dir(argv);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./boolean_single.js -v foo bar baz
|
||||
true
|
||||
[ 'bar', 'baz', 'foo' ]
|
||||
|
||||
boolean_double.js
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.boolean(['x','y','z'])
|
||||
.argv
|
||||
;
|
||||
console.dir([ argv.x, argv.y, argv.z ]);
|
||||
console.dir(argv._);
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ ./boolean_double.js -x -z one two three
|
||||
[ true, false, true ]
|
||||
[ 'one', 'two', 'three' ]
|
||||
|
||||
Optimist is here to help...
|
||||
---------------------------
|
||||
|
||||
You can describe parameters for help messages and set aliases. Optimist figures
|
||||
out how to format a handy help string automatically.
|
||||
|
||||
line_count.js
|
||||
|
||||
````javascript
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.usage('Count the lines in a file.\nUsage: $0')
|
||||
.demand('f')
|
||||
.alias('f', 'file')
|
||||
.describe('f', 'Load a file')
|
||||
.argv
|
||||
;
|
||||
|
||||
var fs = require('fs');
|
||||
var s = fs.createReadStream(argv.file);
|
||||
|
||||
var lines = 0;
|
||||
s.on('data', function (buf) {
|
||||
lines += buf.toString().match(/\n/g).length;
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log(lines);
|
||||
});
|
||||
````
|
||||
|
||||
***
|
||||
|
||||
$ node line_count.js
|
||||
Count the lines in a file.
|
||||
Usage: node ./line_count.js
|
||||
|
||||
Options:
|
||||
-f, --file Load a file [required]
|
||||
|
||||
Missing required arguments: f
|
||||
|
||||
$ node line_count.js --file line_count.js
|
||||
20
|
||||
|
||||
$ node line_count.js -f line_count.js
|
||||
20
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
By itself,
|
||||
|
||||
````javascript
|
||||
require('optimist').argv
|
||||
`````
|
||||
|
||||
will use `process.argv` array to construct the `argv` object.
|
||||
|
||||
You can pass in the `process.argv` yourself:
|
||||
|
||||
````javascript
|
||||
require('optimist')([ '-x', '1', '-y', '2' ]).argv
|
||||
````
|
||||
|
||||
or use .parse() to do the same thing:
|
||||
|
||||
````javascript
|
||||
require('optimist').parse([ '-x', '1', '-y', '2' ])
|
||||
````
|
||||
|
||||
The rest of these methods below come in just before the terminating `.argv`.
|
||||
|
||||
.alias(key, alias)
|
||||
------------------
|
||||
|
||||
Set key names as equivalent such that updates to a key will propagate to aliases
|
||||
and vice-versa.
|
||||
|
||||
Optionally `.alias()` can take an object that maps keys to aliases.
|
||||
|
||||
.default(key, value)
|
||||
--------------------
|
||||
|
||||
Set `argv[key]` to `value` if no option was specified on `process.argv`.
|
||||
|
||||
Optionally `.default()` can take an object that maps keys to default values.
|
||||
|
||||
.demand(key)
|
||||
------------
|
||||
|
||||
If `key` is a string, show the usage information and exit if `key` wasn't
|
||||
specified in `process.argv`.
|
||||
|
||||
If `key` is a number, demand at least as many non-option arguments, which show
|
||||
up in `argv._`.
|
||||
|
||||
If `key` is an Array, demand each element.
|
||||
|
||||
.describe(key, desc)
|
||||
--------------------
|
||||
|
||||
Describe a `key` for the generated usage information.
|
||||
|
||||
Optionally `.describe()` can take an object that maps keys to descriptions.
|
||||
|
||||
.options(key, opt)
|
||||
------------------
|
||||
|
||||
Instead of chaining together `.alias().demand().default()`, you can specify
|
||||
keys in `opt` for each of the chainable methods.
|
||||
|
||||
For example:
|
||||
|
||||
````javascript
|
||||
var argv = require('optimist')
|
||||
.options('f', {
|
||||
alias : 'file',
|
||||
default : '/etc/passwd',
|
||||
})
|
||||
.argv
|
||||
;
|
||||
````
|
||||
|
||||
is the same as
|
||||
|
||||
````javascript
|
||||
var argv = require('optimist')
|
||||
.alias('f', 'file')
|
||||
.default('f', '/etc/passwd')
|
||||
.argv
|
||||
;
|
||||
````
|
||||
|
||||
Optionally `.options()` can take an object that maps keys to `opt` parameters.
|
||||
|
||||
.usage(message)
|
||||
---------------
|
||||
|
||||
Set a usage message to show which commands to use. Inside `message`, the string
|
||||
`$0` will get interpolated to the current script name or node command for the
|
||||
present script similar to how `$0` works in bash or perl.
|
||||
|
||||
.check(fn)
|
||||
----------
|
||||
|
||||
Check that certain conditions are met in the provided arguments.
|
||||
|
||||
If `fn` throws or returns `false`, show the thrown error, usage information, and
|
||||
exit.
|
||||
|
||||
.boolean(key)
|
||||
-------------
|
||||
|
||||
Interpret `key` as a boolean. If a non-flag option follows `key` in
|
||||
`process.argv`, that string won't get set as the value of `key`.
|
||||
|
||||
If `key` never shows up as a flag in `process.arguments`, `argv[key]` will be
|
||||
`false`.
|
||||
|
||||
If `key` is an Array, interpret all the elements as booleans.
|
||||
|
||||
.string(key)
|
||||
------------
|
||||
|
||||
Tell the parser logic not to interpret `key` as a number or boolean.
|
||||
This can be useful if you need to preserve leading zeros in an input.
|
||||
|
||||
If `key` is an Array, interpret all the elements as strings.
|
||||
|
||||
.wrap(columns)
|
||||
--------------
|
||||
|
||||
Format usage output to wrap at `columns` many columns.
|
||||
|
||||
.help()
|
||||
-------
|
||||
|
||||
Return the generated usage string.
|
||||
|
||||
.showHelp(fn=console.error)
|
||||
---------------------------
|
||||
|
||||
Print the usage data using `fn` for printing.
|
||||
|
||||
.parse(args)
|
||||
------------
|
||||
|
||||
Parse `args` instead of `process.argv`. Returns the `argv` object.
|
||||
|
||||
.argv
|
||||
-----
|
||||
|
||||
Get the arguments as a plain old object.
|
||||
|
||||
Arguments without a corresponding flag show up in the `argv._` array.
|
||||
|
||||
The script name or node command is available at `argv.$0` similarly to how `$0`
|
||||
works in bash or perl.
|
||||
|
||||
parsing tricks
|
||||
==============
|
||||
|
||||
stop parsing
|
||||
------------
|
||||
|
||||
Use `--` to stop parsing flags and stuff the remainder into `argv._`.
|
||||
|
||||
$ node examples/reflect.js -a 1 -b 2 -- -c 3 -d 4
|
||||
{ _: [ '-c', '3', '-d', '4' ],
|
||||
'$0': 'node ./examples/reflect.js',
|
||||
a: 1,
|
||||
b: 2 }
|
||||
|
||||
negate fields
|
||||
-------------
|
||||
|
||||
If you want to explicity set a field to false instead of just leaving it
|
||||
undefined or to override a default you can do `--no-key`.
|
||||
|
||||
$ node examples/reflect.js -a --no-b
|
||||
{ _: [],
|
||||
'$0': 'node ./examples/reflect.js',
|
||||
a: true,
|
||||
b: false }
|
||||
|
||||
numbers
|
||||
-------
|
||||
|
||||
Every argument that looks like a number (`!isNaN(Number(arg))`) is converted to
|
||||
one. This way you can just `net.createConnection(argv.port)` and you can add
|
||||
numbers out of `argv` with `+` without having that mean concatenation,
|
||||
which is super frustrating.
|
||||
|
||||
duplicates
|
||||
----------
|
||||
|
||||
If you specify a flag multiple times it will get turned into an array containing
|
||||
all the values in order.
|
||||
|
||||
$ node examples/reflect.js -x 5 -x 8 -x 0
|
||||
{ _: [],
|
||||
'$0': 'node ./examples/reflect.js',
|
||||
x: [ 5, 8, 0 ] }
|
||||
|
||||
installation
|
||||
============
|
||||
|
||||
With [npm](http://github.com/isaacs/npm), just do:
|
||||
npm install optimist
|
||||
|
||||
or clone this project on github:
|
||||
|
||||
git clone http://github.com/substack/node-optimist.git
|
||||
|
||||
To run the tests with [expresso](http://github.com/visionmedia/expresso),
|
||||
just do:
|
||||
|
||||
expresso
|
||||
|
||||
inspired By
|
||||
===========
|
||||
|
||||
This module is loosely inspired by Perl's
|
||||
[Getopt::Casual](http://search.cpan.org/~photo/Getopt-Casual-0.13.1/Casual.pm).
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var util = require('util');
|
||||
var argv = require('optimist').argv;
|
||||
|
||||
if (argv.s) {
|
||||
util.print(argv.fr ? 'Le chat dit: ' : 'The cat says: ');
|
||||
}
|
||||
console.log(
|
||||
(argv.fr ? 'miaou' : 'meow') + (argv.p ? '.' : '')
|
||||
);
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.boolean(['x','y','z'])
|
||||
.argv
|
||||
;
|
||||
console.dir([ argv.x, argv.y, argv.z ]);
|
||||
console.dir(argv._);
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.boolean('v')
|
||||
.argv
|
||||
;
|
||||
console.dir(argv.v);
|
||||
console.dir(argv._);
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var argv = require('optimist')
|
||||
.default({ x : 10, y : 10 })
|
||||
.argv
|
||||
;
|
||||
|
||||
console.log(argv.x + argv.y);
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.default('x', 10)
|
||||
.default('y', 10)
|
||||
.argv
|
||||
;
|
||||
console.log(argv.x + argv.y);
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var argv = require('optimist')
|
||||
.usage('Usage: $0 -x [num] -y [num]')
|
||||
.demand(['x','y'])
|
||||
.argv;
|
||||
|
||||
console.log(argv.x / argv.y);
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.usage('Count the lines in a file.\nUsage: $0')
|
||||
.demand('f')
|
||||
.alias('f', 'file')
|
||||
.describe('f', 'Load a file')
|
||||
.argv
|
||||
;
|
||||
|
||||
var fs = require('fs');
|
||||
var s = fs.createReadStream(argv.file);
|
||||
|
||||
var lines = 0;
|
||||
s.on('data', function (buf) {
|
||||
lines += buf.toString().match(/\n/g).length;
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log(lines);
|
||||
});
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.usage('Count the lines in a file.\nUsage: $0')
|
||||
.options({
|
||||
file : {
|
||||
demand : true,
|
||||
alias : 'f',
|
||||
description : 'Load a file'
|
||||
},
|
||||
base : {
|
||||
alias : 'b',
|
||||
description : 'Numeric base to use for output',
|
||||
default : 10,
|
||||
},
|
||||
})
|
||||
.argv
|
||||
;
|
||||
|
||||
var fs = require('fs');
|
||||
var s = fs.createReadStream(argv.file);
|
||||
|
||||
var lines = 0;
|
||||
s.on('data', function (buf) {
|
||||
lines += buf.toString().match(/\n/g).length;
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log(lines.toString(argv.base));
|
||||
});
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.usage('Count the lines in a file.\nUsage: $0')
|
||||
.wrap(80)
|
||||
.demand('f')
|
||||
.alias('f', [ 'file', 'filename' ])
|
||||
.describe('f',
|
||||
"Load a file. It's pretty important."
|
||||
+ " Required even. So you'd better specify it."
|
||||
)
|
||||
.alias('b', 'base')
|
||||
.describe('b', 'Numeric base to display the number of lines in')
|
||||
.default('b', 10)
|
||||
.describe('x', 'Super-secret optional parameter which is secret')
|
||||
.default('x', '')
|
||||
.argv
|
||||
;
|
||||
|
||||
var fs = require('fs');
|
||||
var s = fs.createReadStream(argv.file);
|
||||
|
||||
var lines = 0;
|
||||
s.on('data', function (buf) {
|
||||
lines += buf.toString().match(/\n/g).length;
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log(lines.toString(argv.base));
|
||||
});
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
console.log('(%d,%d)', argv.x, argv.y);
|
||||
console.log(argv._);
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
console.dir(require('optimist').argv);
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
console.log('(%d,%d)', argv.x, argv.y);
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist')
|
||||
.string('x', 'y')
|
||||
.argv
|
||||
;
|
||||
console.dir([ argv.x, argv.y ]);
|
||||
|
||||
/* Turns off numeric coercion:
|
||||
./node string.js -x 000123 -y 9876
|
||||
[ '000123', '9876' ]
|
||||
*/
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
var optimist = require('./../index');
|
||||
|
||||
var argv = optimist.usage('This is my awesome program', {
|
||||
'about': {
|
||||
description: 'Provide some details about the author of this program',
|
||||
required: true,
|
||||
short: 'a',
|
||||
},
|
||||
'info': {
|
||||
description: 'Provide some information about the node.js agains!!!!!!',
|
||||
boolean: true,
|
||||
short: 'i'
|
||||
}
|
||||
}).argv;
|
||||
|
||||
optimist.showHelp();
|
||||
|
||||
console.log('\n\nInspecting options');
|
||||
console.dir(argv);
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('optimist').argv;
|
||||
|
||||
if (argv.rif - 5 * argv.xup > 7.138) {
|
||||
console.log('Buy more riffiwobbles');
|
||||
}
|
||||
else {
|
||||
console.log('Sell the xupptumblers');
|
||||
}
|
||||
|
||||
-457
@@ -1,457 +0,0 @@
|
||||
var path = require('path');
|
||||
var wordwrap = require('wordwrap');
|
||||
|
||||
/* Hack an instance of Argv with process.argv into Argv
|
||||
so people can do
|
||||
require('optimist')(['--beeble=1','-z','zizzle']).argv
|
||||
to parse a list of args and
|
||||
require('optimist').argv
|
||||
to get a parsed version of process.argv.
|
||||
*/
|
||||
|
||||
var inst = Argv(process.argv.slice(2));
|
||||
Object.keys(inst).forEach(function (key) {
|
||||
Argv[key] = typeof inst[key] == 'function'
|
||||
? inst[key].bind(inst)
|
||||
: inst[key];
|
||||
});
|
||||
|
||||
var exports = module.exports = Argv;
|
||||
function Argv (args, cwd) {
|
||||
var self = {};
|
||||
if (!cwd) cwd = process.cwd();
|
||||
|
||||
self.$0 = process.argv
|
||||
.slice(0,2)
|
||||
.map(function (x) {
|
||||
var b = rebase(cwd, x);
|
||||
return x.match(/^\//) && b.length < x.length
|
||||
? b : x
|
||||
})
|
||||
.join(' ')
|
||||
;
|
||||
|
||||
if (process.argv[1] == process.env._) {
|
||||
self.$0 = process.env._.replace(
|
||||
path.dirname(process.execPath) + '/', ''
|
||||
);
|
||||
}
|
||||
|
||||
var flags = { bools : {}, strings : {} };
|
||||
|
||||
self.boolean = function (bools) {
|
||||
if (!Array.isArray(bools)) {
|
||||
bools = [].slice.call(arguments);
|
||||
}
|
||||
|
||||
bools.forEach(function (name) {
|
||||
flags.bools[name] = true;
|
||||
});
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
self.string = function (strings) {
|
||||
if (!Array.isArray(strings)) {
|
||||
strings = [].slice.call(arguments);
|
||||
}
|
||||
|
||||
strings.forEach(function (name) {
|
||||
flags.strings[name] = true;
|
||||
});
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
var aliases = {};
|
||||
self.alias = function (x, y) {
|
||||
if (typeof x === 'object') {
|
||||
Object.keys(x).forEach(function (key) {
|
||||
self.alias(key, x[key]);
|
||||
});
|
||||
}
|
||||
else if (Array.isArray(y)) {
|
||||
y.forEach(function (yy) {
|
||||
self.alias(x, yy);
|
||||
});
|
||||
}
|
||||
else {
|
||||
var zs = (aliases[x] || []).concat(aliases[y] || []).concat(x, y);
|
||||
aliases[x] = zs.filter(function (z) { return z != x });
|
||||
aliases[y] = zs.filter(function (z) { return z != y });
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
var demanded = {};
|
||||
self.demand = function (keys) {
|
||||
if (typeof keys == 'number') {
|
||||
if (!demanded._) demanded._ = 0;
|
||||
demanded._ += keys;
|
||||
}
|
||||
else if (Array.isArray(keys)) {
|
||||
keys.forEach(function (key) {
|
||||
self.demand(key);
|
||||
});
|
||||
}
|
||||
else {
|
||||
demanded[keys] = true;
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
var usage;
|
||||
self.usage = function (msg, opts) {
|
||||
if (!opts && typeof msg === 'object') {
|
||||
opts = msg;
|
||||
msg = null;
|
||||
}
|
||||
|
||||
usage = msg;
|
||||
|
||||
if (opts) self.options(opts);
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
function fail (msg) {
|
||||
self.showHelp();
|
||||
if (msg) console.error(msg);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var checks = [];
|
||||
self.check = function (f) {
|
||||
checks.push(f);
|
||||
return self;
|
||||
};
|
||||
|
||||
var defaults = {};
|
||||
self.default = function (key, value) {
|
||||
if (typeof key === 'object') {
|
||||
Object.keys(key).forEach(function (k) {
|
||||
self.default(k, key[k]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
defaults[key] = value;
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
var descriptions = {};
|
||||
self.describe = function (key, desc) {
|
||||
if (typeof key === 'object') {
|
||||
Object.keys(key).forEach(function (k) {
|
||||
self.describe(k, key[k]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
descriptions[key] = desc;
|
||||
}
|
||||
return self;
|
||||
};
|
||||
|
||||
self.parse = function (args) {
|
||||
return Argv(args).argv;
|
||||
};
|
||||
|
||||
self.option = self.options = function (key, opt) {
|
||||
if (typeof key === 'object') {
|
||||
Object.keys(key).forEach(function (k) {
|
||||
self.options(k, key[k]);
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (opt.alias) self.alias(key, opt.alias);
|
||||
if (opt.demand) self.demand(key);
|
||||
if (opt.default) self.default(key, opt.default);
|
||||
|
||||
if (opt.boolean || opt.type === 'boolean') {
|
||||
self.boolean(key);
|
||||
}
|
||||
if (opt.string || opt.type === 'string') {
|
||||
self.string(key);
|
||||
}
|
||||
|
||||
var desc = opt.describe || opt.description || opt.desc;
|
||||
if (desc) {
|
||||
self.describe(key, desc);
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
var wrap = null;
|
||||
self.wrap = function (cols) {
|
||||
wrap = cols;
|
||||
return self;
|
||||
};
|
||||
|
||||
self.showHelp = function (fn) {
|
||||
if (!fn) fn = console.error;
|
||||
fn(self.help());
|
||||
};
|
||||
|
||||
self.help = function () {
|
||||
var keys = Object.keys(
|
||||
Object.keys(descriptions)
|
||||
.concat(Object.keys(demanded))
|
||||
.concat(Object.keys(defaults))
|
||||
.reduce(function (acc, key) {
|
||||
if (key !== '_') acc[key] = true;
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
|
||||
var help = keys.length ? [ 'Options:' ] : [];
|
||||
|
||||
if (usage) {
|
||||
help.unshift(usage.replace(/\$0/g, self.$0), '');
|
||||
}
|
||||
|
||||
var switches = keys.reduce(function (acc, key) {
|
||||
acc[key] = [ key ].concat(aliases[key] || [])
|
||||
.map(function (sw) {
|
||||
return (sw.length > 1 ? '--' : '-') + sw
|
||||
})
|
||||
.join(', ')
|
||||
;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
var switchlen = longest(Object.keys(switches).map(function (s) {
|
||||
return switches[s] || '';
|
||||
}));
|
||||
|
||||
var desclen = longest(Object.keys(descriptions).map(function (d) {
|
||||
return descriptions[d] || '';
|
||||
}));
|
||||
|
||||
keys.forEach(function (key) {
|
||||
var kswitch = switches[key];
|
||||
var desc = descriptions[key] || '';
|
||||
|
||||
if (wrap) {
|
||||
desc = wordwrap(switchlen + 4, wrap)(desc)
|
||||
.slice(switchlen + 4)
|
||||
;
|
||||
}
|
||||
|
||||
var spadding = new Array(
|
||||
Math.max(switchlen - kswitch.length + 3, 0)
|
||||
).join(' ');
|
||||
|
||||
var dpadding = new Array(
|
||||
Math.max(desclen - desc.length + 1, 0)
|
||||
).join(' ');
|
||||
|
||||
var type = null;
|
||||
|
||||
if (flags.bools[key]) type = '[boolean]';
|
||||
if (flags.strings[key]) type = '[string]';
|
||||
|
||||
if (!wrap && dpadding.length > 0) {
|
||||
desc += dpadding;
|
||||
}
|
||||
|
||||
var prelude = ' ' + kswitch + spadding;
|
||||
var extra = [
|
||||
type,
|
||||
demanded[key]
|
||||
? '[required]'
|
||||
: null
|
||||
,
|
||||
defaults[key] !== undefined
|
||||
? '[default: ' + JSON.stringify(defaults[key]) + ']'
|
||||
: null
|
||||
,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
var body = [ desc, extra ].filter(Boolean).join(' ');
|
||||
|
||||
if (wrap) {
|
||||
var dlines = desc.split('\n');
|
||||
var dlen = dlines.slice(-1)[0].length
|
||||
+ (dlines.length === 1 ? prelude.length : 0)
|
||||
|
||||
body = desc + (dlen + extra.length > wrap - 2
|
||||
? '\n'
|
||||
+ new Array(wrap - extra.length + 1).join(' ')
|
||||
+ extra
|
||||
: new Array(wrap - extra.length - dlen + 1).join(' ')
|
||||
+ extra
|
||||
);
|
||||
}
|
||||
|
||||
help.push(prelude + body);
|
||||
});
|
||||
|
||||
help.push('');
|
||||
return help.join('\n');
|
||||
};
|
||||
|
||||
Object.defineProperty(self, 'argv', {
|
||||
get : parseArgs,
|
||||
enumerable : true,
|
||||
});
|
||||
|
||||
function parseArgs () {
|
||||
var argv = { _ : [], $0 : self.$0 };
|
||||
Object.keys(flags.bools).forEach(function (key) {
|
||||
setArg(key, defaults[key] || false);
|
||||
});
|
||||
|
||||
function setArg (key, val) {
|
||||
var num = Number(val);
|
||||
var value = typeof val !== 'string' || isNaN(num) ? val : num;
|
||||
if (flags.strings[key]) value = val;
|
||||
|
||||
if (key in argv && !flags.bools[key]) {
|
||||
if (!Array.isArray(argv[key])) {
|
||||
argv[key] = [ argv[key] ];
|
||||
}
|
||||
argv[key].push(value);
|
||||
}
|
||||
else {
|
||||
argv[key] = value;
|
||||
}
|
||||
|
||||
(aliases[key] || []).forEach(function (x) {
|
||||
argv[x] = argv[key];
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
|
||||
if (arg === '--') {
|
||||
argv._.push.apply(argv._, args.slice(i + 1));
|
||||
break;
|
||||
}
|
||||
else if (arg.match(/^--.+=/)) {
|
||||
var m = arg.match(/^--([^=]+)=(.*)/);
|
||||
setArg(m[1], m[2]);
|
||||
}
|
||||
else if (arg.match(/^--no-.+/)) {
|
||||
var key = arg.match(/^--no-(.+)/)[1];
|
||||
setArg(key, false);
|
||||
}
|
||||
else if (arg.match(/^--.+/)) {
|
||||
var key = arg.match(/^--(.+)/)[1];
|
||||
var next = args[i + 1];
|
||||
if (next !== undefined && !next.match(/^-/)
|
||||
&& !flags.bools[key]) {
|
||||
setArg(key, next);
|
||||
i++;
|
||||
}
|
||||
else if (flags.bools[key] && /true|false/.test(next)) {
|
||||
setArg(key, next === 'true');
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
setArg(key, true);
|
||||
}
|
||||
}
|
||||
else if (arg.match(/^-[^-]+/)) {
|
||||
var letters = arg.slice(1,-1).split('');
|
||||
|
||||
var broken = false;
|
||||
for (var j = 0; j < letters.length; j++) {
|
||||
if (letters[j+1] && letters[j+1].match(/\W/)) {
|
||||
setArg(letters[j], arg.slice(j+2));
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
setArg(letters[j], true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!broken) {
|
||||
var key = arg.slice(-1)[0];
|
||||
|
||||
if (args[i+1] && !args[i+1].match(/^-/)
|
||||
&& !flags.bools[key]) {
|
||||
setArg(key, args[i+1]);
|
||||
i++;
|
||||
}
|
||||
else if (args[i+1] && flags.bools[key] && /true|false/.test(args[i+1])) {
|
||||
setArg(key, args[i+1] === 'true');
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
setArg(key, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var n = Number(arg);
|
||||
argv._.push(flags.strings['_'] || isNaN(n) ? arg : n);
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(defaults).forEach(function (key) {
|
||||
if (!(key in argv)) {
|
||||
argv[key] = defaults[key];
|
||||
}
|
||||
});
|
||||
|
||||
if (demanded._ && argv._.length < demanded._) {
|
||||
fail('Not enough non-option arguments: got '
|
||||
+ argv._.length + ', need at least ' + demanded._
|
||||
);
|
||||
}
|
||||
|
||||
var missing = [];
|
||||
Object.keys(demanded).forEach(function (key) {
|
||||
if (!argv[key]) missing.push(key);
|
||||
});
|
||||
|
||||
if (missing.length) {
|
||||
fail('Missing required arguments: ' + missing.join(', '));
|
||||
}
|
||||
|
||||
checks.forEach(function (f) {
|
||||
try {
|
||||
if (f(argv) === false) {
|
||||
fail('Argument check failed: ' + f.toString());
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
fail(err)
|
||||
}
|
||||
});
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
function longest (xs) {
|
||||
return Math.max.apply(
|
||||
null,
|
||||
xs.map(function (x) { return x.length })
|
||||
);
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
// rebase an absolute path to a relative one with respect to a base directory
|
||||
// exported for tests
|
||||
exports.rebase = rebase;
|
||||
function rebase (base, dir) {
|
||||
var ds = path.normalize(dir).split('/').slice(1);
|
||||
var bs = path.normalize(base).split('/').slice(1);
|
||||
|
||||
for (var i = 0; ds[i] && ds[i] == bs[i]; i++);
|
||||
ds.splice(0, i); bs.splice(0, i);
|
||||
|
||||
var p = path.normalize(
|
||||
bs.map(function () { return '..' }).concat(ds).join('/')
|
||||
).replace(/\/$/,'').replace(/^$/, '.');
|
||||
return p.match(/^[.\/]/) ? p : './' + p;
|
||||
};
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"name" : "optimist",
|
||||
"version" : "0.2.8",
|
||||
"description" : "Light-weight option parsing with an argv hash. No optstrings attached.",
|
||||
"main" : "./index.js",
|
||||
"directories" : {
|
||||
"lib" : ".",
|
||||
"test" : "test",
|
||||
"example" : "examples"
|
||||
},
|
||||
"dependencies" : {
|
||||
"wordwrap" : ">=0.0.1 <0.1.0"
|
||||
},
|
||||
"devDependencies" : {
|
||||
"hashish": "0.0.x",
|
||||
"expresso" : "0.7.x"
|
||||
},
|
||||
"scripts" : {
|
||||
"test" : "expresso"
|
||||
},
|
||||
"repository" : {
|
||||
"type" : "git",
|
||||
"url" : "http://github.com/substack/node-optimist.git"
|
||||
},
|
||||
"keywords" : [
|
||||
"argument",
|
||||
"args",
|
||||
"option",
|
||||
"parser",
|
||||
"parsing",
|
||||
"cli",
|
||||
"command"
|
||||
],
|
||||
"author" : {
|
||||
"name" : "James Halliday",
|
||||
"email" : "mail@substack.net",
|
||||
"url" : "http://substack.net"
|
||||
},
|
||||
"license" : "MIT/X11",
|
||||
"engine" : {
|
||||
"node" : ">=0.4"
|
||||
}
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
var spawn = require('child_process').spawn;
|
||||
var assert = require('assert');
|
||||
|
||||
exports.dotSlashEmpty = function () {
|
||||
testCmd('./bin.js', []);
|
||||
};
|
||||
|
||||
exports.dotSlashArgs = function () {
|
||||
testCmd('./bin.js', [ 'a', 'b', 'c' ]);
|
||||
};
|
||||
|
||||
exports.nodeEmpty = function () {
|
||||
testCmd('node bin.js', []);
|
||||
};
|
||||
|
||||
exports.nodeArgs = function () {
|
||||
testCmd('node bin.js', [ 'x', 'y', 'z' ]);
|
||||
};
|
||||
|
||||
exports.whichNodeEmpty = function () {
|
||||
var which = spawn('which', ['node']);
|
||||
|
||||
which.stdout.on('data', function (buf) {
|
||||
testCmd(buf.toString().trim() + ' bin.js', []);
|
||||
});
|
||||
|
||||
which.stderr.on('data', function (err) {
|
||||
assert.fail(err.toString());
|
||||
});
|
||||
};
|
||||
|
||||
exports.whichNodeArgs = function () {
|
||||
var which = spawn('which', ['node']);
|
||||
|
||||
which.stdout.on('data', function (buf) {
|
||||
testCmd(buf.toString().trim() + ' bin.js', [ 'q', 'r' ]);
|
||||
});
|
||||
|
||||
which.stderr.on('data', function (err) {
|
||||
assert.fail(err.toString());
|
||||
});
|
||||
};
|
||||
|
||||
function testCmd (cmd, args) {
|
||||
var to = setTimeout(function () {
|
||||
assert.fail('Never got stdout data.')
|
||||
}, 5000);
|
||||
|
||||
var oldDir = process.cwd();
|
||||
process.chdir(__dirname + '/_');
|
||||
|
||||
var cmds = cmd.split(' ');
|
||||
|
||||
var bin = spawn(cmds[0], cmds.slice(1).concat(args.map(String)));
|
||||
process.chdir(oldDir);
|
||||
|
||||
bin.stderr.on('data', function (err) {
|
||||
assert.fail(err.toString());
|
||||
});
|
||||
|
||||
bin.stdout.on('data', function (buf) {
|
||||
clearTimeout(to);
|
||||
var _ = JSON.parse(buf.toString());
|
||||
assert.eql(_.map(String), args.map(String));
|
||||
});
|
||||
}
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
console.log(JSON.stringify(process.argv));
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
var argv = require('../../index').argv
|
||||
console.log(JSON.stringify(argv._));
|
||||
-304
@@ -1,304 +0,0 @@
|
||||
var optimist = require('../index');
|
||||
var assert = require('assert');
|
||||
var path = require('path');
|
||||
|
||||
var localExpresso = path.normalize(
|
||||
__dirname + '/../node_modules/.bin/expresso'
|
||||
);
|
||||
|
||||
var expresso = process.argv[1] === localExpresso
|
||||
? 'node ./node_modules/.bin/expresso'
|
||||
: 'expresso'
|
||||
;
|
||||
|
||||
exports['short boolean'] = function () {
|
||||
var parse = optimist.parse([ '-b' ]);
|
||||
assert.eql(parse, { b : true, _ : [], $0 : expresso });
|
||||
assert.eql(typeof parse.b, 'boolean');
|
||||
};
|
||||
|
||||
exports['long boolean'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--bool' ]),
|
||||
{ bool : true, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports.bare = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ 'foo', 'bar', 'baz' ]),
|
||||
{ _ : [ 'foo', 'bar', 'baz' ], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['short group'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-cats' ]),
|
||||
{ c : true, a : true, t : true, s : true, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['short group next'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-cats', 'meow' ]),
|
||||
{ c : true, a : true, t : true, s : 'meow', _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['short capture'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-h', 'localhost' ]),
|
||||
{ h : 'localhost', _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['short captures'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-h', 'localhost', '-p', '555' ]),
|
||||
{ h : 'localhost', p : 555, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['long capture sp'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--pow', 'xixxle' ]),
|
||||
{ pow : 'xixxle', _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['long capture eq'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--pow=xixxle' ]),
|
||||
{ pow : 'xixxle', _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['long captures sp'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--host', 'localhost', '--port', '555' ]),
|
||||
{ host : 'localhost', port : 555, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['long captures eq'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--host=localhost', '--port=555' ]),
|
||||
{ host : 'localhost', port : 555, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports['mixed short bool and capture'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
|
||||
{
|
||||
f : true, p : 555, h : 'localhost',
|
||||
_ : [ 'script.js' ], $0 : expresso,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports['short and long'] = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
|
||||
{
|
||||
f : true, p : 555, h : 'localhost',
|
||||
_ : [ 'script.js' ], $0 : expresso,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.no = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '--no-moo' ]),
|
||||
{ moo : false, _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports.multi = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
|
||||
{ v : ['a','b','c'], _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports.comprehensive = function () {
|
||||
assert.eql(
|
||||
optimist.parse([
|
||||
'--name=meowmers', 'bare', '-cats', 'woo',
|
||||
'-h', 'awesome', '--multi=quux',
|
||||
'--key', 'value',
|
||||
'-b', '--bool', '--no-meep', '--multi=baz',
|
||||
'--', '--not-a-flag', 'eek'
|
||||
]),
|
||||
{
|
||||
c : true,
|
||||
a : true,
|
||||
t : true,
|
||||
s : 'woo',
|
||||
h : 'awesome',
|
||||
b : true,
|
||||
bool : true,
|
||||
key : 'value',
|
||||
multi : [ 'quux', 'baz' ],
|
||||
meep : false,
|
||||
name : 'meowmers',
|
||||
_ : [ 'bare', '--not-a-flag', 'eek' ],
|
||||
$0 : expresso
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.nums = function () {
|
||||
var argv = optimist.parse([
|
||||
'-x', '1234',
|
||||
'-y', '5.67',
|
||||
'-z', '1e7',
|
||||
'-w', '10f',
|
||||
'--hex', '0xdeadbeef',
|
||||
'789',
|
||||
]);
|
||||
assert.eql(argv, {
|
||||
x : 1234,
|
||||
y : 5.67,
|
||||
z : 1e7,
|
||||
w : '10f',
|
||||
hex : 0xdeadbeef,
|
||||
_ : [ 789 ],
|
||||
$0 : expresso
|
||||
});
|
||||
assert.eql(typeof argv.x, 'number');
|
||||
assert.eql(typeof argv.y, 'number');
|
||||
assert.eql(typeof argv.z, 'number');
|
||||
assert.eql(typeof argv.w, 'string');
|
||||
assert.eql(typeof argv.hex, 'number');
|
||||
assert.eql(typeof argv._[0], 'number');
|
||||
};
|
||||
|
||||
exports['flag boolean'] = function () {
|
||||
var parse = optimist([ '-t', 'moo' ]).boolean(['t']).argv;
|
||||
assert.eql(parse, { t : true, _ : [ 'moo' ], $0 : expresso });
|
||||
assert.eql(typeof parse.t, 'boolean');
|
||||
};
|
||||
|
||||
exports['flag boolean value'] = function () {
|
||||
var parse = optimist(['--verbose', 'false', 'moo', '-t', 'true'])
|
||||
.boolean(['t', 'verbose']).default('verbose', true).argv;
|
||||
|
||||
assert.eql(parse, {
|
||||
verbose: false,
|
||||
t: true,
|
||||
_: ['moo'],
|
||||
$0 : expresso
|
||||
});
|
||||
|
||||
assert.eql(typeof parse.verbose, 'boolean');
|
||||
assert.eql(typeof parse.t, 'boolean');
|
||||
};
|
||||
|
||||
exports['flag boolean default false'] = function () {
|
||||
var parse = optimist(['moo'])
|
||||
.boolean(['t', 'verbose'])
|
||||
.default('verbose', false)
|
||||
.default('t', false).argv;
|
||||
|
||||
assert.eql(parse, {
|
||||
verbose: false,
|
||||
t: false,
|
||||
_: ['moo'],
|
||||
$0 : expresso
|
||||
});
|
||||
|
||||
assert.eql(typeof parse.verbose, 'boolean');
|
||||
assert.eql(typeof parse.t, 'boolean');
|
||||
|
||||
};
|
||||
|
||||
exports['boolean groups'] = function () {
|
||||
var parse = optimist([ '-x', '-z', 'one', 'two', 'three' ])
|
||||
.boolean(['x','y','z']).argv;
|
||||
|
||||
assert.eql(parse, {
|
||||
x : true,
|
||||
y : false,
|
||||
z : true,
|
||||
_ : [ 'one', 'two', 'three' ],
|
||||
$0 : expresso
|
||||
});
|
||||
|
||||
assert.eql(typeof parse.x, 'boolean');
|
||||
assert.eql(typeof parse.y, 'boolean');
|
||||
assert.eql(typeof parse.z, 'boolean');
|
||||
};
|
||||
|
||||
exports.strings = function () {
|
||||
var s = optimist([ '-s', '0001234' ]).string('s').argv.s;
|
||||
assert.eql(s, '0001234');
|
||||
assert.eql(typeof s, 'string');
|
||||
|
||||
var x = optimist([ '-x', '56' ]).string('x').argv.x;
|
||||
assert.eql(x, '56');
|
||||
assert.eql(typeof x, 'string');
|
||||
};
|
||||
|
||||
exports.stringArgs = function () {
|
||||
var s = optimist([ ' ', ' ' ]).string('_').argv._;
|
||||
assert.eql(s.length, 2);
|
||||
assert.eql(typeof s[0], 'string');
|
||||
assert.eql(s[0], ' ');
|
||||
assert.eql(typeof s[1], 'string');
|
||||
assert.eql(s[1], ' ');
|
||||
};
|
||||
|
||||
exports.slashBreak = function () {
|
||||
assert.eql(
|
||||
optimist.parse([ '-I/foo/bar/baz' ]),
|
||||
{ I : '/foo/bar/baz', _ : [], $0 : expresso }
|
||||
);
|
||||
assert.eql(
|
||||
optimist.parse([ '-xyz/foo/bar/baz' ]),
|
||||
{ x : true, y : true, z : '/foo/bar/baz', _ : [], $0 : expresso }
|
||||
);
|
||||
};
|
||||
|
||||
exports.alias = function () {
|
||||
var argv = optimist([ '-f', '11', '--zoom', '55' ])
|
||||
.alias('z', 'zoom')
|
||||
.argv
|
||||
;
|
||||
assert.equal(argv.zoom, 55);
|
||||
assert.equal(argv.z, argv.zoom);
|
||||
assert.equal(argv.f, 11);
|
||||
};
|
||||
|
||||
exports.multiAlias = function () {
|
||||
var argv = optimist([ '-f', '11', '--zoom', '55' ])
|
||||
.alias('z', [ 'zm', 'zoom' ])
|
||||
.argv
|
||||
;
|
||||
assert.equal(argv.zoom, 55);
|
||||
assert.equal(argv.z, argv.zoom);
|
||||
assert.equal(argv.z, argv.zm);
|
||||
assert.equal(argv.f, 11);
|
||||
};
|
||||
|
||||
exports['boolean default true'] = function () {
|
||||
var argv = optimist.options({
|
||||
sometrue: {
|
||||
boolean: true,
|
||||
default: true
|
||||
}
|
||||
}).argv;
|
||||
|
||||
assert.equal(argv.sometrue, true);
|
||||
};
|
||||
|
||||
exports['boolean default false'] = function () {
|
||||
var argv = optimist.options({
|
||||
somefalse: {
|
||||
boolean: true,
|
||||
default: false
|
||||
}
|
||||
}).argv;
|
||||
|
||||
assert.equal(argv.somefalse, false);
|
||||
};
|
||||
-256
@@ -1,256 +0,0 @@
|
||||
var Hash = require('hashish');
|
||||
var optimist = require('../index');
|
||||
var assert = require('assert');
|
||||
|
||||
exports.usageFail = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -z 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.demand(['x','y'])
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(
|
||||
r.result,
|
||||
{ x : 10, z : 20, _ : [], $0 : './usage' }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
r.errors.join('\n').split(/\n+/),
|
||||
[
|
||||
'Usage: ./usage -x NUM -y NUM',
|
||||
'Options:',
|
||||
' -x [required]',
|
||||
' -y [required]',
|
||||
'Missing required arguments: y',
|
||||
]
|
||||
);
|
||||
assert.deepEqual(r.logs, []);
|
||||
assert.ok(r.exit);
|
||||
};
|
||||
|
||||
exports.usagePass = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -y 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.demand(['x','y'])
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(r, {
|
||||
result : { x : 10, y : 20, _ : [], $0 : './usage' },
|
||||
errors : [],
|
||||
logs : [],
|
||||
exit : false,
|
||||
});
|
||||
};
|
||||
|
||||
exports.checkPass = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -y 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.check(function (argv) {
|
||||
if (!('x' in argv)) throw 'You forgot about -x';
|
||||
if (!('y' in argv)) throw 'You forgot about -y';
|
||||
})
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(r, {
|
||||
result : { x : 10, y : 20, _ : [], $0 : './usage' },
|
||||
errors : [],
|
||||
logs : [],
|
||||
exit : false,
|
||||
});
|
||||
};
|
||||
|
||||
exports.checkFail = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -z 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.check(function (argv) {
|
||||
if (!('x' in argv)) throw 'You forgot about -x';
|
||||
if (!('y' in argv)) throw 'You forgot about -y';
|
||||
})
|
||||
.argv;
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
r.result,
|
||||
{ x : 10, z : 20, _ : [], $0 : './usage' }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
r.errors.join('\n').split(/\n+/),
|
||||
[
|
||||
'Usage: ./usage -x NUM -y NUM',
|
||||
'You forgot about -y'
|
||||
]
|
||||
);
|
||||
|
||||
assert.deepEqual(r.logs, []);
|
||||
assert.ok(r.exit);
|
||||
};
|
||||
|
||||
exports.checkCondPass = function () {
|
||||
function checker (argv) {
|
||||
return 'x' in argv && 'y' in argv;
|
||||
}
|
||||
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -y 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.check(checker)
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(r, {
|
||||
result : { x : 10, y : 20, _ : [], $0 : './usage' },
|
||||
errors : [],
|
||||
logs : [],
|
||||
exit : false,
|
||||
});
|
||||
};
|
||||
|
||||
exports.checkCondFail = function () {
|
||||
function checker (argv) {
|
||||
return 'x' in argv && 'y' in argv;
|
||||
}
|
||||
|
||||
var r = checkUsage(function () {
|
||||
return optimist('-x 10 -z 20'.split(' '))
|
||||
.usage('Usage: $0 -x NUM -y NUM')
|
||||
.check(checker)
|
||||
.argv;
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
r.result,
|
||||
{ x : 10, z : 20, _ : [], $0 : './usage' }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
r.errors.join('\n').split(/\n+/).join('\n'),
|
||||
'Usage: ./usage -x NUM -y NUM\n'
|
||||
+ 'Argument check failed: ' + checker.toString()
|
||||
);
|
||||
|
||||
assert.deepEqual(r.logs, []);
|
||||
assert.ok(r.exit);
|
||||
};
|
||||
|
||||
exports.countPass = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('1 2 3 --moo'.split(' '))
|
||||
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
|
||||
.demand(3)
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(r, {
|
||||
result : { _ : [ '1', '2', '3' ], moo : true, $0 : './usage' },
|
||||
errors : [],
|
||||
logs : [],
|
||||
exit : false,
|
||||
});
|
||||
};
|
||||
|
||||
exports.countFail = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('1 2 --moo'.split(' '))
|
||||
.usage('Usage: $0 [x] [y] [z] {OPTIONS}')
|
||||
.demand(3)
|
||||
.argv;
|
||||
});
|
||||
assert.deepEqual(
|
||||
r.result,
|
||||
{ _ : [ '1', '2' ], moo : true, $0 : './usage' }
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
r.errors.join('\n').split(/\n+/),
|
||||
[
|
||||
'Usage: ./usage [x] [y] [z] {OPTIONS}',
|
||||
'Not enough non-option arguments: got 2, need at least 3',
|
||||
]
|
||||
);
|
||||
|
||||
assert.deepEqual(r.logs, []);
|
||||
assert.ok(r.exit);
|
||||
};
|
||||
|
||||
exports.defaultSingles = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('--foo 50 --baz 70 --powsy'.split(' '))
|
||||
.default('foo', 5)
|
||||
.default('bar', 6)
|
||||
.default('baz', 7)
|
||||
.argv
|
||||
;
|
||||
});
|
||||
assert.eql(r.result, {
|
||||
foo : '50',
|
||||
bar : 6,
|
||||
baz : '70',
|
||||
powsy : true,
|
||||
_ : [],
|
||||
$0 : './usage',
|
||||
});
|
||||
};
|
||||
|
||||
exports.defaultHash = function () {
|
||||
var r = checkUsage(function () {
|
||||
return optimist('--foo 50 --baz 70'.split(' '))
|
||||
.default({ foo : 10, bar : 20, quux : 30 })
|
||||
.argv
|
||||
;
|
||||
});
|
||||
assert.eql(r.result, {
|
||||
foo : '50',
|
||||
bar : 20,
|
||||
baz : 70,
|
||||
quux : 30,
|
||||
_ : [],
|
||||
$0 : './usage',
|
||||
});
|
||||
};
|
||||
|
||||
exports.rebase = function () {
|
||||
assert.equal(
|
||||
optimist.rebase('/home/substack', '/home/substack/foo/bar/baz'),
|
||||
'./foo/bar/baz'
|
||||
);
|
||||
assert.equal(
|
||||
optimist.rebase('/home/substack/foo/bar/baz', '/home/substack'),
|
||||
'../../..'
|
||||
);
|
||||
assert.equal(
|
||||
optimist.rebase('/home/substack/foo', '/home/substack/pow/zoom.txt'),
|
||||
'../pow/zoom.txt'
|
||||
);
|
||||
};
|
||||
|
||||
function checkUsage (f) {
|
||||
var _process = process;
|
||||
process = Hash.copy(process);
|
||||
var exit = false;
|
||||
process.exit = function () { exit = true };
|
||||
process.env = Hash.merge(process.env, { _ : 'node' });
|
||||
process.argv = [ './usage' ];
|
||||
|
||||
var errors = [];
|
||||
var logs = [];
|
||||
|
||||
console._error = console.error;
|
||||
console.error = function (msg) { errors.push(msg) };
|
||||
console._log = console.log;
|
||||
console.log = function (msg) { logs.push(msg) };
|
||||
|
||||
var result = f();
|
||||
|
||||
process = _process;
|
||||
console.error = console._error;
|
||||
console.log = console._log;
|
||||
|
||||
return {
|
||||
errors : errors,
|
||||
logs : logs,
|
||||
exit : exit,
|
||||
result : result,
|
||||
};
|
||||
};
|
||||
+41
-7
@@ -1,16 +1,50 @@
|
||||
{
|
||||
"author": "Craig Condon <craig.j.condon@gmail.com>",
|
||||
"author": "Jared Allard <jaredallard@outlook.com>",
|
||||
"name": "nexe",
|
||||
"description": "Roll node.s applications into a single executable",
|
||||
"version": "0.0.1",
|
||||
"description": "create single executables out of your [node/io].js applications",
|
||||
"license": "MIT",
|
||||
"version": "0.4.1",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Criag Condon",
|
||||
"email": "craig.j.condon@gmail.com",
|
||||
"url": "http://crcn.io/"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/crcn/nexe.git"
|
||||
"url": "git://github.com/jaredallard/nexe.git"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"dependencies": {
|
||||
"optimist":"*",
|
||||
"sardines":"*"
|
||||
"async": "1.2.1",
|
||||
"builtins": "1.0.1",
|
||||
"colors": "^1.0.3",
|
||||
"glob": "^5.0.5",
|
||||
"mkdirp": "^0.5.0",
|
||||
"module-deps": "^3.6.4",
|
||||
"ncp": "^2.0.0",
|
||||
"outcome": "0.0.18",
|
||||
"progress": "^1.1.8",
|
||||
"request": "^2.53.0",
|
||||
"sprintf": "~0.1.5",
|
||||
"step": "0.0.x",
|
||||
"tar.gz": "0.1.1",
|
||||
"through": "^2.3.6",
|
||||
"yargs": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {}
|
||||
"nexe": {
|
||||
"input": "./bin/nexe",
|
||||
"output": "nexe^$",
|
||||
"temp": "src",
|
||||
"runtime": {
|
||||
"framework": "iojs",
|
||||
"version": "2.3.1",
|
||||
"ignoreFlags": true
|
||||
}
|
||||
},
|
||||
"preferGlobal": "true",
|
||||
"bin": {
|
||||
"nexe": "./bin/nexe"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"build_systems":
|
||||
[
|
||||
{
|
||||
"name":"cbd make",
|
||||
"cmd":["cbd","make","nexe"]
|
||||
},
|
||||
{
|
||||
"name":"cbd start",
|
||||
"cmd":["cbd","start","nexe"]
|
||||
},
|
||||
{
|
||||
"name":"cbd make+start",
|
||||
"cmd":["cbd","make+start","nexe"]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user