Add sqlite3 modules for tests

This commit is contained in:
Timothy Warren 2014-11-03 10:59:34 -05:00
parent c43e902525
commit 1c449eced0
815 changed files with 101370 additions and 0 deletions

103
node_modules/sqlite3/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,103 @@
# Changelog
## 3.0.2
- Republish for possibly busted npm package.
## 3.0.1
- Use ~ in node-pre-gyp semver for more flexible dep management.
## 3.0.0
Released September 20nd, 2014
- Backwards-incompatible change: node versions 0.8.x are no longer supported.
- Updated to node-pre-gyp@0.5.27
- Updated NAN to 1.3.0
- Updated internal libsqlite3 to v3.8.6
## 2.2.7
Released August 6th, 2014
- Removed usage of `npm ls` with `prepublish` target (which breaks node v0.8.x)
## 2.2.6
Released August 6th, 2014
- Fix bundled version of node-pre-gyp
## 2.2.5
Released August 5th, 2014
- Fix leak in complete() callback of Database.each() (#307)
- Started using `engineStrict` and improved `engines` declaration to make clear only >= 0.11.13 is supported for the 0.11.x series.
## 2.2.4
Released July 14th, 2014
- Now supporting node v0.11.x (specifically >=0.11.13)
- Fix db opening error with absolute path on windows
- Updated to node-pre-gyp@0.5.18
- updated internal libsqlite3 from 3.8.4.3 -> 3.8.5 (http://www.sqlite.org/news.html)
## 2.2.3
- Fixed regression in v2.2.2 for installing from binaries on windows.
## 2.2.2
- Fixed packaging problem whereby a `config.gypi` was unintentially packaged and could cause breakages for OS X builds.
## 2.2.1
- Now shipping with 64bit FreeBSD binaries against both node v0.10.x and node v0.8.x.
- Fixed solaris/smartos source compile by passing `-std=c99` when building internally bundled libsqlite3 (#201)
- Reduced size of npm package by ignoring tests and examples.
- Various fixes and improvements for building against node-webkit
- Upgraded to node-pre-gyp@0.5.x from node-pre-gyp@0.2.5
- Improved ability to build from source against `sqlcipher` by passing custom library name: `--sqlite_libname=sqlcipher`
- No changes to C++ Core / Existing binaries are exactly the same
## 2.2.0
Released Jan 13th, 2014
- updated internal libsqlite3 from 3.7.17 -> 3.8.2 (http://www.sqlite.org/news.html) which includes the next-generation query planner http://www.sqlite.org/queryplanner-ng.html
- improved binary deploy system using https://github.com/springmeyer/node-pre-gyp
- binary install now supports http proxies
- source compile now supports freebsd
- fixed support for node-webkit
## 2.1.19
Released October 31st, 2013
- Started respecting `process.env.npm_config_tmp` as location to download binaries
- Removed uneeded `progress` dependency
## 2.1.18
Released October 22nd, 2013
- `node-sqlite3` moved to mapbox github group
- Fixed reporting of node-gyp errors
- Fixed support for node v0.6.x
## 2.1.17
- Minor fixes to binary deployment
## 2.1.16
- Support for binary deployment
## 2.1.15
Released August 7th, 2013
- Minor readme additions and code optimizations

25
node_modules/sqlite3/LICENSE generated vendored Normal file
View File

@ -0,0 +1,25 @@
Copyright (c) MapBox
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
- Neither the name "MapBox" nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

186
node_modules/sqlite3/README.md generated vendored Normal file
View File

@ -0,0 +1,186 @@
Asynchronous, non-blocking [SQLite3](http://sqlite.org/) bindings for [Node.js](http://nodejs.org/).
[![NPM](https://nodei.co/npm/sqlite3.png?downloads=true&downloadRank=true)](https://nodei.co/npm/sqlite3/)
[![Build Status](https://travis-ci.org/mapbox/node-sqlite3.svg?branch=master)](https://travis-ci.org/mapbox/node-sqlite3)
[![Build status](https://ci.appveyor.com/api/projects/status/gvm7ul0hpmdawqom)](https://ci.appveyor.com/project/Mapbox/node-sqlite3)
## Supported platforms
The `sqlite3` module works with Node.js v0.10.x or v0.11.x (though only v0.11.13 and above).
Binaries for most Node versions and platforms are provided by default via [node-pre-gyp](https://github.com/springmeyer/node-pre-gyp).
The `sqlite3` module also works with [node-webkit](https://github.com/rogerwang/node-webkit) if node-webkit contains a supported version of Node.js engine. [(See below.)](#building-for-node-webkit)
SQLite's [SQLCipher extension](https://github.com/sqlcipher/sqlcipher) is also supported. [(See below.)](#building-for-sqlcipher)
# Usage
**Note:** the module must be [installed](#installing) before use.
``` js
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');
db.serialize(function() {
db.run("CREATE TABLE lorem (info TEXT)");
var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
stmt.run("Ipsum " + i);
}
stmt.finalize();
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
console.log(row.id + ": " + row.info);
});
});
db.close();
```
# Features
- Straightforward query and parameter binding interface
- Full Buffer/Blob support
- Extensive [debugging support](https://github.com/mapbox/node-sqlite3/wiki/Debugging)
- [Query serialization](https://github.com/mapbox/node-sqlite3/wiki/Control-Flow) API
- [Extension support](https://github.com/mapbox/node-sqlite3/wiki/Extensions)
- Big test suite
- Written in modern C++ and tested for memory leaks
# API
See the [API documentation](https://github.com/mapbox/node-sqlite3/wiki) in the wiki.
# Installing
You can use [`npm`](https://github.com/isaacs/npm) to download and install:
* The latest `sqlite3` package: `npm install sqlite3`
* GitHub's `master` branch: `npm install https://github.com/mapbox/node-sqlite3/tarball/master`
In both cases the module is automatically built with npm's internal version of `node-gyp`,
and thus your system must meet [node-gyp's requirements](https://github.com/TooTallNate/node-gyp#installation).
It is also possible to make your own build of `sqlite3` from its source instead of its npm package ([see below](#building-from-the-source)).
It is possible to use the installed package in [node-webkit](https://github.com/rogerwang/node-webkit) instead of the vanilla Node.js. See [Building for node-webkit](#building-for-node-webkit) for details.
## Source install
Unless building via `npm install` (which uses its own `node-gyp`) you will need `node-gyp` installed globally:
npm install node-gyp -g
The sqlite3 module depends only on libsqlite3. However, by default, an internal/bundled copy of sqlite will be built and statically linked, so an externally installed sqlite3 is not required.
If you wish to install against an external sqlite then you need to pass the `--sqlite` argument to `node-gyp`, `npm install` or the `configure` wrapper.
./configure --sqlite=/usr/local
make
Or, using the node-gyp directly:
node-gyp --sqlite=/usr/local
make
Or, using npm:
npm install --sqlite=/usr/local
If building against an external sqlite3 make sure to have the development headers available. Mac OS X ships with these by default. If you don't have them installed, install the `-dev` package with your package manager, e.g. `apt-get install libsqlite3-dev` for Debian/Ubuntu. Make sure that you have at least `libsqlite3` >= 3.6.
Note, if building against homebrew-installed sqlite on OS X you can do:
./configure --sqlite=/usr/local/opt/sqlite/
make
## Building for node-webkit
Because of ABI differences, `sqlite3` must be built in a custom to be used with [node-webkit](https://github.com/rogerwang/node-webkit).
To build node-sqlite3 for node-webkit:
1. Install [`nw-gyp`](https://github.com/rogerwang/nw-gyp) globally: `npm install nw-gyp -g` *(unless already installed)*
2. Build the module with the custom flags of `--runtime`, `--target_arch`, and `--target`:
```sh
NODE_WEBKIT_VERSION="0.8.6" # see latest version at https://github.com/rogerwang/node-webkit#downloads
npm install sqlite3 --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
```
This command internally calls out to [`node-pre-gyp`](https://github.com/mapbox/node-pre-gyp) which itself calls out to [`nw-gyp`](https://github.com/rogerwang/nw-gyp) when the `--runtime=node-webkit` option is passed.
You can also run this command from within a `node-sqlite3` checkout:
```sh
npm install --build-from-source --runtime=node-webkit --target_arch=ia32 --target=$(NODE_WEBKIT_VERSION)
```
Remember the following:
* You must provide the right `--target_arch` flag. `ia32` is needed to target 32bit node-webkit builds, while `x64` will target 64bit node-webkit builds (if available for your platform).
* After the `sqlite3` package is built for node-webkit it cannot run in the vanilla Node.js (and vice versa).
* For example, `npm test` of the node-webkit's package would fail.
Visit the “[Using Node modules](https://github.com/rogerwang/node-webkit/wiki/Using-Node-modules)” article in the node-webkit's wiki for more details.
## Building for sqlcipher
To run node-sqlite3 against sqlcipher you need to compile from source by passing build options like:
npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/
If your sqlcipher is installed in a custom location, say if you installed it with homebrew on OS X you also need to do:
export LDFLAGS="-L`brew --prefix`/opt/sqlcipher/lib"
export CPPFLAGS="-I`brew --prefix`/opt/sqlcipher/include"
npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=`brew --prefix`
# Testing
[mocha](https://github.com/visionmedia/mocha) is required to run unit tests.
In sqlite3's directory (where its `package.json` resides) run the following:
npm install mocha
npm test
# Contributors
* [Konstantin Käfer](https://github.com/kkaefer)
* [Dane Springmeyer](https://github.com/springmeyer)
* [Will White](https://github.com/willwhite)
* [Orlando Vazquez](https://github.com/orlandov)
* [Artem Kustikov](https://github.com/artiz)
* [Eric Fredricksen](https://github.com/grumdrig)
* [John Wright](https://github.com/mrjjwright)
* [Ryan Dahl](https://github.com/ry)
* [Tom MacWright](https://github.com/tmcw)
* [Carter Thaxton](https://github.com/carter-thaxton)
* [Audrius Kažukauskas](https://github.com/audriusk)
* [Johannes Schauer](https://github.com/pyneo)
* [Mithgol](https://github.com/Mithgol)
# Acknowledgments
Thanks to [Orlando Vazquez](https://github.com/orlandov),
[Eric Fredricksen](https://github.com/grumdrig) and
[Ryan Dahl](https://github.com/ry) for their SQLite bindings for node, and to mraleph on Freenode's #v8 for answering questions.
Development of this module is sponsored by [MapBox](http://mapbox.org/).
# License
`node-sqlite3` is [BSD licensed](https://github.com/mapbox/node-sqlite3/raw/master/LICENSE).

45
node_modules/sqlite3/appveyor.yml generated vendored Normal file
View File

@ -0,0 +1,45 @@
environment:
node_pre_gyp_accessKeyId:
secure: 7DrSVc5eIGtmMcki5H+iRft+Tk3MJTwDBQEUuJHWaQ4=
node_pre_gyp_secretAccessKey:
secure: 1amwJJw9fu0j6dXnc5KsAQbSYf7Cjw/dapT6OZWABa6nc52grkKeLQ+DGaOfQz8i
matrix:
- nodejs_version: 0.10.30
nw_version: 0.8.6
PLATFORM: x86
- nodejs_version: 0.10.30
nw_version: 0.8.6
PLATFORM: x64
- nodejs_version: 0.11.13
nw_version: 0.10.5
PLATFORM: x86
- nodejs_version: 0.11.13
nw_version: 0.10.5
PLATFORM: x64
install:
- ps: Update-NodeJsInstallation $env:nodejs_version $env:Platform
- node --version
- npm --version
- echo %PLATFORM%
- SET PATH=c:\python27;%PATH%
- SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
- SET PATH=%APPDATA%\npm;%PATH%
# add local node-pre-gyp dir to path
- SET PATH=node_modules\.bin;%PATH%
# # work around old npm problem with ^
- npm update npm -g
- npm --version
# upgrade node-gyp to support --msvs_version=2013
- npm install node-gyp
- npm install --build-from-source --msvs_version=2013
- npm test
- node-pre-gyp package
# make commit message env var shorter
- SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
- if not "%CM%" == "%CM:[publish binary]=%" node-pre-gyp --msvs_version=2013 publish
- call scripts\build_for_node_webkit.cmd %PLATFORM%
build: OFF
test: OFF
deploy: OFF

52
node_modules/sqlite3/binding.gyp generated vendored Normal file
View File

@ -0,0 +1,52 @@
{
"includes": [ "deps/common-sqlite.gypi" ],
"variables": {
"sqlite%":"internal",
"sqlite_libname%":"sqlite3"
},
"targets": [
{
"target_name": "<(module_name)",
"include_dirs": ["<!(node -e \"require('nan')\")"],
"conditions": [
["sqlite != 'internal'", {
"include_dirs": [ "<@(sqlite)/include" ],
"libraries": [
"-l<(sqlite_libname)"
],
"conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<@(sqlite)/lib"]} ] ],
"conditions": [ [ "OS!='win'", {"libraries+":["-L<@(sqlite)/lib"]} ] ],
'msvs_settings': {
'VCLinkerTool': {
'AdditionalLibraryDirectories': [
'<@(sqlite)/lib'
],
},
}
},
{
"dependencies": [
"deps/sqlite3.gyp:sqlite3"
]
}
]
],
"sources": [
"src/database.cc",
"src/node_sqlite3.cc",
"src/statement.cc"
]
},
{
"target_name": "action_after_build",
"type": "none",
"dependencies": [ "<(module_name)" ],
"copies": [
{
"files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
"destination": "<(module_path)"
}
]
}
]
}

5
node_modules/sqlite3/deps/common-sqlite.gypi generated vendored Normal file
View File

@ -0,0 +1,5 @@
{
'variables': {
'sqlite_version%':'3080600'
}
}

9
node_modules/sqlite3/deps/extract.py generated vendored Normal file
View File

@ -0,0 +1,9 @@
import sys
import tarfile
import os
tarball = os.path.abspath(sys.argv[1])
dirname = os.path.abspath(sys.argv[2])
tfile = tarfile.open(tarball,'r:gz');
tfile.extractall(dirname)
sys.exit(0)

Binary file not shown.

100
node_modules/sqlite3/deps/sqlite3.gyp generated vendored Executable file
View File

@ -0,0 +1,100 @@
{
'includes': [ 'common-sqlite.gypi' ],
'target_defaults': {
'default_configuration': 'Release',
'cflags':[
'-std=c99'
],
'configurations': {
'Debug': {
'defines': [ 'DEBUG', '_DEBUG' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 1, # static debug
},
},
},
'Release': {
'defines': [ 'NDEBUG' ],
'msvs_settings': {
'VCCLCompilerTool': {
'RuntimeLibrary': 0, # static release
},
},
}
},
'msvs_settings': {
'VCCLCompilerTool': {
},
'VCLibrarianTool': {
},
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
},
},
'conditions': [
['OS == "win"', {
'defines': [
'WIN32'
],
}]
],
},
'targets': [
{
'target_name': 'action_before_build',
'type': 'none',
'hard_dependency': 1,
'actions': [
{
'action_name': 'unpack_sqlite_dep',
'inputs': [
'./sqlite-autoconf-<@(sqlite_version).tar.gz'
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/sqlite3.c'
],
'action': ['python','./extract.py','./sqlite-autoconf-<@(sqlite_version).tar.gz','<(SHARED_INTERMEDIATE_DIR)']
}
],
'direct_dependent_settings': {
'include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/',
]
},
},
{
'target_name': 'sqlite3',
'type': 'static_library',
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/' ],
'dependencies': [
'action_before_build'
],
'sources': [
'<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/sqlite3.c'
],
'direct_dependent_settings': {
'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)/sqlite-autoconf-<@(sqlite_version)/' ],
'defines': [
'SQLITE_THREADSAFE=1',
'SQLITE_ENABLE_FTS3',
'SQLITE_ENABLE_RTREE'
],
},
'cflags_cc': [
'-Wno-unused-value',
'-include ../src/gcc-preinclude.h'
],
'defines': [
'_REENTRANT=1',
'SQLITE_THREADSAFE=1',
'SQLITE_ENABLE_FTS3',
'SQLITE_ENABLE_RTREE'
],
'export_dependent_settings': [
'action_before_build',
]
}
]
}

Binary file not shown.

1
node_modules/sqlite3/lib/index.js generated vendored Normal file
View File

@ -0,0 +1 @@
module.exports = require('./sqlite3');

187
node_modules/sqlite3/lib/sqlite3.js generated vendored Normal file
View File

@ -0,0 +1,187 @@
var binary = require('node-pre-gyp');
var path = require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
var binding = require(binding_path);
var sqlite3 = module.exports = exports = binding;
var EventEmitter = require('events').EventEmitter;
function normalizeMethod (fn) {
return function (sql) {
var errBack;
var args = Array.prototype.slice.call(arguments, 1);
if (typeof args[args.length - 1] === 'function') {
var callback = args[args.length - 1];
errBack = function(err) {
if (err) {
callback(err);
}
};
}
var statement = new Statement(this, sql, errBack);
return fn.call(this, statement, args);
}
}
function inherits(target, source) {
for (var k in source.prototype)
target.prototype[k] = source.prototype[k];
}
sqlite3.cached = {
Database: function(file, a, b) {
if (file === '' || file === ':memory:') {
// Don't cache special databases.
return new Database(file, a, b);
}
file = path.resolve(file);
if (!sqlite3.cached.objects[file]) {
var db =sqlite3.cached.objects[file] = new Database(file, a, b);
}
else {
// Make sure the callback is called.
var db = sqlite3.cached.objects[file];
var callback = (typeof a === 'number') ? b : a;
if (typeof callback === 'function') {
function cb() { callback.call(db, null); }
if (db.open) process.nextTick(cb);
else db.once('open', cb);
}
}
return db;
},
objects: {}
};
var Database = sqlite3.Database;
var Statement = sqlite3.Statement;
inherits(Database, EventEmitter);
inherits(Statement, EventEmitter);
// Database#prepare(sql, [bind1, bind2, ...], [callback])
Database.prototype.prepare = normalizeMethod(function(statement, params) {
return params.length
? statement.bind.apply(statement, params)
: statement;
});
// Database#run(sql, [bind1, bind2, ...], [callback])
Database.prototype.run = normalizeMethod(function(statement, params) {
statement.run.apply(statement, params).finalize();
return this;
});
// Database#get(sql, [bind1, bind2, ...], [callback])
Database.prototype.get = normalizeMethod(function(statement, params) {
statement.get.apply(statement, params).finalize();
return this;
});
// Database#all(sql, [bind1, bind2, ...], [callback])
Database.prototype.all = normalizeMethod(function(statement, params) {
statement.all.apply(statement, params).finalize();
return this;
});
// Database#each(sql, [bind1, bind2, ...], [callback], [complete])
Database.prototype.each = normalizeMethod(function(statement, params) {
statement.each.apply(statement, params).finalize();
return this;
});
Database.prototype.map = normalizeMethod(function(statement, params) {
statement.map.apply(statement, params).finalize();
return this;
});
Statement.prototype.map = function() {
var params = Array.prototype.slice.call(arguments);
var callback = params.pop();
params.push(function(err, rows) {
if (err) return callback(err);
var result = {};
if (rows.length) {
var keys = Object.keys(rows[0]), key = keys[0];
if (keys.length > 2) {
// Value is an object
for (var i = 0; i < rows.length; i++) {
result[rows[i][key]] = rows[i];
}
} else {
var value = keys[1];
// Value is a plain value
for (var i = 0; i < rows.length; i++) {
result[rows[i][key]] = rows[i][value];
}
}
}
callback(err, result);
});
return this.all.apply(this, params);
};
var isVerbose = false;
var supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ];
Database.prototype.addListener = Database.prototype.on = function(type) {
var val = EventEmitter.prototype.addListener.apply(this, arguments);
if (supportedEvents.indexOf(type) >= 0) {
this.configure(type, true);
}
return val;
};
Database.prototype.removeListener = function(type) {
var val = EventEmitter.prototype.removeListener.apply(this, arguments);
if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) {
this.configure(type, false);
}
return val;
};
Database.prototype.removeAllListeners = function(type) {
var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
if (supportedEvents.indexOf(type) >= 0) {
this.configure(type, false);
}
return val;
};
// Save the stack trace over EIO callbacks.
sqlite3.verbose = function() {
if (!isVerbose) {
var trace = require('./trace');
[
'prepare',
'get',
'run',
'all',
'each',
'map',
'close',
'exec'
].forEach(function (name) {
trace.extendTrace(Database.prototype, name);
});
[
'bind',
'get',
'run',
'all',
'each',
'map',
'reset',
'finalize',
].forEach(function (name) {
trace.extendTrace(Statement.prototype, name);
});
isVerbose = true;
}
return this;
};

42
node_modules/sqlite3/lib/trace.js generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Inspired by https://github.com/tlrobinson/long-stack-traces
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function extendTrace(object, property, pos) {
var old = object[property];
object[property] = function() {
var error = new Error();
var name = object.constructor.name + '#' + property + '(' +
Array.prototype.slice.call(arguments).map(function(el) {
return util.inspect(el, false, 0);
}).join(', ') + ')';
if (typeof pos === 'undefined') pos = -1;
if (pos < 0) pos += arguments.length;
var cb = arguments[pos];
if (typeof arguments[pos] === 'function') {
arguments[pos] = function replacement() {
try {
return cb.apply(this, arguments);
} catch (err) {
if (err && err.stack && !err.__augmented) {
err.stack = filter(err).join('\n');
err.stack += '\n--> in ' + name;
err.stack += '\n' + filter(error).slice(1).join('\n');
err.__augmented = true;
}
throw err;
}
};
}
return old.apply(this, arguments);
};
}
exports.extendTrace = extendTrace;
function filter(error) {
return error.stack.split('\n').filter(function(line) {
return line.indexOf(__filename) < 0;
});
}

1
node_modules/sqlite3/node_modules/.bin/node-pre-gyp generated vendored Symbolic link
View File

@ -0,0 +1 @@
../node-pre-gyp/bin/node-pre-gyp

30
node_modules/sqlite3/node_modules/nan/.dntrc generated vendored Normal file
View File

@ -0,0 +1,30 @@
## DNT config file
## see https://github.com/rvagg/dnt
NODE_VERSIONS="\
master \
v0.11.13 \
v0.10.30 \
v0.10.29 \
v0.10.28 \
v0.10.26 \
v0.10.25 \
v0.10.24 \
v0.10.23 \
v0.10.22 \
v0.10.21 \
v0.10.20 \
v0.10.19 \
v0.8.28 \
v0.8.27 \
v0.8.26 \
v0.8.24 \
"
OUTPUT_PREFIX="nan-"
TEST_CMD=" \
cd /dnt/ && \
npm install && \
node_modules/.bin/node-gyp --nodedir /usr/src/node/ rebuild --directory test && \
node_modules/.bin/tap --gc test/js/*-test.js \
"

200
node_modules/sqlite3/node_modules/nan/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,200 @@
# NAN ChangeLog
### Version 1.3.0: current Node unstable: 0.11.13, Node stable: 0.10.30
**1.3.0 Aug 2 2014**
- Added NanNew<v8::String, std::string>(std::string)
- Added NanNew<v8::String, std::string&>(std::string&)
- Added NanAsciiString helper class
- Added NanUtf8String helper class
- Added NanUcs2String helper class
- Deprecated NanRawString()
- Deprecated NanCString()
- Added NanGetIsolateData(v8::Isolate *isolate)
- Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value>* argv)
- Added NanMakeCallback(v8::Handle<v8::Object> target, v8::Handle<v8::String> symbol, int argc, v8::Handle<v8::Value>* argv)
- Added NanMakeCallback(v8::Handle<v8::Object> target, const char* method, int argc, v8::Handle<v8::Value>* argv)
- Added NanSetTemplate(v8::Handle<v8::Template> templ, v8::Handle<v8::String> name , v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- Added NanSetPrototypeTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
- Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, const char *name, v8::Handle<v8::Data> value)
- Added NanSetInstanceTemplate(v8::Local<v8::FunctionTemplate> templ, v8::Handle<v8::String> name, v8::Handle<v8::Data> value, v8::PropertyAttribute attributes)
**1.2.0 Jun 5 2014**
- Add NanSetPrototypeTemplate
- Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class,
introduced _NanWeakCallbackDispatcher
- Removed -Wno-unused-local-typedefs from test builds
- Made test builds Windows compatible ('Sleep()')
**1.1.2 May 28 2014**
- Release to fix more stuff-ups in 1.1.1
**1.1.1 May 28 2014**
- Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0
**1.1.0 May 25 2014**
- Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead
- Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]),
(uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*,
v8::String::ExternalAsciiStringResource*
- Deprecate NanSymbol()
- Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker
**1.0.0 May 4 2014**
- Heavy API changes for V8 3.25 / Node 0.11.13
- Use cpplint.py
- Removed NanInitPersistent
- Removed NanPersistentToLocal
- Removed NanFromV8String
- Removed NanMakeWeak
- Removed NanNewLocal
- Removed NAN_WEAK_CALLBACK_OBJECT
- Removed NAN_WEAK_CALLBACK_DATA
- Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions
- Introduce NanUndefined, NanNull, NanTrue and NanFalse
- Introduce NanEscapableScope and NanEscapeScope
- Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node)
- Introduce NanMakeCallback for node::MakeCallback
- Introduce NanSetTemplate
- Introduce NanGetCurrentContext
- Introduce NanCompileScript and NanRunScript
- Introduce NanAdjustExternalMemory
- Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback
- Introduce NanGetHeapStatistics
- Rename NanAsyncWorker#SavePersistent() to SaveToPersistent()
**0.8.0 Jan 9 2014**
- NanDispose -> NanDisposePersistent, deprecate NanDispose
- Extract _NAN_*_RETURN_TYPE, pull up NAN_*()
**0.7.1 Jan 9 2014**
- Fixes to work against debug builds of Node
- Safer NanPersistentToLocal (avoid reinterpret_cast)
- Speed up common NanRawString case by only extracting flattened string when necessary
**0.7.0 Dec 17 2013**
- New no-arg form of NanCallback() constructor.
- NanCallback#Call takes Handle rather than Local
- Removed deprecated NanCallback#Run method, use NanCallback#Call instead
- Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS
- Restore (unofficial) Node 0.6 compatibility at NanCallback#Call()
- Introduce NanRawString() for char* (or appropriate void*) from v8::String
(replacement for NanFromV8String)
- Introduce NanCString() for null-terminated char* from v8::String
**0.6.0 Nov 21 2013**
- Introduce NanNewLocal<T>(v8::Handle<T> value) for use in place of
v8::Local<T>::New(...) since v8 started requiring isolate in Node 0.11.9
**0.5.2 Nov 16 2013**
- Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public
**0.5.1 Nov 12 2013**
- Use node::MakeCallback() instead of direct v8::Function::Call()
**0.5.0 Nov 11 2013**
- Added @TooTallNate as collaborator
- New, much simpler, "include_dirs" for binding.gyp
- Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros
**0.4.4 Nov 2 2013**
- Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+
**0.4.3 Nov 2 2013**
- Include node_object_wrap.h, removed from node.h for Node 0.11.8.
**0.4.2 Nov 2 2013**
- Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for
Node 0.11.8 release.
**0.4.1 Sep 16 2013**
- Added explicit `#include <uv.h>` as it was removed from node.h for v0.11.8
**0.4.0 Sep 2 2013**
- Added NAN_INLINE and NAN_DEPRECATED and made use of them
- Added NanError, NanTypeError and NanRangeError
- Cleaned up code
**0.3.2 Aug 30 2013**
- Fix missing scope declaration in GetFromPersistent() and SaveToPersistent
in NanAsyncWorker
**0.3.1 Aug 20 2013**
- fix "not all control paths return a value" compile warning on some platforms
**0.3.0 Aug 19 2013**
- Made NAN work with NPM
- Lots of fixes to NanFromV8String, pulling in features from new Node core
- Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API
- Added optional error number argument for NanThrowError()
- Added NanInitPersistent()
- Added NanReturnNull() and NanReturnEmptyString()
- Added NanLocker and NanUnlocker
- Added missing scopes
- Made sure to clear disposed Persistent handles
- Changed NanAsyncWorker to allocate error messages on the heap
- Changed NanThrowError(Local<Value>) to NanThrowError(Handle<Value>)
- Fixed leak in NanAsyncWorker when errmsg is used
**0.2.2 Aug 5 2013**
- Fixed usage of undefined variable with node::BASE64 in NanFromV8String()
**0.2.1 Aug 5 2013**
- Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for
NanFromV8String()
**0.2.0 Aug 5 2013**
- Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR,
NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY
- Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS,
_NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS,
_NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS,
_NAN_PROPERTY_QUERY_ARGS
- Added NanGetInternalFieldPointer, NanSetInternalFieldPointer
- Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT,
NAN_WEAK_CALLBACK_DATA, NanMakeWeak
- Renamed THROW_ERROR to _NAN_THROW_ERROR
- Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*)
- Added NanBufferUse(char*, uint32_t)
- Added NanNewContextHandle(v8::ExtensionConfiguration*,
v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
- Fixed broken NanCallback#GetFunction()
- Added optional encoding and size arguments to NanFromV8String()
- Added NanGetPointerSafe() and NanSetPointerSafe()
- Added initial test suite (to be expanded)
- Allow NanUInt32OptionValue to convert any Number object
**0.1.0 Jul 21 2013**
- Added `NAN_GETTER`, `NAN_SETTER`
- Added `NanThrowError` with single Local<Value> argument
- Added `NanNewBufferHandle` with single uint32_t argument
- Added `NanHasInstance(Persistent<FunctionTemplate>&, Handle<Value>)`
- Added `Local<Function> NanCallback#GetFunction()`
- Added `NanCallback#Call(int, Local<Value>[])`
- Deprecated `NanCallback#Run(int, Local<Value>[])` in favour of Call

46
node_modules/sqlite3/node_modules/nan/LICENSE generated vendored Normal file
View File

@ -0,0 +1,46 @@
Copyright 2013, NAN contributors:
- Rod Vagg <https://github.com/rvagg>
- Benjamin Byholm <https://github.com/kkoopa>
- Trevor Norris <https://github.com/trevnorris>
- Nathan Rajlich <https://github.com/TooTallNate>
- Brett Lawson <https://github.com/brett19>
- Ben Noordhuis <https://github.com/bnoordhuis>
(the "Original Author")
All rights reserved.
MIT +no-false-attribs 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.
Distributions of all or part of the Software intended to be used
by the recipients as they would use the unmodified Software,
containing modifications that substantially alter, remove, or
disable functionality of the Software, outside of the documented
configuration mechanisms provided by the Software, shall be
modified such that the Original Author's bug reporting email
addresses and urls are either replaced with the contact information
of the parties responsible for the changes, or removed entirely.
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.
Except where noted, this license applies to any and all software
programs and associated documentation files created by the
Original Author, when distributed with the Software.

1054
node_modules/sqlite3/node_modules/nan/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

32
node_modules/sqlite3/node_modules/nan/appveyor.yml generated vendored Normal file
View File

@ -0,0 +1,32 @@
# http://www.appveyor.com/docs/appveyor-yml
# Test against these versions of Node.js.
environment:
matrix:
- nodejs_version: "0.8"
- nodejs_version: "0.10"
- nodejs_version: "0.11"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node 0.STABLE.latest
- npm install npm
- move node_modules npm
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version)
# Typical npm stuff.
- npm/.bin/npm install
- npm/.bin/npm run rebuild-tests
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
- cmd: npm test
# Don't actually build.
build: off
# Set build version format here instead of in the admin panel.
version: "{build}"

View File

@ -0,0 +1 @@
console.log(require('path').relative('.', __dirname));

2331
node_modules/sqlite3/node_modules/nan/nan.h generated vendored Normal file

File diff suppressed because it is too large Load Diff

79
node_modules/sqlite3/node_modules/nan/package.json generated vendored Normal file
View File

@ -0,0 +1,79 @@
{
"name": "nan",
"version": "1.3.0",
"description": "Native Abstractions for Node.js: C++ header for Node 0.8->0.12 compatibility",
"main": "include_dirs.js",
"repository": {
"type": "git",
"url": "git://github.com/rvagg/nan.git"
},
"scripts": {
"test": "tap --gc test/js/*-test.js",
"rebuild-tests": "node-gyp rebuild --directory test"
},
"contributors": [
{
"name": "Rod Vagg",
"email": "r@va.gg",
"url": "https://github.com/rvagg"
},
{
"name": "Benjamin Byholm",
"email": "bbyholm@abo.fi",
"url": "https://github.com/kkoopa/"
},
{
"name": "Trevor Norris",
"email": "trev.norris@gmail.com",
"url": "https://github.com/trevnorris"
},
{
"name": "Nathan Rajlich",
"email": "nathan@tootallnate.net",
"url": "https://github.com/TooTallNate"
},
{
"name": "Brett Lawson",
"email": "brett19@gmail.com",
"url": "https://github.com/brett19"
},
{
"name": "Ben Noordhuis",
"email": "info@bnoordhuis.nl",
"url": "https://github.com/bnoordhuis"
}
],
"devDependencies": {
"bindings": "~1.2.1",
"node-gyp": "~1.0.1",
"tap": "~0.4.12",
"xtend": "~4.0.0"
},
"license": "MIT",
"gitHead": "e482fbe142e58373d5a24f4e5a60c61e22a13f83",
"bugs": {
"url": "https://github.com/rvagg/nan/issues"
},
"homepage": "https://github.com/rvagg/nan",
"_id": "nan@1.3.0",
"_shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742",
"_from": "nan@1.3.0",
"_npmVersion": "1.4.21",
"_npmUser": {
"name": "rvagg",
"email": "rod@vagg.org"
},
"maintainers": [
{
"name": "rvagg",
"email": "rod@vagg.org"
}
],
"dist": {
"shasum": "9a5b8d5ef97a10df3050e59b2c362d3baf779742",
"tarball": "http://registry.npmjs.org/nan/-/nan-1.3.0.tgz"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/nan/-/nan-1.3.0.tgz",
"readme": "ERROR: No README data found!"
}

View File

@ -0,0 +1,161 @@
# node-pre-gyp changelog
## 0.5.27
- Fixed support for auto-detecting s3 bucket name when it contains `.` - @taavo
- Fixed support for installing when path contains a `'` - @halfdan
- Ported tests to mocha
## 0.5.26
- Fix node-webkit support when `--target` option is not provided
## 0.5.25
- Fix bundling of deps
## 0.5.24
- Updated ABI crosswalk to incldue node v0.10.30 and v0.10.31
## 0.5.23
- Added `reveal` command. Pass no options to get all versioning data as json. Pass a second arg to grab a single versioned property value
- Added support for `--silent` (shortcut for `--loglevel=silent`)
## 0.5.22
- Fixed node-webkit versioning name (NOTE: node-webkit support still experimental)
## 0.5.21
- New package to fix `shasum check failed` error with v0.5.20
## 0.5.20
- Now versioning node-webkit binaries based on major.minor.patch - assuming no compatible ABI across versions (#90)
## 0.5.19
- Updated to know about more node-webkit releases
## 0.5.18
- Updated to know about more node-webkit releases
## 0.5.17
- Updated to know about node v0.10.29 release
## 0.5.16
- Now supporting all aws-sdk configuration parameters (http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html) (#86)
## 0.5.15
- Fixed installation of windows packages sub directories on unix systems (#84)
## 0.5.14
- Finished support for cross building using `--target_platform` option (#82)
- Now skipping binary validation on install if target arch/platform do not match the host.
- Removed multi-arch validing for OS X since it required a FAT node.js binary
## 0.5.13
- Fix problem in 0.5.12 whereby the wrong versions of mkdirp and semver where bundled.
## 0.5.12
- Improved support for node-webkit (@Mithgol)
## 0.5.11
- Updated target versions listing
## 0.5.10
- Fixed handling of `-debug` flag passed directory to node-pre-gyp (#72)
- Added optional second arg to `node_pre_gyp.find` to customize the default versioning options used to locate the runtime binary
- Failed install due to `testbinary` check failure no longer leaves behind binary (#70)
## 0.5.9
- Fixed regression in `testbinary` command causing installs to fail on windows with 0.5.7 (#60)
## 0.5.8
- Started bundling deps
## 0.5.7
- Fixed the `testbinary` check, which is used to determine whether to re-download or source compile, to work even in complex dependency situations (#63)
- Exposed the internal `testbinary` command in node-pre-gyp command line tool
- Fixed minor bug so that `fallback_to_build` option is always respected
## 0.5.6
- Added support for versioning on the `name` value in `package.json` (#57).
- Moved to using streams for reading tarball when publishing (#52)
## 0.5.5
- Improved binary validation that also now works with node-webkit (@Mithgol)
- Upgraded test apps to work with node v0.11.x
- Improved test coverage
## 0.5.4
- No longer depends on external install of node-gyp for compiling builds.
## 0.5.3
- Reverted fix for debian/nodejs since it broke windows (#45)
## 0.5.2
- Support for debian systems where the node binary is named `nodejs` (#45)
- Added `bin/node-pre-gyp.cmd` to be able to run command on windows locally (npm creates an .npm automatically when globally installed)
- Updated abi-crosswalk with node v0.10.26 entry.
## 0.5.1
- Various minor bug fixes, several improving windows support for publishing.
## 0.5.0
- Changed property names in `binary` object: now required are `module_name`, `module_path`, and `host`.
- Now `module_path` supports versioning, which allows developers to opt-in to using a versioned install path (#18).
- Added `remote_path` which also supports versioning.
- Changed `remote_uri` to `host`.
## 0.4.2
- Added support for `--target` flag to request cross-compile against a specific node/node-webkit version.
- Added preliminary support for node-webkit
- Fixed support for `--target_arch` option being respected in all cases.
## 0.4.1
- Fixed exception when only stderr is available in binary test (@bendi / #31)
## 0.4.0
- Enforce only `https:` based remote publishing access.
- Added `node-pre-gyp info` command to display listing of published binaries
- Added support for changing the directory node-pre-gyp should build in with the `-C/--directory` option.
- Added support for S3 prefixes.
## 0.3.1
- Added `unpublish` command.
- Fixed module path construction in tests.
- Added ability to disable falling back to build behavior via `npm install --fallback-to-build=false` which overrides setting in a depedencies package.json `install` target.
## 0.3.0
- Support for packaging all files in `module_path` directory - see `app4` for example
- Added `testpackage` command.
- Changed `clean` command to only delete `.node` not entire `build` directory since node-gyp will handle that.
- `.node` modules must be in a folder of there own since tar-pack will remove everything when it unpacks.

27
node_modules/sqlite3/node_modules/node-pre-gyp/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c), MapBox
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,515 @@
# node-pre-gyp
#### node-pre-gyp makes it easy to publish and install Node.js C++ addons from binaries
[![NPM](https://nodei.co/npm/node-pre-gyp.png)](https://nodei.co/npm/node-pre-gyp/)
[![Build Status](https://api.travis-ci.org/mapbox/node-pre-gyp.svg)](https://travis-ci.org/mapbox/node-pre-gyp)
[![Build status](https://ci.appveyor.com/api/projects/status/3nxewb425y83c0gv)](https://ci.appveyor.com/project/Mapbox/node-pre-gyp)
[![Dependencies](https://david-dm.org/mapbox/node-pre-gyp.svg)](https://david-dm.org/mapbox/node-pre-gyp)
`node-pre-gyp` stands between [npm](https://github.com/npm/npm) and [node-gyp](https://github.com/Tootallnate/node-gyp) and offers a cross-platform method of binary deployment.
### Features
- A command line tool called `node-pre-gyp` that can install your package's c++ module from a binary.
- A variety of developer targeted commands for packaging, testing, and publishing binaries.
- A Javascript module that can dynamically require your installed binary: `require('node-pre-gyp').find`
For a hello world example of a module packaged with `node-pre-gyp` see <https://github.com/springmeyer/node-addon-example> and [the wiki ](https://github.com/mapbox/node-pre-gyp/wiki/Modules-using-node-pre-gyp) for real world examples.
## Credits
- The module is modeled after [node-gyp](https://github.com/Tootallnate/node-gyp) by [@Tootallnate](https://github.com/Tootallnate)
- Motivation for initial development came from [@ErisDS](https://github.com/ErisDS) and the [Ghost Project](https://github.com/TryGhost/Ghost).
- Development is sponsored by [Mapbox](https://www.mapbox.com/)
## Depends
- Node.js 0.10.x or 0.8.x
## Install
`node-pre-gyp` is designed to be installed as a local dependency of your Node.js C++ addon and accessed like:
./node_modules/.bin/node-pre-gyp --help
But you can also install it globally:
npm install node-pre-gyp -g
## Usage
### Commands
View all possible commands:
node-pre-gyp --help
- clean - Removes the entire folder containing the compiled .node module
- install - Attempts to install pre-built binary for module
- reinstall - Runs "clean" and "install" at once
- build - Attempts to compile the module by dispatching to node-gyp or nw-gyp
- rebuild - Runs "clean" and "build" at once
- package - Packs binary into tarball
- testpackage - Tests that the staged package is valid
- publish - Publishes pre-built binary
- unpublish - Unpublishes pre-built binary
- info - Fetches info on published binaries
You can also chain commands:
node-pre-gyp clean build unpublish publish info
### Options
Options include:
- `-C/--directory`: run the command in this directory
- `--build-from-source`: build from source instead of using pre-built binary
- `--runtime=node-webkit`: customize the runtime: `node` and `node-webkit` are the valid options
- `--fallback-to-build`: fallback to building from source if pre-built binary is not available
- `--target=0.10.25`: Pass the target node or node-webkit version to compile against
- `--target_arch=ia32`: Pass the target arch and override the host `arch`. Valid values are 'ia32','x64', or `arm`.
- `--target_platform=win32`: Pass the target platform and override the host `platform`. Valid values are `linux`, `darwin`, `win32`, `sunos`, `freebsd`, `openbsd`, and `aix`.
Both `--build-from-source` and `--fallback-to-build` can be passed alone or they can provide values. You can pass `--fallback-to-build=false` to override the option as declared in package.json. In addition to being able to pass `--build-from-source` you can also pass `--build-from-source=myapp` where `myapp` is the name of your module.
For example: `npm install --build-from-source=myapp`. This is useful if:
- `myapp` is referenced in the package.json of a larger app and therefore `myapp` is being installed as a dependent with `npm install`.
- The larger app also depends on other modules installed with `node-pre-gyp`
- You only want to trigger a source compile for `myapp` and the other modules.
### Configuring
This is a guide to configuring your module to use node-pre-gyp.
#### 1) Add new entries to your `package.json`
- Add `node-pre-gyp` to `bundledDependencies`
- Add `aws-sdk` as a `devDependency`
- Add a custom `install` script
- Declare a `binary` object
This looks like:
```js
"dependencies" : {
"node-pre-gyp": "0.5.x"
},
"bundledDependencies":["node-pre-gyp"],
"devDependencies": {
"aws-sdk": "~2.0.0-rc.15"
}
"scripts": {
"install": "node-pre-gyp install --fallback-to-build",
},
"binary": {
"module_name": "your_module",
"module_path": "./lib/binding/",
"host": "https://your_module.s3-us-west-1.amazonaws.com"
}
```
For a full example see [node-addon-examples's package.json](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/package.json#L11-L22).
##### The `binary` object has three required properties
###### module_name
The name of your native node module. This value must:
- Match the name passed to [the NODE_MODULE macro](http://nodejs.org/api/addons.html#addons_hello_world)
- Must be a valid C variable name (e.g. it cannot contain `-`)
- Should not include the `.node` extension.
###### module_path
The location your native module is placed after a build. This should be an empty directory without other javascript files. This entire directory will be packaged in the binary tarball. When installing from a remote package this directory will be overwritten with the contents of the tarball.
Note: This property supports variables based on [Versioning](#versioning).
###### host
A url to the remote location where you've published tarball binaries (must be `https` not `http`).
It is highly recommended that you use Amazon S3. The reasons are:
- Various node-pre-gyp commands like `publish` and `info` only work with an S3 host.
- S3 is a very solid hosting platform for distributing large files, even [Github recommends using it instead of github](https://help.github.com/articles/distributing-large-binaries).
- We provide detail documentation for using [S3 hosting](#s3-hosting) with node-pre-gyp.
Why then not require S3? Because while some applications using node-pre-gyp need to distribute binaries as large as 20-30 MB, others might have very small binaries and might wish to store them in a github repo. This is not recommended, but if an author really wants to host in a non-s3 location then it should be possible.
##### The `binary` object has two optional properties
###### remote_path
It **is recommended** that you customize this property. This is an extra path to use for publishing and finding remote tarballs. The default value for `remote_path` is `""` meaning that if you do not provide it then all packages will be published at the base of the `host`. It is recommended to provide a value like `./{name}/v{version}` to help organize remote packages in the case that you choose to publish multiple node addons to the same `host`.
Note: This property supports variables based on [Versioning](#versioning).
###### package_name
It is **not recommended** to override this property unless you are also overriding the `remote_path`. This is the versioned name of the remote tarball containing the binary `.node` module and any supporting files you've placed inside the `module_path` directory. Unless you specify `package_name` in your `package.json` then it defaults to `{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz` which allows your binary to work across node versions, platforms, and architectures. If you are using `remote_path` that is also versioned by `./{module_name}/v{version}` then you could remove these variables from the `package_name` and just use: `{node_abi}-{platform}-{arch}.tar.gz`. Then your remote tarball will be looked up at, for example, `https://example.com/your-module/v0.1.0/node-v11-linux-x64.tar.gz`.
Note: This property supports variables based on [Versioning](#versioning).
#### 2) Add a new target to binding.gyp
`node-pre-gyp` calls out to `node-gyp` to compile the module and passes variables along like [module_name](#module_name) and [module_path](#module_path).
A new target must be added to `binding.gyp` that moves the compiled `.node` module from `./build/Release/module_name.node` into the directory specified by `module_path`.
Add a target like this at the end of your `targets` list:
```js
{
"target_name": "action_after_build",
"type": "none",
"dependencies": [ "<(module_name)" ],
"copies": [
{
"files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
"destination": "<(module_path)"
}
]
}
```
For a full example see [node-addon-example's binding.gyp](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/binding.gyp).
#### 3) Dynamically require your `.node`
Inside the main js file that requires your addon module you are likely currently doing:
```js
var binding = require('../build/Release/binding.node');
```
or:
```js
var bindings = require('./bindings')
```
Change those lines to:
```js
var binary = require('node-pre-gyp');
var path = require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'./package.json')));
var binding = require(binding_path);
```
For a full example see [node-addon-example's index.js](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/index.js#L1-L4)
#### 4) Build and package your app
Now build your module from source:
npm install --build-from-source
The `--build-from-source` tells `node-pre-gyp` to not look for a remote package and instead dispatch to node-gyp to build.
Now `node-pre-gyp` should now also be installed as a local dependency so the command line tool it offers can be found at `./node_modules/.bin/node-pre-gyp`.
#### 5) Test
Now `npm test` should work just as it did before.
#### 6) Publish the tarball
Then package your app:
./node_modules/.bin/node-pre-gyp package
Once packaged, now you can publish:
./node_modules/.bin/node-pre-gyp publish
Currently the `publish` command pushes your binary to S3. This requires:
- You have installed `aws-sdk` with `npm install aws-sdk`
- You have created a bucket already.
- The `host` points to an S3 http or https endpoint.
- You have configured node-pre-gyp to read your S3 credentials (see [S3 hosting](#s3-hosting) for details).
You can also host your binaries elsewhere. To do this requires:
- You manually publish the binary created by the `package` command to an `https` endpoint
- Ensure that the `host` value points to your custom `https` endpoint.
#### 7) Automate builds
Now you need to publish builds for all the platforms and node versions you wish to support. This is best automated.
- See [Appveyor Automation](#appveyor-automation) for how to auto-publish builds on Windows.
- See [Travis Automation](#travis-automation) for how to auto-publish builds on OS X and Linux.
#### 8) You're done!
Now publish your module to the npm registry. Users will now be able to install your module from a binary.
What will happen is this:
1. `npm install <your package>` will pull from the npm registry
2. npm will run the `install` script which will call out to `node-pre-gyp`
3. `node-pre-gyp` will fetch the binary `.node` module and unpack in the right place
4. Assuming that all worked, you are done
If a a binary was not available for a given platform and `--fallback-to-build` was used then `node-gyp rebuild` will be called to try to source compile the module.
## S3 Hosting
You can host wherever you choose but S3 is cheap, `node-pre-gyp publish` expects it, and S3 can be integrated well with [travis.ci](http://travis-ci.org) to automate builds for OS X and Ubuntu. Here is an approach to do this:
First, get setup locally and test the workflow:
#### 1) Create an S3 bucket
And have your **key** and **secret key** ready for writing to the bucket.
It is recommended to create a IAM user with a policy that only gives permissions to the specific bucket you plan to publish to. This can be done in the [IAM console](https://console.aws.amazon.com/iam/) by: 1) adding a new user, 2) choosing `Attach User Policy`, 3) Using the `Policy Generator`, 4) selecting `Amazon S3` for the service, 5) adding the actions: `DeleteObject`, `GetObject`, `GetObjectAcl`, `ListBucket`, `PutObject`, `PutObjectAcl`, 6) adding an ARN of `arn:aws:s3:::bucket/*` (replacing `bucket` with your bucket name), and finally 7) clicking `Add Statement` and saving the policy. It should generate a policy like:
```js
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1394587197000",
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::node-pre-gyp-tests/*"
]
}
]
}
```
#### 2) Install node-pre-gyp
Either install it globally:
npm install node-pre-gyp -g
Or put the local version on your PATH
export PATH=`pwd`/node_modules/.bin/:$PATH
#### 3) Configure AWS credentials
There are several ways to do this.
You can use any of the methods described at http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html.
Or you can create a `~/.node_pre_gyprc`
Or pass options in any way supported by [RC](https://github.com/dominictarr/rc#standards)
A `~/.node_pre_gyprc` looks like:
```js
{
"accessKeyId": "xxx",
"secretAccessKey": "xxx"
}
```
Another way is to use your environment:
export node_pre_gyp_accessKeyId=xxx
export node_pre_gyp_secretAccessKey=xxx
You may also need to specify the `region` if it is not explicit in the `host` value you use. The `bucket` can also be specified but it is optional because `node-pre-gyp` will detect it from the `host` value.
#### 4) Package and publish your build
Install the `aws-sdk`:
npm install aws-sdk
Then publish:
node-pre-gyp package publish
Note: if you hit an error like `Hostname/IP doesn't match certificate's altnames` it may mean that you need to provide the `region` option in your config.
## Appveyor Automation
[Appveyor](http://www.appveyor.com/) can build binaries and publish the results per commit and supports:
- Windows Visual Studio 2013 and related compilers
- Both 64 bit (x64) and 32 bit (x86) build configurations
- Multiple Node.js versions
For an example of doing this see [node-sqlite3's appveyor.yml](https://github.com/mapbox/node-sqlite3/blob/master/appveyor.yml).
Below is a guide to getting set up:
#### 1) Create a free Appveyor account
Go to https://ci.appveyor.com/signup/free and sign in with your github account.
#### 2) Create a new project
Go to https://ci.appveyor.com/projects/new and select the github repo for your module
#### 3) Add appveyor.yml and push it
Once you have committed an `appveyor.yml` ([appveyor.yml reference](http://www.appveyor.com/docs/appveyor-yml)) to your github repo and pushed it appveyor should automatically start building your project.
#### 4) Create secure variables
Encrypt your S3 AWS keys by going to <https://ci.appveyor.com/tools/encrypt> and hitting the `encrypt` button.
Then paste the result into your `appveyor.yml`
```yml
environment:
node_pre_gyp_accessKeyId:
secure: Dn9HKdLNYvDgPdQOzRq/DqZ/MPhjknRHB1o+/lVU8MA=
node_pre_gyp_secretAccessKey:
secure: W1rwNoSnOku1r+28gnoufO8UA8iWADmL1LiiwH9IOkIVhDTNGdGPJqAlLjNqwLnL
```
NOTE: keys are per account but not per repo (this is difference than travis where keys are per repo but not related to the account used to encrypt them).
#### 5) Hook up publishing
Just put `node-pre-gyp package publish` in your `appveyor.yml` after `npm install`.
#### 6) Publish when you want
You might wish to publish binaries only on a specific commit. To do this you could borrow from the [travis.ci idea of commit keywords](http://about.travis-ci.org/docs/user/how-to-skip-a-build/) and add special handling for commit messages with `[publish binary]`:
SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
if not "%CM%" == "%CM:[publish binary]=%" node-pre-gyp --msvs_version=2013 publish
If your commit message contains special characters (e.g. `&`) this method might fail. An alternative is to use PowerShell, which gives you additional possibilites, like ignoring case by using `ToLower()`:
ps: if($env:APPVEYOR_REPO_COMMIT_MESSAGE.ToLower().Contains('[publish binary]')) { node-pre-gyp --msvs_version=2013 publish }
Remember this publishing is not the same as `npm publish`. We're just talking about the binary module here and not your entire npm package. To automate the publishing of your entire package to npm on travis see http://about.travis-ci.org/docs/user/deployment/npm/
## Travis Automation
[Travis](https://travis-ci.org/) can push to S3 after a successful build and supports both:
- Ubuntu Precise and OS X
- Multiple Node.js versions
For an example of doing this see [node-add-example's .travis.yml](https://github.com/springmeyer/node-addon-example/blob/2ff60a8ded7f042864ad21db00c3a5a06cf47075/.travis.yml).
Below is a guide to getting set up:
#### 1) Install the travis gem
gem install travis
#### 2) Create secure variables
Make sure you run this command from within the directory of your module.
Use `travis-encrypt` like:
travis encrypt node_pre_gyp_accessKeyId=${node_pre_gyp_accessKeyId}
travis encrypt node_pre_gyp_secretAccessKey=${node_pre_gyp_secretAccessKey}
Then put those values in your `.travis.yml` like:
```yaml
env:
global:
- secure: F+sEL/v56CzHqmCSSES4pEyC9NeQlkoR0Gs/ZuZxX1ytrj8SKtp3MKqBj7zhIclSdXBz4Ev966Da5ctmcTd410p0b240MV6BVOkLUtkjZJyErMBOkeb8n8yVfSoeMx8RiIhBmIvEn+rlQq+bSFis61/JkE9rxsjkGRZi14hHr4M=
- secure: o2nkUQIiABD139XS6L8pxq3XO5gch27hvm/gOdV+dzNKc/s2KomVPWcOyXNxtJGhtecAkABzaW8KHDDi5QL1kNEFx6BxFVMLO8rjFPsMVaBG9Ks6JiDQkkmrGNcnVdxI/6EKTLHTH5WLsz8+J7caDBzvKbEfTux5EamEhxIWgrI=
```
More details on travis encryption at http://about.travis-ci.org/docs/user/encryption-keys/.
#### 3) Hook up publishing
Just put `node-pre-gyp package publish` in your `.travis.yml` after `npm install`.
If you want binaries for OS X change you have two options:
- Enable `multi-os` for your repo by emailing a request to `support@travis-ci.com`. More details at <http://docs.travis-ci.com/user/multi-os/>. An example of a repo using multi-os is [node-sqlite3](https://github.com/mapbox/node-sqlite3/blob/f69b89a078e2200fee54a9f897e6957bd627d8b7/.travis.yml#L4-L6).
- Or, you can change the `language` and push to a different branch to build on OS X just when you commit to that branch. Details on this below:
##### OS X publishing via a branch
Tweak your `.travis.yml` to use:
```yml
language: objective-c
```
Keep that change in a different git branch and sync that when you want binaries published.
Note: using `language: objective-c` instead of `language: nodejs` looses node.js specific travis sugar like a matrix for multiple node.js versions.
But you can replicate the lost behavior by replacing:
```yml
node_js:
- "0.8"
- "0.10"
```
With:
```yml
env:
matrix:
- export NODE_VERSION="0.8"
- export NODE_VERSION="0.10"
before_install:
- git clone https://github.com/creationix/nvm.git ./.nvm
- source ./.nvm/nvm.sh
- nvm install $NODE_VERSION
- nvm use $NODE_VERSION
```
#### 4) Publish when you want
You might wish to publish binaries only on a specific commit. To do this you could borrow from the [travis.ci idea of commit keywords](http://about.travis-ci.org/docs/user/how-to-skip-a-build/) and add special handling for commit messages with `[publish binary]`:
COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then node-pre-gyp publish; fi;
Then you can trigger new binaries to be built like:
git commit -a -m "[publish binary]"
Or, if you don't have any changes to make simply run:
git commit --allow-empty -m "[publish binary]"
Remember this publishing is not the same as `npm publish`. We're just talking about the binary module here and not your entire npm package. To automate the publishing of your entire package to npm on travis see http://about.travis-ci.org/docs/user/deployment/npm/
# Versioning
The `binary` properties of `module_path`, `remote_path`, and `package_name` support variable substitution. The strings are evaluated by `node-pre-gyp` depending on your system and any custom build flags you passed.
- `configuration` - Either 'Release' or 'Debug' depending on if `--debug` is passed during the build.
- `module_name` - the `binary.module_name` attribute from `package.json`.
- `version` - the semver `version` value for your module from `package.json`.
- `major`, `minor`, `patch`, and `prelease` match the individual semver values for your module's `version`
- `node_abi`: The node C++ `ABI` number. This value is available in javascript as `process.versions.modules` as of [`>= v0.10.4 >= v0.11.7`](https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e) and in C++ as the `NODE_MODULE_VERSION` define much earlier. For versions of Node before this was available we fallback to the V8 major and minor version.
- `platform` matches node's `process.platform` like `linux`, `darwin`, and `win32` unless the user passed the `--target_platform` option to override.
- `arch` matches node's `process.arch` like `x64` or `ia32` unless the user passes the `--target_arch` option to override.
The options are visible in the code at <https://github.com/mapbox/node-pre-gyp/blob/612b7bca2604508d881e1187614870ba19a7f0c5/lib/util/versioning.js#L114-L127>

View File

@ -0,0 +1,32 @@
environment:
matrix:
#- nodejs_version: 0.8.28
- nodejs_version: 0.10.32
- nodejs_version: 0.11.13
platform:
- x64
- x86
shallow_clone: true
install:
#- ps: Update-NodeJsInstallation $env:nodejs_version $env:Platform
# http://help.appveyor.com/discussions/problems/618-nodejs-10030-doesnt-work-on-appveyor-cant-find-npm#comment_34002825
- ps: Install-Product node $env:nodejs_version $env:Platform
- ps: gcm node
- ps: gcm npm
- node --version
- npm --version
- SET PATH=%APPDATA%\npm;%PATH%
- npm update -g npm
- npm --version
- node -e "console.log(process.arch);"
- SET PATH=C:\python27;%PATH%
- npm install
- npm test
- cmd: test.bat
build: off
test: off
deploy: off

View File

@ -0,0 +1,130 @@
#!/usr/bin/env node
/**
* Set the title.
*/
process.title = 'node-pre-gyp'
/**
* Module dependencies.
*/
var node_pre_gyp = require('../')
var log = require('npmlog')
/**
* Process and execute the selected commands.
*/
var prog = new node_pre_gyp.Run()
var completed = false
prog.parseArgv(process.argv)
if (prog.todo.length === 0) {
if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) {
console.log('v%s', prog.version)
} else {
console.log('%s', prog.usage())
}
return process.exit(0)
}
// if --no-color is passed
if (prog.opts && prog.opts.hasOwnProperty('color') && !prog.opts.color) {
log.disableColor();
}
log.info('it worked if it ends with', 'ok')
log.verbose('cli', process.argv)
log.info('using', process.title + '@%s', prog.version)
log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch)
/**
* Change dir if -C/--directory was passed.
*/
var dir = prog.opts.directory
if (dir) {
var fs = require('fs')
try {
var stat = fs.statSync(dir)
if (stat.isDirectory()) {
log.info('chdir', dir)
process.chdir(dir)
} else {
log.warn('chdir', dir + ' is not a directory')
}
} catch (e) {
if (e.code === 'ENOENT') {
log.warn('chdir', dir + ' is not a directory')
} else {
log.warn('chdir', 'error during chdir() "%s"', e.message)
}
}
}
function run () {
var command = prog.todo.shift()
if (!command) {
// done!
completed = true
log.info('ok')
return
}
prog.commands[command.name](command.args, function (err) {
if (err) {
log.error(command.name + ' error')
log.error('stack', err.stack)
errorMessage()
log.error('not ok')
console.log(err.message);
return process.exit(1)
}
var args_array = [].slice.call(arguments, 1)
if (args_array.length) {
console.log.apply(console, args_array)
}
// now run the next command in the queue
process.nextTick(run)
})
}
process.on('exit', function (code) {
if (!completed && !code) {
log.error('Completion callback never invoked!')
issueMessage()
process.exit(6)
}
})
process.on('uncaughtException', function (err) {
log.error('UNCAUGHT EXCEPTION')
log.error('stack', err.stack)
issueMessage()
process.exit(7)
})
function errorMessage () {
// copied from npm's lib/util/error-handler.js
var os = require('os')
log.error('System', os.type() + ' ' + os.release())
log.error('command', process.argv
.map(JSON.stringify).join(' '))
log.error('cwd', process.cwd())
log.error('node -v', process.version)
log.error(process.title+' -v', 'v' + prog.package.version)
}
function issueMessage () {
errorMessage()
log.error('', [ 'This is a bug in `'+process.title+'`.'
, 'Try to update '+process.title+' and file an issue if it does not help:'
, ' <https://github.com/mapbox/'+process.title+'/issues>'
].join('\n'))
}
// start running the given commands!
run()

View File

@ -0,0 +1,2 @@
@echo off
node "%~dp0\node-pre-gyp" %*

View File

@ -0,0 +1,52 @@
module.exports = exports = build
exports.usage = 'Attempts to compile the module by dispatching to node-gyp or nw-gyp'
var fs = require('fs')
, compile = require('./util/compile.js')
, versioning = require('./util/versioning.js')
, path = require('path')
, fs = require('fs')
, mkdirp = require('mkdirp')
function build(gyp, argv, callback) {
var gyp_args = [];
if (argv.length && argv[0] == 'rebuild') {
gyp_args.push('rebuild');
} else {
gyp_args.push('configure');
gyp_args.push('build');
}
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
// options look different depending on whether node-pre-gyp is called directly
// or whether it is called from npm install, hence the following line.
// TODO: check if this is really necessary with latest npm/nopt versions
var original_args = (typeof(gyp.opts.argv.original) === 'string') ? JSON.parse(gyp.opts.argv).original : gyp.opts.argv.original || [];
// add command line options to existing opts
original_args.forEach(function(opt) {
// we ignore any args like 'install' since we know
// we are either running 'build' or 'rebuild' but we
// do want to pass along to node-gyp/nw-gyp any command
// line options like --option or --option=value passed in
if (opt.length > 2 && opt.slice(0,2) == '--') {
var parts = opt.split('=');
if (parts.length > 1) {
var key = parts[0];
opts[key.slice(2)] = parts[1];
}
}
})
var command_line_args = [];
// turn back into command line options
Object.keys(opts).forEach(function(o) {
var val = opts[o];
if (val) {
command_line_args.push('--' + o + '=' + val);
}
})
compile.run_gyp(gyp_args.concat(command_line_args),opts,function(err,gopts) {
return callback(err);
});
}

View File

@ -0,0 +1,24 @@
module.exports = exports = clean
exports.usage = 'Removes the entire folder containing the compiled .node module'
var fs = require('fs')
, rm = require('rimraf')
, path = require('path')
, exists = require('fs').exists || require('path').exists
, log = require('npmlog')
, versioning = require('./util/versioning.js')
function clean (gyp, argv, callback) {
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
var to_delete = opts.module_path;
exists(to_delete, function(found) {
if (found) {
if (!gyp.opts.silent_clean) console.log('['+package_json.name+'] Removing "%s"', to_delete);
return rm(to_delete, callback);
}
return callback();
})
}

View File

@ -0,0 +1,40 @@
module.exports = exports = unpublish
exports.usage = 'Lists all published binaries (requires aws-sdk)'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, versioning = require('./util/versioning.js')
, s3_setup = require('./util/s3_setup.js')
, config = require('rc')("node_pre_gyp",{acl:"public-read"});
function unpublish(gyp, argv, callback) {
var AWS = require("aws-sdk");
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
s3_setup.detect(opts.hosted_path,config);
AWS.config.update(config);
var s3 = new AWS.S3();
var s3_opts = { Bucket: config.bucket,
Prefix: config.prefix
};
s3.listObjects(s3_opts, function(err, meta){
if (err && err.code == 'NotFound') {
return callback(new Error('['+package_json.name+'] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/'+config.prefix));
} else if(err) {
return callback(err);
} else {
log.verbose(JSON.stringify(meta,null,1));
if (meta && meta.Contents) {
meta.Contents.forEach(function(obj) {
console.log(obj.Key);
});
} else {
console.error('['+package_json.name+'] No objects found at https://' + s3_opts.Bucket + '.s3.amazonaws.com/'+config.prefix )
}
return callback();
}
});
}

View File

@ -0,0 +1,198 @@
module.exports = exports = install
exports.usage = 'Attempts to install pre-built binary for module'
var fs = require('fs')
, tar = require('tar')
, path = require('path')
, zlib = require('zlib')
, log = require('npmlog')
, request = require('request')
, existsAsync = fs.exists || path.exists
, versioning = require('./util/versioning.js')
, compile = require('./util/compile.js')
, testbinary = require('./testbinary.js')
, clean = require('./clean.js')
function download(uri,opts,callback) {
log.http('GET', uri)
var req = null
var requestOpts = {
uri: uri
, headers: {
'User-Agent': 'node-pre-gyp (node ' + process.version + ')'
}
}
var proxyUrl = opts.proxy
|| process.env.http_proxy
|| process.env.HTTP_PROXY
|| process.env.npm_config_proxy
if (proxyUrl) {
if (/^https?:\/\//i.test(proxyUrl)) {
log.verbose('download', 'using proxy url: "%s"', proxyUrl)
requestOpts.proxy = proxyUrl
} else {
log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl)
}
}
try {
req = request(requestOpts)
} catch (e) {
return callback(e)
}
if (req) {
req.on('response', function (res) {
log.http(res.statusCode, uri)
})
}
return callback(null,req);
}
function place_binary(from,to,opts,callback) {
download(from,opts,function(err,req) {
if (err) return callback(err);
if (!req) return callback(new Error("empty req"));
var badDownload = false
, extractCount = 0
, gunzip = zlib.createGunzip()
, extracter = tar.Extract({ path: to, strip: 1});
function afterTarball(err) {
if (err) return callback(err);
if (badDownload) return callback(new Error("bad download"));
if (extractCount === 0) {
return callback(new Error('There was a fatal problem while downloading/extracting the tarball'))
}
log.info('tarball', 'done parsing tarball')
callback();
}
function filter_func(entry) {
// ensure directories are +x
// https://github.com/mapnik/node-mapnik/issues/262
entry.props.mode |= (entry.props.mode >>> 2) & 0111;
log.info('install','unpacking ' + entry.path);
extractCount++
}
gunzip.on('error', callback)
extracter.on('entry', filter_func)
extracter.on('error', callback)
extracter.on('end', afterTarball)
req.on('error', function (err) {
badDownload = true
callback(err)
})
req.on('close', function () {
if (extractCount === 0) {
callback(new Error('Connection closed while downloading tarball file'))
}
})
req.on('response', function (res) {
if (res.statusCode !== 200) {
badDownload = true
if (res.statusCode == 404) {
return callback(new Error('Pre-built binary not available for your system'));
} else {
return callback(new Error(res.statusCode + ' status code downloading tarball'));
}
}
// start unzipping and untaring
req.pipe(gunzip).pipe(extracter)
})
});
}
function do_build(gyp,argv,callback) {
gyp.todo.push( { name: 'build', args: ['rebuild'] } );
process.nextTick(callback);
}
function install(gyp, argv, callback) {
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var source_build = gyp.opts['build-from-source'] || gyp.opts['build_from_source'];
var should_do_source_build = source_build === package_json.name || (source_build === true || source_build === 'true');
if (should_do_source_build) {
log.info('build','requesting source compile');
return do_build(gyp,argv,callback);
} else {
var fallback_to_build = gyp.opts['fallback-to-build'] || gyp.opts['fallback_to_build'];
var should_do_fallback_build = fallback_to_build === package_json.name || (fallback_to_build === true || fallback_to_build === 'true');
// but allow override from npm
if (process.env.npm_config_argv) {
var cooked = JSON.parse(process.env.npm_config_argv).cooked;
var match = cooked.indexOf("--fallback-to-build");
if (match > -1 && cooked.length > match && cooked[match+1] == "false") {
should_do_fallback_build = false;
log.info('install','Build fallback disabled via npm flag: --fallback-to-build=false');
}
}
try {
var opts = versioning.evaluate(package_json, gyp.opts);
} catch (err) {
return callback(err);
}
var from = opts.hosted_tarball;
var to = opts.module_path;
var binary_module = path.join(to,opts.module_name + '.node');
if (existsAsync(binary_module,function(found) {
if (found) {
testbinary(gyp, argv, function(err) {
if (err) {
console.error('['+package_json.name+'] ' + err.message);
log.error("Testing local pre-built binary failed, attempting to re-download");
place_binary(from,to,opts,function(err) {
if (err) {
if (should_do_fallback_build) {
log.http(err.message + ' (falling back to source compile with node-gyp)');
return do_build(gyp,argv,callback);
} else {
return callback(err);
}
} else {
console.log('['+package_json.name+'] Success: "' + binary_module + '" is reinstalled via remote');
return callback();
}
});
} else {
console.log('['+package_json.name+'] Success: "' + binary_module + '" already installed');
console.log('Pass --build-from-source to recompile');
return callback();
}
});
} else {
log.info('check','checked for "' + binary_module + '" (not found)')
place_binary(from,to,opts,function(err) {
if (err && should_do_fallback_build) {
log.http(err.message + ' (falling back to source compile with node-gyp)');
return do_build(gyp,argv,callback);
} else if (err) {
return callback(err);
} else {
testbinary(gyp, argv, function(err) {
if (err) {
gyp.opts.silent_clean = true;
clean(gyp, argv, function(error) {
if (error) console.log(error);
if (should_do_fallback_build) {
console.error('['+package_json.name+'] ' + err.message);
log.error("Testing pre-built binary failed, attempting to source compile");
return do_build(gyp,argv,callback);
} else {
return callback(err);
}
});
} else {
console.log('['+package_json.name+'] Success: "' + binary_module + '" is installed via remote');
return callback();
}
});
};
});
}
}));
}
};

View File

@ -0,0 +1,194 @@
/**
* Module exports.
*/
module.exports = exports;
/**
* Module dependencies.
*/
var fs = require('fs')
, path = require('path')
, nopt = require('nopt')
, log = require('npmlog')
, child_process = require('child_process')
, EE = require('events').EventEmitter
, inherits = require('util').inherits
, commands = [
'clean',
'install',
'reinstall',
'build',
'rebuild',
'package',
'testpackage',
'publish',
'unpublish',
'info',
'testbinary',
'reveal'
]
, aliases = {
}
// differentiate node-pre-gyp's logs from npm's
log.heading = 'node-pre-gyp'
exports.find = require('./pre-binding').find;
function Run() {
var self = this
this.commands = {}
commands.forEach(function (command) {
self.commands[command] = function (argv, callback) {
log.verbose('command', command, argv)
return require('./' + command)(self, argv, callback)
}
})
}
inherits(Run, EE)
exports.Run = Run
var proto = Run.prototype
/**
* Export the contents of the package.json.
*/
proto.package = require('../package')
/**
* nopt configuration definitions
*/
proto.configDefs = {
help: Boolean // everywhere
, arch: String // 'configure'
, debug: Boolean // 'build'
, directory: String // bin
, proxy: String // 'install'
, loglevel: String // everywhere
}
/**
* nopt shorthands
*/
proto.shorthands = {
release: '--no-debug'
, C: '--directory'
, debug: '--debug'
, j: '--jobs'
, silent: '--loglevel=silent'
, silly: '--loglevel=silly'
, verbose: '--loglevel=verbose'
}
/**
* expose the command aliases for the bin file to use.
*/
proto.aliases = aliases
/**
* Parses the given argv array and sets the 'opts',
* 'argv' and 'command' properties.
*/
proto.parseArgv = function parseOpts (argv) {
this.opts = nopt(this.configDefs, this.shorthands, argv)
this.argv = this.opts.argv.remain.slice()
var commands = this.todo = []
// create a copy of the argv array with aliases mapped
argv = this.argv.map(function (arg) {
// is this an alias?
if (arg in this.aliases) {
arg = this.aliases[arg]
}
return arg
}, this)
// process the mapped args into "command" objects ("name" and "args" props)
argv.slice().forEach(function (arg) {
if (arg in this.commands) {
var args = argv.splice(0, argv.indexOf(arg))
argv.shift()
if (commands.length > 0) {
commands[commands.length - 1].args = args
}
commands.push({ name: arg, args: [] })
}
}, this)
if (commands.length > 0) {
commands[commands.length - 1].args = argv.splice(0)
}
// support for inheriting config env variables from npm
var npm_config_prefix = 'npm_config_'
Object.keys(process.env).forEach(function (name) {
if (name.indexOf(npm_config_prefix) !== 0) return
var val = process.env[name]
if (name === npm_config_prefix + 'loglevel') {
log.level = val
} else {
// add the user-defined options to the config
name = name.substring(npm_config_prefix.length)
// avoid npm argv clobber already present args
// which avoids problem of 'npm test' calling
// script that runs unique npm install commands
if (name === 'argv') {
if (this.opts.argv &&
this.opts.argv.remain &&
this.opts.argv.remain.length) {
// do nothing
} else {
this.opts[name] = val
}
} else {
this.opts[name] = val
}
}
}, this)
if (this.opts.loglevel) {
log.level = this.opts.loglevel
}
log.resume()
}
/**
* Returns the usage instructions for node-pre-gyp.
*/
proto.usage = function usage () {
var str = [
''
, ' Usage: node-pre-gyp <command> [options]'
, ''
, ' where <command> is one of:'
, commands.map(function (c) {
return ' - ' + c + ' - ' + require('./' + c).usage
}).join('\n')
, ''
, 'node-pre-gyp@' + this.version + ' ' + path.resolve(__dirname, '..')
, 'node@' + process.versions.node
].join('\n')
return str
}
/**
* Version number getter.
*/
Object.defineProperty(proto, 'version', {
get: function () {
return this.package.version
}
, enumerable: true
})

View File

@ -0,0 +1,46 @@
module.exports = exports = package
exports.usage = 'Packs binary (and enclosing directory) into locally staged tarball'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, versioning = require('./util/versioning.js')
, compile = require('./util/compile.js')
, write = require('fs').createWriteStream
, pack = require('tar-pack').pack
, existsAsync = fs.exists || path.exists
, mkdirp = require('mkdirp');
function package(gyp, argv, callback) {
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
var from = opts.module_path;
var binary_module = path.join(from,opts.module_name + '.node');
existsAsync(binary_module,function(found) {
if (!found) {
return callback(new Error("Cannot package because " + binary_module + " missing: run `node-pre-gyp rebuild` first"))
}
var tarball = opts.staged_tarball;
var basedir = path.basename(from);
var filter_func = function (entry) {
// ensure directories are +x
// https://github.com/mapnik/node-mapnik/issues/262
log.info('package','packing ' + entry.path);
return true;
}
mkdirp(path.dirname(tarball),function(err) {
pack(from, { filter: filter_func })
.pipe(write(tarball))
.on('error', function (err) {
if (err) console.error('['+package_json.name+'] ' + err.message);
return callback(err);
})
.on('close', function () {
log.info('package','Binary staged at "' + tarball + '"');
return callback();
})
});
});
}

View File

@ -0,0 +1,24 @@
var fs = require('fs');
var versioning = require('../lib/util/versioning.js')
var existsSync = require('fs').existsSync || require('path').existsSync;
var path = require('path');
module.exports = exports;
exports.usage = 'Finds the require path for the node-pre-gyp installed module'
exports.validate = function(package_json) {
versioning.validate_config(package_json);
}
exports.find = function(package_json_path,opts) {
if (!existsSync(package_json_path)) {
throw new Error("package.json does not exist at " + package_json_path);
}
var package_json = require(package_json_path);
versioning.validate_config(package_json);
opts = opts || {};
if (!opts.module_root) opts.module_root = path.dirname(package_json_path);
var meta = versioning.evaluate(package_json,opts);
return meta.module;
}

View File

@ -0,0 +1,58 @@
module.exports = exports = publish
exports.usage = 'Publishes pre-built binary (requires aws-sdk)'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, versioning = require('./util/versioning.js')
, s3_setup = require('./util/s3_setup.js')
, mkdirp = require('mkdirp')
, existsAsync = fs.exists || path.exists
, url = require('url')
, config = require('rc')("node_pre_gyp",{acl:"public-read"});
function publish(gyp, argv, callback) {
var AWS = require("aws-sdk");
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
var tarball = opts.staged_tarball;
existsAsync(tarball,function(found) {
if (!found) {
return callback(new Error("Cannot publish because " + tarball + " missing: run `node-pre-gyp package` first"))
}
s3_setup.detect(opts.hosted_path,config);
var key_name = url.resolve(config.prefix,opts.package_name)
AWS.config.update(config);
var s3 = new AWS.S3();
var s3_opts = { Bucket: config.bucket,
Key: key_name
};
s3.headObject(s3_opts, function(err, meta){
if (err && err.code == 'NotFound') {
// we are safe to publish because
// the object does not already exist
var s3 = new AWS.S3();
var s3_obj_opts = { ACL: config.acl,
Body: fs.createReadStream(tarball),
Bucket: config.bucket,
Key: key_name
};
s3.putObject(s3_obj_opts, function(err, resp){
if(err) return callback(err);
console.log('['+package_json.name+'] Success: published to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
return callback();
});
} else if(err) {
return callback(err);
} else {
log.error('publish','Cannot publish over existing version');
log.error('publish',"Update the 'version' field in package.json and try again");
log.error('publish','If the previous version was published in error see:');
log.error('publish','\t node-pre-gyp unpublish');
return callback(new Error('Failed publishing to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key));
}
});
});
}

View File

@ -0,0 +1,12 @@
module.exports = exports = rebuild
exports.usage = 'Runs "clean" and "build" at once'
function rebuild (gyp, argv, callback) {
gyp.todo.unshift(
{ name: 'clean', args: [] }
, { name: 'build', args: ['rebuild'] }
)
process.nextTick(callback)
}

View File

@ -0,0 +1,12 @@
module.exports = exports = rebuild
exports.usage = 'Runs "clean" and "install" at once'
function rebuild (gyp, argv, callback) {
gyp.todo.unshift(
{ name: 'clean', args: [] }
, { name: 'install', args: [] }
)
process.nextTick(callback)
}

View File

@ -0,0 +1,28 @@
module.exports = exports = reveal
exports.usage = 'Reveals data on the versioned binary'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, versioning = require('./util/versioning.js');
function reveal(gyp, argv, callback) {
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
var hit = false;
// if a second arg is passed look to see
// if it is a known option
var args = gyp.opts.argv.cooked;
var find_val = args[args.indexOf('reveal')+1];
if (find_val && opts.hasOwnProperty(find_val)) {
console.log(opts[find_val]);
hit = true;
}
// otherwise return all options as json
if (!hit) {
console.log(JSON.stringify(opts,null,2));
}
return callback();
}

View File

@ -0,0 +1,71 @@
module.exports = exports = testbinary
exports.usage = 'Tests that the binary.node can be required'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, cp = require('child_process')
, versioning = require('./util/versioning.js')
, path = require('path')
function testbinary(gyp, argv, callback) {
var args = [];
var options = {}
var shell_cmd = process.execPath;
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
// ensure on windows that / are used for require path
var binary_module = opts.module.replace(/\\/g, '/');
var nw = (opts.runtime && opts.runtime === 'node-webkit');
if (nw) {
options.timeout = 5000;
if (process.platform === 'darwin') {
shell_cmd = 'node-webkit';
} else if (process.platform === 'win32') {
shell_cmd = 'nw.exe';
} else {
shell_cmd = 'nw';
}
var modulePath = path.resolve(binary_module);
var appDir = path.join(__dirname, 'util', 'nw-pre-gyp');
args.push(appDir);
args.push(modulePath);
log.info("validate","Running test command: '" + shell_cmd + ' ' + args.join(' ') + "'");
cp.execFile(shell_cmd, args, options, function(err, stdout, stderr) {
// check for normal timeout for node-webkit
if (err) {
if (err.killed == true && err.signal && err.signal.indexOf('SIG') > -1) {
return callback();
}
var stderrLog = stderr.toString();
log.info('stderr', stderrLog);
if( /^\s*Xlib:\s*extension\s*"RANDR"\s*missing\s*on\s*display\s*":\d+\.\d+"\.\s*$/.test(stderrLog) ){
log.info('RANDR', 'stderr contains only RANDR error, ignored');
return callback();
}
return callback(err);
}
return callback();
});
return;
}
if ((process.arch != opts.target_arch) ||
(process.platform != opts.target_platform)) {
var msg = "skipping validation since host platform/arch (";
msg += process.platform+'/'+process.arch+")";
msg += " does not match target (";
msg += opts.target_platform+'/'+opts.target_arch+")";
log.info('validate', msg);
return callback();
}
args.push('--eval');
args.push("require('" + binary_module.replace(/\'/g, '\\\'') +"')");
log.info("validate","Running test command: '" + shell_cmd + ' ' + args.join(' ') + "'");
cp.execFile(shell_cmd, args, options, function(err, stdout, stderr) {
if (err) {
return callback(err);
}
return callback();
});
}

View File

@ -0,0 +1,49 @@
module.exports = exports = testpackage
exports.usage = 'Tests that the staged package is valid'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, existsAsync = fs.exists || path.exists
, versioning = require('./util/versioning.js')
, testbinary = require('./testbinary.js')
, read = require('fs').createReadStream
, tar = require('tar')
, zlib = require('zlib')
function testpackage(gyp, argv, callback) {
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
var tarball = opts.staged_tarball;
existsAsync(tarball, function(found) {
if (!found) {
return callback(new Error("Cannot test package because " + tarball + " missing: run `node-pre-gyp package` first"))
}
var to = opts.module_path;
var gunzip = zlib.createGunzip()
var extracter = tar.Extract({ path: to, strip: 1 });
function filter_func(entry) {
// ensure directories are +x
// https://github.com/mapnik/node-mapnik/issues/262
entry.props.mode |= (entry.props.mode >>> 2) & 0111;
log.info('install','unpacking ' + entry.path);
}
gunzip.on('error', callback)
extracter.on('error', callback)
extracter.on('entry', filter_func)
extracter.on('end', function(err) {
if (err) return callback(err);
testbinary(gyp,argv,function(err) {
if (err) {
return callback(err);
} else {
console.log('['+package_json.name+'] Package appears valid');
return callback();
}
});
});
read(tarball).pipe(gunzip).pipe(extracter);
});
}

View File

@ -0,0 +1,41 @@
module.exports = exports = unpublish
exports.usage = 'Unpublishes pre-built binary (requires aws-sdk)'
var fs = require('fs')
, path = require('path')
, log = require('npmlog')
, versioning = require('./util/versioning.js')
, s3_setup = require('./util/s3_setup.js')
, url = require('url')
, config = require('rc')("node_pre_gyp",{acl:"public-read"});
function unpublish(gyp, argv, callback) {
var AWS = require("aws-sdk");
var package_json = JSON.parse(fs.readFileSync('./package.json'));
var opts = versioning.evaluate(package_json, gyp.opts);
s3_setup.detect(opts.hosted_path,config);
AWS.config.update(config);
var key_name = url.resolve(config.prefix,opts.package_name)
var s3 = new AWS.S3();
var s3_opts = { Bucket: config.bucket,
Key: key_name
};
s3.headObject(s3_opts, function(err, meta) {
if (err && err.code == 'NotFound') {
console.log('['+package_json.name+'] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
return callback();
} else if(err) {
return callback(err);
} else {
log.info(JSON.stringify(meta));
s3.deleteObject(s3_opts, function(err, resp) {
if (err) return callback(err);
log.info(JSON.stringify(resp));
console.log('['+package_json.name+'] Success: removed https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key);
return callback();
})
}
});
}

View File

@ -0,0 +1,474 @@
{
"0.6.3": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.4": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.5": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.6": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.7": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.8": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.9": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.10": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.11": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.12": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.13": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.14": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.15": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.16": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.17": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.18": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.19": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.20": {
"node_abi": 1,
"v8": "3.6"
},
"0.6.21": {
"node_abi": 1,
"v8": "3.6"
},
"0.7.0": {
"node_abi": 1,
"v8": "3.8"
},
"0.7.1": {
"node_abi": 1,
"v8": "3.8"
},
"0.7.2": {
"node_abi": 1,
"v8": "3.8"
},
"0.7.3": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.4": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.5": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.6": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.7": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.8": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.9": {
"node_abi": 1,
"v8": "3.11"
},
"0.7.10": {
"node_abi": 1,
"v8": "3.9"
},
"0.7.11": {
"node_abi": 1,
"v8": "3.11"
},
"0.7.12": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.0": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.1": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.2": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.3": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.4": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.5": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.6": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.7": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.8": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.9": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.10": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.11": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.12": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.13": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.14": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.15": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.16": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.17": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.18": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.19": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.20": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.21": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.22": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.23": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.24": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.25": {
"node_abi": 1,
"v8": "3.11"
},
"0.8.26": {
"node_abi": 1,
"v8": "3.11"
},
"0.9.0": {
"node_abi": 1,
"v8": "3.11"
},
"0.9.1": {
"node_abi": 10,
"v8": "3.11"
},
"0.9.2": {
"node_abi": 10,
"v8": "3.11"
},
"0.9.3": {
"node_abi": 10,
"v8": "3.13"
},
"0.9.4": {
"node_abi": 10,
"v8": "3.13"
},
"0.9.5": {
"node_abi": 10,
"v8": "3.13"
},
"0.9.6": {
"node_abi": 10,
"v8": "3.15"
},
"0.9.7": {
"node_abi": 10,
"v8": "3.15"
},
"0.9.8": {
"node_abi": 10,
"v8": "3.15"
},
"0.9.9": {
"node_abi": 11,
"v8": "3.15"
},
"0.9.10": {
"node_abi": 11,
"v8": "3.15"
},
"0.9.11": {
"node_abi": 11,
"v8": "3.14"
},
"0.9.12": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.0": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.1": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.2": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.3": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.4": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.5": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.6": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.7": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.8": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.9": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.10": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.11": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.12": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.13": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.14": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.15": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.16": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.17": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.18": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.19": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.20": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.21": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.22": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.23": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.24": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.25": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.26": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.27": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.28": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.29": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.30": {
"node_abi": 11,
"v8": "3.14"
},
"0.10.31": {
"node_abi": 11,
"v8": "3.14"
},
"0.11.0": {
"node_abi": 12,
"v8": "3.17"
},
"0.11.1": {
"node_abi": 12,
"v8": "3.18"
},
"0.11.2": {
"node_abi": 12,
"v8": "3.19"
},
"0.11.3": {
"node_abi": 12,
"v8": "3.19"
},
"0.11.4": {
"node_abi": 12,
"v8": "3.20"
},
"0.11.5": {
"node_abi": 12,
"v8": "3.20"
},
"0.11.6": {
"node_abi": 12,
"v8": "3.20"
},
"0.11.7": {
"node_abi": 12,
"v8": "3.20"
},
"0.11.8": {
"node_abi": 13,
"v8": "3.21"
},
"0.11.9": {
"node_abi": 13,
"v8": "3.22"
},
"0.11.10": {
"node_abi": 13,
"v8": "3.22"
},
"0.11.11": {
"node_abi": 14,
"v8": "3.22"
},
"0.11.12": {
"node_abi": 14,
"v8": "3.22"
},
"0.11.13": {
"node_abi": 14,
"v8": "3.25"
}
}

View File

@ -0,0 +1,80 @@
module.exports = exports;
var fs = require('fs')
, tar = require('tar')
, path = require('path')
, zlib = require('zlib')
, log = require('npmlog')
, semver = require('semver')
, request = require('request')
, win = process.platform == 'win32'
, os = require('os')
, existsSync = fs.existsSync || path.existsSync
, cp = require('child_process')
// try to build up the complete path to node-gyp
/* priority:
- node-gyp on NODE_PATH
- node-gyp inside npm on NODE_PATH
- node-gyp inside npm beside node exe
*/
function which_node_gyp() {
try {
var node_gyp_main = require.resolve('node-gyp');
var node_gyp_bin = path.join(path.dirname(
path.dirname(node_gyp_main))
,'bin/node-gyp.js');
if (existsSync(node_gyp_bin)) {
return node_gyp_bin;
}
} catch (err) { }
try {
var npm_main = require.resolve('npm');
var node_gyp_bin = path.join(path.dirname(
path.dirname(npm_main))
,'node_modules/node-gyp/bin/node-gyp.js');
if (existsSync(node_gyp_bin)) {
return node_gyp_bin;
}
} catch (err) { }
var npm_base = path.join(path.dirname(
path.dirname(process.execPath))
,'lib/node_modules/npm/')
var node_gyp_bin = path.join(npm_base,'node_modules/node-gyp/bin/node-gyp.js');
if (existsSync(node_gyp_bin)) {
return node_gyp_bin;
}
}
module.exports.run_gyp = function(args,opts,callback) {
var shell_cmd = '';
var cmd_args = [];
if (opts.runtime && opts.runtime == 'node-webkit') {
shell_cmd = 'nw-gyp';
if (win) shell_cmd += '.cmd';
} else {
var node_gyp_path = which_node_gyp();
if (node_gyp_path) {
shell_cmd = process.execPath;
cmd_args.push(node_gyp_path);
} else {
shell_cmd = 'node-gyp';
if (win) shell_cmd += '.cmd';
}
}
var final_args = cmd_args.concat(args);
var cmd = cp.spawn(shell_cmd, final_args, {cwd: undefined, env: process.env, customFds: [ 0, 1, 2]});
cmd.on('error', function (err) {
if (err) {
return callback(new Error("Failed to execute '" + shell_cmd + ' ' + final_args.join(' ') + "' (" + err + ")"));
}
callback(null,opts);
});
cmd.on('close', function (code, signal) {
if (code && code !== 0) {
return callback(new Error("Failed to execute '" + shell_cmd + ' ' + final_args.join(' ') + "' (" + code + ")"));
}
callback(null,opts);
});
}

View File

@ -0,0 +1,26 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Node-webkit-based module test</title>
<script>
function nwModuleTest(){
var util = require('util');
var moduleFolder = require('nw.gui').App.argv[0];
try {
require(moduleFolder);
} catch(e) {
if( process.platform !== 'win32' ){
util.log('nw-pre-gyp error:');
util.log(e.stack);
}
process.exit(1);
}
process.exit(0);
}
</script>
</head>
<body onload="nwModuleTest()">
<h1>Node-webkit-based module test</h1>
</body>
</html>

View File

@ -0,0 +1,9 @@
{
"main": "index.html",
"name": "nw-pre-gyp-module-test",
"description": "Node-webkit-based module test.",
"version": "0.0.1",
"window": {
"show": false
}
}

View File

@ -0,0 +1,30 @@
module.exports = exports;
var url = require('url')
var URI_REGEX="^(.*)\.(s3(?:-.*)?)\.amazonaws\.com$";
module.exports.detect = function(to,config) {
var uri = url.parse(to);
var hostname_matches = uri.hostname.match(URI_REGEX);
config.prefix = (!uri.pathname || uri.pathname == '/') ? '' : uri.pathname.replace('/','');
if(!hostname_matches) {
return;
}
if (!config.bucket) {
config.bucket = hostname_matches[1];
}
if (!config.region) {
var s3_domain = hostname_matches[2];
if (s3_domain.slice(0,3) == 's3-' &&
s3_domain.length >= 3) {
// it appears the region is explicit in the url
config.region = s3_domain.replace('s3-','');
}
}
}

View File

@ -0,0 +1,159 @@
module.exports = exports;
var path = require('path')
, semver = require('semver')
, url = require('url')
, abi_crosswalk = require('./abi_crosswalk.json')
function get_node_abi(runtime, target) {
if (target) {
// abi_crosswalk generated with ./scripts/abi_crosswalk.js
var abi = '';
if (runtime === 'node-webkit') {
return runtime + '-v' + target;
} else {
if (abi_crosswalk[target]) {
abi = abi_crosswalk[target].node_abi;
}
}
if (!abi) {
throw new Error("Unsupported target version: " + target);
}
if (abi > 1) {
return runtime+'-v' + (+abi);
} else {
// no support for node-webkit unless > 0.10.x
if (runtime != 'node') {
throw new Error("Runtime '" + runtime + "' unsupported for target version: " + target);
}
if (!abi_crosswalk[target]) {
throw new Error("Unsupported target version: " + target);
}
abi = abi_crosswalk[target].v8;
return 'v8-' + abi;
}
} else {
if (runtime === 'node-webkit') {
if (typeof process.versions['node-webkit'] === 'undefined') {
// erroneous CLI call
throw new Error("Empty target version is not supported if node-webkit is the target.");
}
return runtime + '-v' + process.versions['node-webkit'];
}
// process.versions.modules added in >= v0.10.4 and v0.11.7
// https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
return process.versions.modules ? runtime+'-v' + (+process.versions.modules) :
'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
}
}
var required_parameters = [
'module_name',
'module_path',
'host'
];
function validate_config(package_json,callback) {
var msg = package_json.name + ' package.json is not node-pre-gyp ready:\n';
var missing = [];
if (!package_json.main) {
missing.push('main');
}
if (!package_json.name) {
missing.push('name');
}
if (!package_json.binary) {
missing.push('binary');
}
var o = package_json.binary;
required_parameters.forEach(function(p) {
if (missing.indexOf('binary') > -1) {
missing.pop('binary');
}
if (!o || o[p] == undefined) {
missing.push('binary.' + p);
}
});
if (missing.length >= 1) {
throw new Error(msg+"package.json must declare these properties: \n" + missing.join('\n'));
}
if (o) {
// enforce https over http
var protocol = url.parse(o.host).protocol;
if (protocol === 'http:') {
throw new Error("'host' protocol ("+protocol+") is invalid - only 'https:' is accepted");
}
}
};
module.exports.validate_config = validate_config;
function eval_template(template,opts) {
Object.keys(opts).forEach(function(key) {
var pattern = '{'+key+'}';
while (template.indexOf(pattern) > -1) {
template = template.replace(pattern,opts[key]);
}
});
return template;
}
// url.resolve needs single trailing slash
// to behave correctly, otherwise a double slash
// may end up in the url which breaks requests
// and a lacking slash may not lead to proper joining
function add_trailing_slash(pathname) {
if (pathname.slice(-1) != '/') {
return pathname + '/';
}
return pathname;
}
var default_package_name = '{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz';
var default_remote_path = '';
module.exports.evaluate = function(package_json,options) {
options = options || {};
validate_config(package_json);
var v = package_json.version;
var module_version = semver.parse(v);
var runtime = options.runtime || (process.versions['node-webkit'] ? 'node-webkit' : 'node');
var opts = {
name: package_json.name
, configuration: Boolean(options.debug) ? 'Debug' : 'Release'
, debug: options.debug
, module_name: package_json.binary.module_name
, version: module_version.version
, prerelease: module_version.prerelease.length ? v.slice(v.indexOf(module_version.prerelease[0])) : ''
, major: module_version.major
, minor: module_version.minor
, patch: module_version.patch
, runtime: runtime
, node_abi: get_node_abi(runtime,options.target)
, target: options.target || ''
, platform: options.target_platform || process.platform
, target_platform: options.target_platform || process.platform
, arch: options.target_arch || process.arch
, target_arch: options.target_arch || process.arch
, module_main: package_json.main
}
opts.host = add_trailing_slash(eval_template(package_json.binary.host,opts));
opts.module_path = eval_template(package_json.binary.module_path,opts);
// now we resolve the module_path to ensure it is absolute so that binding.gyp variables work predictably
if (options.module_root) {
// resolve relative to known module root: works for pre-binding require
opts.module_path = path.join(options.module_root,opts.module_path);
} else {
// resolve relative to current working directory: works for node-pre-gyp commands
opts.module_path = path.resolve(opts.module_path);
}
opts.module = path.join(opts.module_path,opts.module_name + '.node')
opts.remote_path = package_json.binary.remote_path ? add_trailing_slash(eval_template(package_json.binary.remote_path,opts)) : default_remote_path;
var package_name = package_json.binary.package_name ? package_json.binary.package_name : default_package_name;
opts.package_name = eval_template(package_name,opts);
opts.staged_tarball = path.join('build/stage',opts.remote_path,opts.package_name);
opts.hosted_path = url.resolve(opts.host,opts.remote_path);
opts.hosted_tarball = url.resolve(opts.hosted_path,opts.package_name);
return opts;
}

View File

@ -0,0 +1 @@
../mkdirp/bin/cmd.js

View File

@ -0,0 +1 @@
../nopt/bin/nopt.js

View File

@ -0,0 +1 @@
../rc/index.js

View File

@ -0,0 +1 @@
../rimraf/bin.js

View File

@ -0,0 +1 @@
../semver/bin/semver

View File

@ -0,0 +1,2 @@
node_modules/
npm-debug.log

View File

@ -0,0 +1,5 @@
language: node_js
node_js:
- 0.6
- 0.8
- "0.10"

View File

@ -0,0 +1,21 @@
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.

View File

@ -0,0 +1,33 @@
#!/usr/bin/env node
var mkdirp = require('../');
var minimist = require('minimist');
var fs = require('fs');
var argv = minimist(process.argv.slice(2), {
alias: { m: 'mode', h: 'help' },
string: [ 'mode' ]
});
if (argv.help) {
fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
return;
}
var paths = argv._.slice();
var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
(function next () {
if (paths.length === 0) return;
var p = paths.shift();
if (mode === undefined) mkdirp(p, cb)
else mkdirp(p, mode, cb)
function cb (err) {
if (err) {
console.error(err.message);
process.exit(1);
}
else next();
}
})();

View File

@ -0,0 +1,12 @@
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.

View File

@ -0,0 +1,6 @@
var mkdirp = require('mkdirp');
mkdirp('/tmp/foo/bar/baz', function (err) {
if (err) console.error(err)
else console.log('pow!')
});

View File

@ -0,0 +1,97 @@
var path = require('path');
var fs = require('fs');
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
function mkdirP (p, opts, f, made) {
if (typeof opts === 'function') {
f = opts;
opts = {};
}
else if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = 0777 & (~process.umask());
}
if (!made) made = null;
var cb = f || function () {};
p = path.resolve(p);
xfs.mkdir(p, mode, function (er) {
if (!er) {
made = made || p;
return cb(null, made);
}
switch (er.code) {
case 'ENOENT':
mkdirP(path.dirname(p), opts, function (er, made) {
if (er) cb(er, made);
else mkdirP(p, opts, cb, made);
});
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
xfs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
if (er2 || !stat.isDirectory()) cb(er, made)
else cb(null, made);
});
break;
}
});
}
mkdirP.sync = function sync (p, opts, made) {
if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = 0777 & (~process.umask());
}
if (!made) made = null;
p = path.resolve(p);
try {
xfs.mkdirSync(p, mode);
made = made || p;
}
catch (err0) {
switch (err0.code) {
case 'ENOENT' :
made = sync(path.dirname(p), opts, made);
sync(p, opts, made);
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
var stat;
try {
stat = xfs.statSync(p);
}
catch (err1) {
throw err0;
}
if (!stat.isDirectory()) throw err0;
break;
}
}
return made;
};

View File

@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.8"
- "0.10"

View File

@ -0,0 +1,18 @@
This software is released under the MIT 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.

View File

@ -0,0 +1,2 @@
var argv = require('../')(process.argv.slice(2));
console.dir(argv);

View File

@ -0,0 +1,187 @@
module.exports = function (args, opts) {
if (!opts) opts = {};
var flags = { bools : {}, strings : {} };
[].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
flags.bools[key] = true;
});
[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true;
});
var aliases = {};
Object.keys(opts.alias || {}).forEach(function (key) {
aliases[key] = [].concat(opts.alias[key]);
aliases[key].forEach(function (x) {
aliases[x] = [key].concat(aliases[key].filter(function (y) {
return x !== y;
}));
});
});
var defaults = opts['default'] || {};
var argv = { _ : [] };
Object.keys(flags.bools).forEach(function (key) {
setArg(key, defaults[key] === undefined ? false : defaults[key]);
});
var notFlags = [];
if (args.indexOf('--') !== -1) {
notFlags = args.slice(args.indexOf('--')+1);
args = args.slice(0, args.indexOf('--'));
}
function setArg (key, val) {
var value = !flags.strings[key] && isNumber(val)
? Number(val) : val
;
setKey(argv, key.split('.'), value);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), value);
});
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (/^--.+=/.test(arg)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
setArg(m[1], m[2]);
}
else if (/^--no-.+/.test(arg)) {
var key = arg.match(/^--no-(.+)/)[1];
setArg(key, false);
}
else if (/^--.+/.test(arg)) {
var key = arg.match(/^--(.+)/)[1];
var next = args[i + 1];
if (next !== undefined && !/^-/.test(next)
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, next);
i++;
}
else if (/^(true|false)$/.test(next)) {
setArg(key, next === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
else if (/^-[^-]+/.test(arg)) {
var letters = arg.slice(1,-1).split('');
var broken = false;
for (var j = 0; j < letters.length; j++) {
var next = arg.slice(j+2);
if (next === '-') {
setArg(letters[j], next)
continue;
}
if (/[A-Za-z]/.test(letters[j])
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next);
broken = true;
break;
}
if (letters[j+1] && letters[j+1].match(/\W/)) {
setArg(letters[j], arg.slice(j+2));
broken = true;
break;
}
else {
setArg(letters[j], flags.strings[letters[j]] ? '' : true);
}
}
var key = arg.slice(-1)[0];
if (!broken && key !== '-') {
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, args[i+1]);
i++;
}
else if (args[i+1] && /true|false/.test(args[i+1])) {
setArg(key, args[i+1] === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
}
else {
argv._.push(
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
);
}
}
Object.keys(defaults).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) {
setKey(argv, key.split('.'), defaults[key]);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), defaults[key]);
});
}
});
notFlags.forEach(function(key) {
argv._.push(key);
});
return argv;
};
function hasKey (obj, keys) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
o = (o[key] || {});
});
var key = keys[keys.length - 1];
return key in o;
}
function setKey (obj, keys, value) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
if (o[key] === undefined) o[key] = {};
o = o[key];
});
var key = keys[keys.length - 1];
if (o[key] === undefined || typeof o[key] === 'boolean') {
o[key] = value;
}
else if (Array.isArray(o[key])) {
o[key].push(value);
}
else {
o[key] = [ o[key], value ];
}
}
function isNumber (x) {
if (typeof x === 'number') return true;
if (/^0x[0-9a-f]+$/i.test(x)) return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
}
function longest (xs) {
return Math.max.apply(null, xs.map(function (x) { return x.length }));
}

View File

@ -0,0 +1,67 @@
{
"name": "minimist",
"version": "0.0.8",
"description": "parse argument options",
"main": "index.js",
"devDependencies": {
"tape": "~1.0.4",
"tap": "~0.4.0"
},
"scripts": {
"test": "tap test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/6..latest",
"ff/5",
"firefox/latest",
"chrome/10",
"chrome/latest",
"safari/5.1",
"safari/latest",
"opera/12"
]
},
"repository": {
"type": "git",
"url": "git://github.com/substack/minimist.git"
},
"homepage": "https://github.com/substack/minimist",
"keywords": [
"argv",
"getopt",
"parser",
"optimist"
],
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/substack/minimist/issues"
},
"_id": "minimist@0.0.8",
"dist": {
"shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
"tarball": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
},
"_from": "minimist@0.0.8",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "substack",
"email": "mail@substack.net"
},
"maintainers": [
{
"name": "substack",
"email": "mail@substack.net"
}
],
"directories": {},
"_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"readme": "ERROR: No README data found!"
}

View File

@ -0,0 +1,73 @@
# minimist
parse argument options
This module is the guts of optimist's argument parser without all the
fanciful decoration.
[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
# example
``` js
var argv = require('minimist')(process.argv.slice(2));
console.dir(argv);
```
```
$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
```
```
$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }
```
# methods
``` js
var parseArgs = require('minimist')
```
## var argv = parseArgs(args, opts={})
Return an argument object `argv` populated with the array arguments from `args`.
`argv._` contains all the arguments that didn't have an option associated with
them.
Numeric-looking arguments will be returned as numbers unless `opts.string` or
`opts.boolean` is set for that argument name.
Any arguments after `'--'` will not be parsed and will end up in `argv._`.
options can be:
* `opts.string` - a string or array of strings argument names to always treat as
strings
* `opts.boolean` - a string or array of strings to always treat as booleans
* `opts.alias` - an object mapping string names to strings or arrays of string
argument names to use as aliases
* `opts.default` - an object mapping string argument names to default values
# install
With [npm](https://npmjs.org) do:
```
npm install minimist
```
# license
MIT

View File

@ -0,0 +1,24 @@
var parse = require('../');
var test = require('tape');
test('-', function (t) {
t.plan(5);
t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
t.deepEqual(
parse([ '-b', '-' ], { boolean: 'b' }),
{ b: true, _: [ '-' ] }
);
t.deepEqual(
parse([ '-s', '-' ], { string: 's' }),
{ s: '-', _: [] }
);
});
test('-a -- b', function (t) {
t.plan(3);
t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
});

View File

@ -0,0 +1,20 @@
var test = require('tape');
var parse = require('../');
test('boolean default true', function (t) {
var argv = parse([], {
boolean: 'sometrue',
default: { sometrue: true }
});
t.equal(argv.sometrue, true);
t.end();
});
test('boolean default false', function (t) {
var argv = parse([], {
boolean: 'somefalse',
default: { somefalse: false }
});
t.equal(argv.somefalse, false);
t.end();
});

View File

@ -0,0 +1,16 @@
var parse = require('../');
var test = require('tape');
test('dotted alias', function (t) {
var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 22);
t.equal(argv.aa.bb, 22);
t.end();
});
test('dotted default', function (t) {
var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 11);
t.equal(argv.aa.bb, 11);
t.end();
});

View File

@ -0,0 +1,31 @@
var test = require('tape');
var parse = require('../');
test('long opts', function (t) {
t.deepEqual(
parse([ '--bool' ]),
{ bool : true, _ : [] },
'long boolean'
);
t.deepEqual(
parse([ '--pow', 'xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture sp'
);
t.deepEqual(
parse([ '--pow=xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture eq'
);
t.deepEqual(
parse([ '--host', 'localhost', '--port', '555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures sp'
);
t.deepEqual(
parse([ '--host=localhost', '--port=555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures eq'
);
t.end();
});

View File

@ -0,0 +1,318 @@
var parse = require('../');
var test = require('tape');
test('parse args', function (t) {
t.deepEqual(
parse([ '--no-moo' ]),
{ moo : false, _ : [] },
'no'
);
t.deepEqual(
parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
{ v : ['a','b','c'], _ : [] },
'multi'
);
t.end();
});
test('comprehensive', function (t) {
t.deepEqual(
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' ]
}
);
t.end();
});
test('nums', function (t) {
var argv = parse([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789'
]);
t.deepEqual(argv, {
x : 1234,
y : 5.67,
z : 1e7,
w : '10f',
hex : 0xdeadbeef,
_ : [ 789 ]
});
t.deepEqual(typeof argv.x, 'number');
t.deepEqual(typeof argv.y, 'number');
t.deepEqual(typeof argv.z, 'number');
t.deepEqual(typeof argv.w, 'string');
t.deepEqual(typeof argv.hex, 'number');
t.deepEqual(typeof argv._[0], 'number');
t.end();
});
test('flag boolean', function (t) {
var argv = parse([ '-t', 'moo' ], { boolean: 't' });
t.deepEqual(argv, { t : true, _ : [ 'moo' ] });
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('flag boolean value', function (t) {
var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
boolean: [ 't', 'verbose' ],
default: { verbose: true }
});
t.deepEqual(argv, {
verbose: false,
t: true,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('flag boolean default false', function (t) {
var argv = parse(['moo'], {
boolean: ['t', 'verbose'],
default: { verbose: false, t: false }
});
t.deepEqual(argv, {
verbose: false,
t: false,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('boolean groups', function (t) {
var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
boolean: ['x','y','z']
});
t.deepEqual(argv, {
x : true,
y : false,
z : true,
_ : [ 'one', 'two', 'three' ]
});
t.deepEqual(typeof argv.x, 'boolean');
t.deepEqual(typeof argv.y, 'boolean');
t.deepEqual(typeof argv.z, 'boolean');
t.end();
});
test('newlines in params' , function (t) {
var args = parse([ '-s', "X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
// reproduce in bash:
// VALUE="new
// line"
// node program.js --s="$VALUE"
args = parse([ "--s=X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
t.end();
});
test('strings' , function (t) {
var s = parse([ '-s', '0001234' ], { string: 's' }).s;
t.equal(s, '0001234');
t.equal(typeof s, 'string');
var x = parse([ '-x', '56' ], { string: 'x' }).x;
t.equal(x, '56');
t.equal(typeof x, 'string');
t.end();
});
test('stringArgs', function (t) {
var s = parse([ ' ', ' ' ], { string: '_' })._;
t.same(s.length, 2);
t.same(typeof s[0], 'string');
t.same(s[0], ' ');
t.same(typeof s[1], 'string');
t.same(s[1], ' ');
t.end();
});
test('empty strings', function(t) {
var s = parse([ '-s' ], { string: 's' }).s;
t.equal(s, '');
t.equal(typeof s, 'string');
var str = parse([ '--str' ], { string: 'str' }).str;
t.equal(str, '');
t.equal(typeof str, 'string');
var letters = parse([ '-art' ], {
string: [ 'a', 't' ]
});
t.equal(letters.a, '');
t.equal(letters.r, true);
t.equal(letters.t, '');
t.end();
});
test('slashBreak', function (t) {
t.same(
parse([ '-I/foo/bar/baz' ]),
{ I : '/foo/bar/baz', _ : [] }
);
t.same(
parse([ '-xyz/foo/bar/baz' ]),
{ x : true, y : true, z : '/foo/bar/baz', _ : [] }
);
t.end();
});
test('alias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: 'zoom' }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.f, 11);
t.end();
});
test('multiAlias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: [ 'zm', 'zoom' ] }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.z, argv.zm);
t.equal(argv.f, 11);
t.end();
});
test('nested dotted objects', function (t) {
var argv = parse([
'--foo.bar', '3', '--foo.baz', '4',
'--foo.quux.quibble', '5', '--foo.quux.o_O',
'--beep.boop'
]);
t.same(argv.foo, {
bar : 3,
baz : 4,
quux : {
quibble : 5,
o_O : true
}
});
t.same(argv.beep, { boop : true });
t.end();
});
test('boolean and alias with chainable api', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
herp: { alias: 'h', boolean: true }
};
var aliasedArgv = parse(aliased, {
boolean: 'herp',
alias: { h: 'herp' }
});
var propertyArgv = parse(regular, {
boolean: 'herp',
alias: { h: 'herp' }
});
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias with options hash', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
alias: { 'h': 'herp' },
boolean: 'herp'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias using explicit true', function (t) {
var aliased = [ '-h', 'true' ];
var regular = [ '--herp', 'true' ];
var opts = {
alias: { h: 'herp' },
boolean: 'h'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
// regression, see https://github.com/substack/node-optimist/issues/71
test('boolean and --x=true', function(t) {
var parsed = parse(['--boool', '--other=true'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'true');
parsed = parse(['--boool', '--other=false'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'false');
t.end();
});

View File

@ -0,0 +1,9 @@
var parse = require('../');
var test = require('tape');
test('parse with modifier functions' , function (t) {
t.plan(1);
var argv = parse([ '-b', '123' ], { boolean: 'b' });
t.deepEqual(argv, { b: true, _: ['123'] });
});

View File

@ -0,0 +1,67 @@
var parse = require('../');
var test = require('tape');
test('numeric short args', function (t) {
t.plan(2);
t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] });
t.deepEqual(
parse([ '-123', '456' ]),
{ 1: true, 2: true, 3: 456, _: [] }
);
});
test('short', function (t) {
t.deepEqual(
parse([ '-b' ]),
{ b : true, _ : [] },
'short boolean'
);
t.deepEqual(
parse([ 'foo', 'bar', 'baz' ]),
{ _ : [ 'foo', 'bar', 'baz' ] },
'bare'
);
t.deepEqual(
parse([ '-cats' ]),
{ c : true, a : true, t : true, s : true, _ : [] },
'group'
);
t.deepEqual(
parse([ '-cats', 'meow' ]),
{ c : true, a : true, t : true, s : 'meow', _ : [] },
'short group next'
);
t.deepEqual(
parse([ '-h', 'localhost' ]),
{ h : 'localhost', _ : [] },
'short capture'
);
t.deepEqual(
parse([ '-h', 'localhost', '-p', '555' ]),
{ h : 'localhost', p : 555, _ : [] },
'short captures'
);
t.end();
});
test('mixed short bool and capture', function (t) {
t.same(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});
test('short and long', function (t) {
t.deepEqual(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});

View File

@ -0,0 +1,8 @@
var parse = require('../');
var test = require('tape');
test('whitespace should be whitespace' , function (t) {
t.plan(1);
var x = parse([ '-x', '\t' ]).x;
t.equal(x, '\t');
});

View File

@ -0,0 +1,58 @@
{
"name": "mkdirp",
"description": "Recursively mkdir, like `mkdir -p`",
"version": "0.5.0",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"main": "./index",
"keywords": [
"mkdir",
"directory"
],
"repository": {
"type": "git",
"url": "https://github.com/substack/node-mkdirp.git"
},
"scripts": {
"test": "tap test/*.js"
},
"dependencies": {
"minimist": "0.0.8"
},
"devDependencies": {
"tap": "~0.4.0",
"mock-fs": "~2.2.0"
},
"bin": {
"mkdirp": "bin/cmd.js"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/substack/node-mkdirp/issues"
},
"homepage": "https://github.com/substack/node-mkdirp",
"_id": "mkdirp@0.5.0",
"dist": {
"shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12",
"tarball": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz"
},
"_from": "mkdirp@~0.5.0",
"_npmVersion": "1.4.3",
"_npmUser": {
"name": "substack",
"email": "mail@substack.net"
},
"maintainers": [
{
"name": "substack",
"email": "mail@substack.net"
}
],
"directories": {},
"_shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12",
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
"readme": "ERROR: No README data found!"
}

View File

@ -0,0 +1,100 @@
# mkdirp
Like `mkdir -p`, but in node.js!
[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
# example
## pow.js
```js
var mkdirp = require('mkdirp');
mkdirp('/tmp/foo/bar/baz', function (err) {
if (err) console.error(err)
else console.log('pow!')
});
```
Output
```
pow!
```
And now /tmp/foo/bar/baz exists, huzzah!
# methods
```js
var mkdirp = require('mkdirp');
```
## mkdirp(dir, opts, cb)
Create a new directory and any necessary subdirectories at `dir` with octal
permission string `opts.mode`. If `opts` is a non-object, it will be treated as
the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
`cb(err, made)` fires with the error or the first directory `made`
that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and
`opts.fs.stat(path, cb)`.
## mkdirp.sync(dir, opts)
Synchronously create a new directory and any necessary subdirectories at `dir`
with octal permission string `opts.mode`. If `opts` is a non-object, it will be
treated as the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
Returns the first directory that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and
`opts.fs.statSync(path)`.
# usage
This package also ships with a `mkdirp` command.
```
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.
```
# install
With [npm](http://npmjs.org) do:
```
npm install mkdirp
```
to get the library, or
```
npm install -g mkdirp
```
to get the command.
# license
MIT

View File

@ -0,0 +1,38 @@
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
test('chmod-pre', function (t) {
var mode = 0744
mkdirp(file, mode, function (er) {
t.ifError(er, 'should not error');
fs.stat(file, function (er, stat) {
t.ifError(er, 'should exist');
t.ok(stat && stat.isDirectory(), 'should be directory');
t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
t.end();
});
});
});
test('chmod', function (t) {
var mode = 0755
mkdirp(file, mode, function (er) {
t.ifError(er, 'should not error');
fs.stat(file, function (er, stat) {
t.ifError(er, 'should exist');
t.ok(stat && stat.isDirectory(), 'should be directory');
t.end();
});
});
});

View File

@ -0,0 +1,37 @@
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
// a file in the way
var itw = ps.slice(0, 3).join('/');
test('clobber-pre', function (t) {
console.error("about to write to "+itw)
fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
fs.stat(itw, function (er, stat) {
t.ifError(er)
t.ok(stat && stat.isFile(), 'should be file')
t.end()
})
})
test('clobber', function (t) {
t.plan(2);
mkdirp(file, 0755, function (err) {
t.ok(err);
t.equal(err.code, 'ENOTDIR');
t.end();
});
});

View File

@ -0,0 +1,26 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('woo', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
mkdirp(file, 0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});

View File

@ -0,0 +1,27 @@
var mkdirp = require('../');
var path = require('path');
var test = require('tap').test;
var mockfs = require('mock-fs');
test('opts.fs', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/beep/boop/' + [x,y,z].join('/');
var xfs = mockfs.fs();
mkdirp(file, { fs: xfs, mode: 0755 }, function (err) {
t.ifError(err);
xfs.exists(file, function (ex) {
t.ok(ex, 'created file');
xfs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
});

View File

@ -0,0 +1,25 @@
var mkdirp = require('../');
var path = require('path');
var test = require('tap').test;
var mockfs = require('mock-fs');
test('opts.fs sync', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/beep/boop/' + [x,y,z].join('/');
var xfs = mockfs.fs();
mkdirp.sync(file, { fs: xfs, mode: 0755 });
xfs.exists(file, function (ex) {
t.ok(ex, 'created file');
xfs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});

View File

@ -0,0 +1,30 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('async perm', function (t) {
t.plan(5);
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
mkdirp(file, 0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});
test('async root perm', function (t) {
mkdirp('/tmp', 0755, function (err) {
if (err) t.fail(err);
t.end();
});
t.end();
});

View File

@ -0,0 +1,34 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('sync perm', function (t) {
t.plan(4);
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
mkdirp.sync(file, 0755);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
test('sync root perm', function (t) {
t.plan(3);
var file = '/tmp';
mkdirp.sync(file, 0755);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.ok(stat.isDirectory(), 'target not a directory');
})
});
});

View File

@ -0,0 +1,40 @@
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('race', function (t) {
t.plan(6);
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
var res = 2;
mk(file, function () {
if (--res === 0) t.end();
});
mk(file, function () {
if (--res === 0) t.end();
});
function mk (file, cb) {
mkdirp(file, 0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
if (cb) cb();
});
})
});
}
});

View File

@ -0,0 +1,30 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('rel', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var cwd = process.cwd();
process.chdir('/tmp');
var file = [x,y,z].join('/');
mkdirp(file, 0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
process.chdir(cwd);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});

View File

@ -0,0 +1,25 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
test('return value', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
// should return the first dir created.
// By this point, it would be profoundly surprising if /tmp didn't
// already exist, since every other test makes things in there.
mkdirp(file, function (err, made) {
t.ifError(err);
t.equal(made, '/tmp/' + x);
mkdirp(file, function (err, made) {
t.ifError(err);
t.equal(made, null);
});
});
});

View File

@ -0,0 +1,24 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
test('return value', function (t) {
t.plan(2);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
// should return the first dir created.
// By this point, it would be profoundly surprising if /tmp didn't
// already exist, since every other test makes things in there.
// Note that this will throw on failure, which will fail the test.
var made = mkdirp.sync(file);
t.equal(made, '/tmp/' + x);
// making the same file again should have no effect.
made = mkdirp.sync(file);
t.equal(made, null);
});

View File

@ -0,0 +1,18 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
test('root', function (t) {
// '/' on unix, 'c:/' on windows.
var file = path.resolve('/');
mkdirp(file, 0755, function (err) {
if (err) throw err
fs.stat(file, function (er, stat) {
if (er) throw er
t.ok(stat.isDirectory(), 'target is a directory');
t.end();
})
});
});

View File

@ -0,0 +1,30 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('sync', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
try {
mkdirp.sync(file, 0755);
} catch (err) {
t.fail(err);
return t.end();
}
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});

View File

@ -0,0 +1,26 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('implicit mode from umask', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
mkdirp(file, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, 0777 & (~process.umask()));
t.ok(stat.isDirectory(), 'target not a directory');
});
})
});
});

View File

@ -0,0 +1,30 @@
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
test('umask sync modes', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
try {
mkdirp.sync(file);
} catch (err) {
t.fail(err);
return t.end();
}
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & 0777, (0777 & (~process.umask())));
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});

View File

@ -0,0 +1 @@
node_modules

View File

@ -0,0 +1,23 @@
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
All rights reserved.
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.

View File

@ -0,0 +1,209 @@
If you want to write an option parser, and have it be good, there are
two ways to do it. The Right Way, and the Wrong Way.
The Wrong Way is to sit down and write an option parser. We've all done
that.
The Right Way is to write some complex configurable program with so many
options that you go half-insane just trying to manage them all, and put
it off with duct-tape solutions until you see exactly to the core of the
problem, and finally snap and write an awesome option parser.
If you want to write an option parser, don't write an option parser.
Write a package manager, or a source control system, or a service
restarter, or an operating system. You probably won't end up with a
good one of those, but if you don't give up, and you are relentless and
diligent enough in your procrastination, you may just end up with a very
nice option parser.
## USAGE
// my-program.js
var nopt = require("nopt")
, Stream = require("stream").Stream
, path = require("path")
, knownOpts = { "foo" : [String, null]
, "bar" : [Stream, Number]
, "baz" : path
, "bloo" : [ "big", "medium", "small" ]
, "flag" : Boolean
, "pick" : Boolean
, "many" : [String, Array]
}
, shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
, "b7" : ["--bar", "7"]
, "m" : ["--bloo", "medium"]
, "p" : ["--pick"]
, "f" : ["--flag"]
}
// everything is optional.
// knownOpts and shorthands default to {}
// arg list defaults to process.argv
// slice defaults to 2
, parsed = nopt(knownOpts, shortHands, process.argv, 2)
console.log(parsed)
This would give you support for any of the following:
```bash
$ node my-program.js --foo "blerp" --no-flag
{ "foo" : "blerp", "flag" : false }
$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag
{ bar: 7, foo: "Mr. Hand", flag: true }
$ node my-program.js --foo "blerp" -f -----p
{ foo: "blerp", flag: true, pick: true }
$ node my-program.js -fp --foofoo
{ foo: "Mr. Foo", flag: true, pick: true }
$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.
{ foo: "Mr. Foo", argv: { remain: ["-fp"] } }
$ node my-program.js --blatzk -fp # unknown opts are ok.
{ blatzk: true, flag: true, pick: true }
$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value
{ blatzk: 1000, flag: true, pick: true }
$ node my-program.js --no-blatzk -fp # unless they start with "no-"
{ blatzk: false, flag: true, pick: true }
$ node my-program.js --baz b/a/z # known paths are resolved.
{ baz: "/Users/isaacs/b/a/z" }
# if Array is one of the types, then it can take many
# values, and will always be an array. The other types provided
# specify what types are allowed in the list.
$ node my-program.js --many 1 --many null --many foo
{ many: ["1", "null", "foo"] }
$ node my-program.js --many foo
{ many: ["foo"] }
```
Read the tests at the bottom of `lib/nopt.js` for more examples of
what this puppy can do.
## Types
The following types are supported, and defined on `nopt.typeDefs`
* String: A normal string. No parsing is done.
* path: A file system path. Gets resolved against cwd if not absolute.
* url: A url. If it doesn't parse, it isn't accepted.
* Number: Must be numeric.
* Date: Must parse as a date. If it does, and `Date` is one of the options,
then it will return a Date object, not a string.
* Boolean: Must be either `true` or `false`. If an option is a boolean,
then it does not need a value, and its presence will imply `true` as
the value. To negate boolean flags, do `--no-whatever` or `--whatever
false`
* NaN: Means that the option is strictly not allowed. Any value will
fail.
* Stream: An object matching the "Stream" class in node. Valuable
for use when validating programmatically. (npm uses this to let you
supply any WriteStream on the `outfd` and `logfd` config options.)
* Array: If `Array` is specified as one of the types, then the value
will be parsed as a list of options. This means that multiple values
can be specified, and that the value will always be an array.
If a type is an array of values not on this list, then those are
considered valid values. For instance, in the example above, the
`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`,
and any other value will be rejected.
When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be
interpreted as their JavaScript equivalents.
You can also mix types and values, or multiple types, in a list. For
instance `{ blah: [Number, null] }` would allow a value to be set to
either a Number or null. When types are ordered, this implies a
preference, and the first type that can be used to properly interpret
the value will be used.
To define a new type, add it to `nopt.typeDefs`. Each item in that
hash is an object with a `type` member and a `validate` method. The
`type` member is an object that matches what goes in the type list. The
`validate` method is a function that gets called with `validate(data,
key, val)`. Validate methods should assign `data[key]` to the valid
value of `val` if it can be handled properly, or return boolean
`false` if it cannot.
You can also call `nopt.clean(data, types, typeDefs)` to clean up a
config object and remove its invalid properties.
## Error Handling
By default, nopt outputs a warning to standard error when invalid
options are found. You can change this behavior by assigning a method
to `nopt.invalidHandler`. This method will be called with
the offending `nopt.invalidHandler(key, val, types)`.
If no `nopt.invalidHandler` is assigned, then it will console.error
its whining. If it is assigned to boolean `false` then the warning is
suppressed.
## Abbreviations
Yes, they are supported. If you define options like this:
```javascript
{ "foolhardyelephants" : Boolean
, "pileofmonkeys" : Boolean }
```
Then this will work:
```bash
node program.js --foolhar --pil
node program.js --no-f --pileofmon
# etc.
```
## Shorthands
Shorthands are a hash of shorter option names to a snippet of args that
they expand to.
If multiple one-character shorthands are all combined, and the
combination does not unambiguously match any other option or shorthand,
then they will be broken up into their constituent parts. For example:
```json
{ "s" : ["--loglevel", "silent"]
, "g" : "--global"
, "f" : "--force"
, "p" : "--parseable"
, "l" : "--long"
}
```
```bash
npm ls -sgflp
# just like doing this:
npm ls --loglevel silent --global --force --long --parseable
```
## The Rest of the args
The config object returned by nopt is given a special member called
`argv`, which is an object with the following fields:
* `remain`: The remaining args after all the parsing has occurred.
* `original`: The args as they originally appeared.
* `cooked`: The args after flags and shorthands are expanded.
## Slicing
Node programs are called with more or less the exact argv as it appears
in C land, after the v8 and node-specific options have been plucked off.
As such, `argv[0]` is always `node` and `argv[1]` is always the
JavaScript program being run.
That's usually not very useful to you. So they're sliced off by
default. If you want them, then you can pass in `0` as the last
argument, or any other number that you'd like to slice off the start of
the list.

View File

@ -0,0 +1,54 @@
#!/usr/bin/env node
var nopt = require("../lib/nopt")
, path = require("path")
, types = { num: Number
, bool: Boolean
, help: Boolean
, list: Array
, "num-list": [Number, Array]
, "str-list": [String, Array]
, "bool-list": [Boolean, Array]
, str: String
, clear: Boolean
, config: Boolean
, length: Number
, file: path
}
, shorthands = { s: [ "--str", "astring" ]
, b: [ "--bool" ]
, nb: [ "--no-bool" ]
, tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ]
, "?": ["--help"]
, h: ["--help"]
, H: ["--help"]
, n: [ "--num", "125" ]
, c: ["--config"]
, l: ["--length"]
, f: ["--file"]
}
, parsed = nopt( types
, shorthands
, process.argv
, 2 )
console.log("parsed", parsed)
if (parsed.help) {
console.log("")
console.log("nopt cli tester")
console.log("")
console.log("types")
console.log(Object.keys(types).map(function M (t) {
var type = types[t]
if (Array.isArray(type)) {
return [t, type.map(function (type) { return type.name })]
}
return [t, type && type.name]
}).reduce(function (s, i) {
s[i[0]] = i[1]
return s
}, {}))
console.log("")
console.log("shorthands")
console.log(shorthands)
}

View File

@ -0,0 +1,30 @@
#!/usr/bin/env node
//process.env.DEBUG_NOPT = 1
// my-program.js
var nopt = require("../lib/nopt")
, Stream = require("stream").Stream
, path = require("path")
, knownOpts = { "foo" : [String, null]
, "bar" : [Stream, Number]
, "baz" : path
, "bloo" : [ "big", "medium", "small" ]
, "flag" : Boolean
, "pick" : Boolean
}
, shortHands = { "foofoo" : ["--foo", "Mr. Foo"]
, "b7" : ["--bar", "7"]
, "m" : ["--bloo", "medium"]
, "p" : ["--pick"]
, "f" : ["--flag", "true"]
, "g" : ["--flag"]
, "s" : "--flag"
}
// everything is optional.
// knownOpts and shorthands default to {}
// arg list defaults to process.argv
// slice defaults to 2
, parsed = nopt(knownOpts, shortHands, process.argv, 2)
console.log("parsed =\n"+ require("util").inspect(parsed))

View File

@ -0,0 +1,414 @@
// info about each config option.
var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG
? function () { console.error.apply(console, arguments) }
: function () {}
var url = require("url")
, path = require("path")
, Stream = require("stream").Stream
, abbrev = require("abbrev")
module.exports = exports = nopt
exports.clean = clean
exports.typeDefs =
{ String : { type: String, validate: validateString }
, Boolean : { type: Boolean, validate: validateBoolean }
, url : { type: url, validate: validateUrl }
, Number : { type: Number, validate: validateNumber }
, path : { type: path, validate: validatePath }
, Stream : { type: Stream, validate: validateStream }
, Date : { type: Date, validate: validateDate }
}
function nopt (types, shorthands, args, slice) {
args = args || process.argv
types = types || {}
shorthands = shorthands || {}
if (typeof slice !== "number") slice = 2
debug(types, shorthands, args, slice)
args = args.slice(slice)
var data = {}
, key
, remain = []
, cooked = args
, original = args.slice(0)
parse(args, data, remain, types, shorthands)
// now data is full
clean(data, types, exports.typeDefs)
data.argv = {remain:remain,cooked:cooked,original:original}
Object.defineProperty(data.argv, 'toString', { value: function () {
return this.original.map(JSON.stringify).join(" ")
}, enumerable: false })
return data
}
function clean (data, types, typeDefs) {
typeDefs = typeDefs || exports.typeDefs
var remove = {}
, typeDefault = [false, true, null, String, Array]
Object.keys(data).forEach(function (k) {
if (k === "argv") return
var val = data[k]
, isArray = Array.isArray(val)
, type = types[k]
if (!isArray) val = [val]
if (!type) type = typeDefault
if (type === Array) type = typeDefault.concat(Array)
if (!Array.isArray(type)) type = [type]
debug("val=%j", val)
debug("types=", type)
val = val.map(function (val) {
// if it's an unknown value, then parse false/true/null/numbers/dates
if (typeof val === "string") {
debug("string %j", val)
val = val.trim()
if ((val === "null" && ~type.indexOf(null))
|| (val === "true" &&
(~type.indexOf(true) || ~type.indexOf(Boolean)))
|| (val === "false" &&
(~type.indexOf(false) || ~type.indexOf(Boolean)))) {
val = JSON.parse(val)
debug("jsonable %j", val)
} else if (~type.indexOf(Number) && !isNaN(val)) {
debug("convert to number", val)
val = +val
} else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) {
debug("convert to date", val)
val = new Date(val)
}
}
if (!types.hasOwnProperty(k)) {
return val
}
// allow `--no-blah` to set 'blah' to null if null is allowed
if (val === false && ~type.indexOf(null) &&
!(~type.indexOf(false) || ~type.indexOf(Boolean))) {
val = null
}
var d = {}
d[k] = val
debug("prevalidated val", d, val, types[k])
if (!validate(d, k, val, types[k], typeDefs)) {
if (exports.invalidHandler) {
exports.invalidHandler(k, val, types[k], data)
} else if (exports.invalidHandler !== false) {
debug("invalid: "+k+"="+val, types[k])
}
return remove
}
debug("validated val", d, val, types[k])
return d[k]
}).filter(function (val) { return val !== remove })
if (!val.length) delete data[k]
else if (isArray) {
debug(isArray, data[k], val)
data[k] = val
} else data[k] = val[0]
debug("k=%s val=%j", k, val, data[k])
})
}
function validateString (data, k, val) {
data[k] = String(val)
}
function validatePath (data, k, val) {
if (val === true) return false
if (val === null) return true
val = String(val)
var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\//
if (val.match(homePattern) && process.env.HOME) {
val = path.resolve(process.env.HOME, val.substr(2))
}
data[k] = path.resolve(String(val))
return true
}
function validateNumber (data, k, val) {
debug("validate Number %j %j %j", k, val, isNaN(val))
if (isNaN(val)) return false
data[k] = +val
}
function validateDate (data, k, val) {
debug("validate Date %j %j %j", k, val, Date.parse(val))
var s = Date.parse(val)
if (isNaN(s)) return false
data[k] = new Date(val)
}
function validateBoolean (data, k, val) {
if (val instanceof Boolean) val = val.valueOf()
else if (typeof val === "string") {
if (!isNaN(val)) val = !!(+val)
else if (val === "null" || val === "false") val = false
else val = true
} else val = !!val
data[k] = val
}
function validateUrl (data, k, val) {
val = url.parse(String(val))
if (!val.host) return false
data[k] = val.href
}
function validateStream (data, k, val) {
if (!(val instanceof Stream)) return false
data[k] = val
}
function validate (data, k, val, type, typeDefs) {
// arrays are lists of types.
if (Array.isArray(type)) {
for (var i = 0, l = type.length; i < l; i ++) {
if (type[i] === Array) continue
if (validate(data, k, val, type[i], typeDefs)) return true
}
delete data[k]
return false
}
// an array of anything?
if (type === Array) return true
// NaN is poisonous. Means that something is not allowed.
if (type !== type) {
debug("Poison NaN", k, val, type)
delete data[k]
return false
}
// explicit list of values
if (val === type) {
debug("Explicitly allowed %j", val)
// if (isArray) (data[k] = data[k] || []).push(val)
// else data[k] = val
data[k] = val
return true
}
// now go through the list of typeDefs, validate against each one.
var ok = false
, types = Object.keys(typeDefs)
for (var i = 0, l = types.length; i < l; i ++) {
debug("test type %j %j %j", k, val, types[i])
var t = typeDefs[types[i]]
if (t && type === t.type) {
var d = {}
ok = false !== t.validate(d, k, val)
val = d[k]
if (ok) {
// if (isArray) (data[k] = data[k] || []).push(val)
// else data[k] = val
data[k] = val
break
}
}
}
debug("OK? %j (%j %j %j)", ok, k, val, types[i])
if (!ok) delete data[k]
return ok
}
function parse (args, data, remain, types, shorthands) {
debug("parse", args, data, remain)
var key = null
, abbrevs = abbrev(Object.keys(types))
, shortAbbr = abbrev(Object.keys(shorthands))
for (var i = 0; i < args.length; i ++) {
var arg = args[i]
debug("arg", arg)
if (arg.match(/^-{2,}$/)) {
// done with keys.
// the rest are args.
remain.push.apply(remain, args.slice(i + 1))
args[i] = "--"
break
}
var hadEq = false
if (arg.charAt(0) === "-" && arg.length > 1) {
if (arg.indexOf("=") !== -1) {
hadEq = true
var v = arg.split("=")
arg = v.shift()
v = v.join("=")
args.splice.apply(args, [i, 1].concat([arg, v]))
}
// see if it's a shorthand
// if so, splice and back up to re-parse it.
var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs)
debug("arg=%j shRes=%j", arg, shRes)
if (shRes) {
debug(arg, shRes)
args.splice.apply(args, [i, 1].concat(shRes))
if (arg !== shRes[0]) {
i --
continue
}
}
arg = arg.replace(/^-+/, "")
var no = null
while (arg.toLowerCase().indexOf("no-") === 0) {
no = !no
arg = arg.substr(3)
}
if (abbrevs[arg]) arg = abbrevs[arg]
var isArray = types[arg] === Array ||
Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1
// allow unknown things to be arrays if specified multiple times.
if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) {
if (!Array.isArray(data[arg]))
data[arg] = [data[arg]]
isArray = true
}
var val
, la = args[i + 1]
var isBool = typeof no === 'boolean' ||
types[arg] === Boolean ||
Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 ||
(typeof types[arg] === 'undefined' && !hadEq) ||
(la === "false" &&
(types[arg] === null ||
Array.isArray(types[arg]) && ~types[arg].indexOf(null)))
if (isBool) {
// just set and move along
val = !no
// however, also support --bool true or --bool false
if (la === "true" || la === "false") {
val = JSON.parse(la)
la = null
if (no) val = !val
i ++
}
// also support "foo":[Boolean, "bar"] and "--foo bar"
if (Array.isArray(types[arg]) && la) {
if (~types[arg].indexOf(la)) {
// an explicit type
val = la
i ++
} else if ( la === "null" && ~types[arg].indexOf(null) ) {
// null allowed
val = null
i ++
} else if ( !la.match(/^-{2,}[^-]/) &&
!isNaN(la) &&
~types[arg].indexOf(Number) ) {
// number
val = +la
i ++
} else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) {
// string
val = la
i ++
}
}
if (isArray) (data[arg] = data[arg] || []).push(val)
else data[arg] = val
continue
}
if (types[arg] === String && la === undefined)
la = ""
if (la && la.match(/^-{2,}$/)) {
la = undefined
i --
}
val = la === undefined ? true : la
if (isArray) (data[arg] = data[arg] || []).push(val)
else data[arg] = val
i ++
continue
}
remain.push(arg)
}
}
function resolveShort (arg, shorthands, shortAbbr, abbrevs) {
// handle single-char shorthands glommed together, like
// npm ls -glp, but only if there is one dash, and only if
// all of the chars are single-char shorthands, and it's
// not a match to some other abbrev.
arg = arg.replace(/^-+/, '')
// if it's an exact known option, then don't go any further
if (abbrevs[arg] === arg)
return null
// if it's an exact known shortopt, same deal
if (shorthands[arg]) {
// make it an array, if it's a list of words
if (shorthands[arg] && !Array.isArray(shorthands[arg]))
shorthands[arg] = shorthands[arg].split(/\s+/)
return shorthands[arg]
}
// first check to see if this arg is a set of single-char shorthands
var singles = shorthands.___singles
if (!singles) {
singles = Object.keys(shorthands).filter(function (s) {
return s.length === 1
}).reduce(function (l,r) {
l[r] = true
return l
}, {})
shorthands.___singles = singles
debug('shorthand singles', singles)
}
var chrs = arg.split("").filter(function (c) {
return singles[c]
})
if (chrs.join("") === arg) return chrs.map(function (c) {
return shorthands[c]
}).reduce(function (l, r) {
return l.concat(r)
}, [])
// if it's an arg abbrev, and not a literal shorthand, then prefer the arg
if (abbrevs[arg] && !shorthands[arg])
return null
// if it's an abbr for a shorthand, then use that
if (shortAbbr[arg])
arg = shortAbbr[arg]
// make it an array, if it's a list of words
if (shorthands[arg] && !Array.isArray(shorthands[arg]))
shorthands[arg] = shorthands[arg].split(/\s+/)
return shorthands[arg]
}

View File

@ -0,0 +1,3 @@
To get started, <a
href="http://www.clahub.com/agreements/isaacs/abbrev-js">sign the
Contributor License Agreement</a>.

View File

@ -0,0 +1,23 @@
Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
All rights reserved.
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.

View File

@ -0,0 +1,23 @@
# abbrev-js
Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).
Usage:
var abbrev = require("abbrev");
abbrev("foo", "fool", "folding", "flop");
// returns:
{ fl: 'flop'
, flo: 'flop'
, flop: 'flop'
, fol: 'folding'
, fold: 'folding'
, foldi: 'folding'
, foldin: 'folding'
, folding: 'folding'
, foo: 'foo'
, fool: 'fool'
}
This is handy for command-line scripts, or other cases where you want to be able to accept shorthands.

Some files were not shown because too many files have changed in this diff Show More