diff --git a/.gitignore b/.gitignore index d38da24..8003b36 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build .DS_Store .*.sw[op] +npm-debug.log diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2df62df --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +os: + - linux + - osx +osx_image: xcode7.3 +sudo: required +language: node_js +node_js: + - "4.4.6" + - "6.2.2" +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update ; fi +install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install g++-4.8 ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX="g++-4.8" CC="gcc-4.8"; fi +script: + - npm install diff --git a/README.md b/README.md index 6e1c723..7822ac9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ +[![Build Status](https://travis-ci.org/NodeOS/nodeos-mount.svg?branch=master)](https://travis-ci.org/NodeOS/nodeos-mount) +[![bitHound Score](https://www.bithound.io/NodeOS/nodeos-mount/badges/score.svg)](https://www.bithound.io/NodeOS/nodeos-mount) + # node-mount +[![Greenkeeper badge](https://badges.greenkeeper.io/NodeOS/nodeos-mount.svg)](https://greenkeeper.io/) + Mount/umount devices from node.js Really works on linux, may work on OS X, and will never work on windows. @@ -8,46 +13,49 @@ Really works on linux, may work on OS X, and will never work on windows. **Mount Tmpfs:** ```javascript var mount = require("mount"); -mount.mount('tmpfs', 'tmpDir', 'tmpfs', function(err) { +mount.mount('tmpDir', 'tmpfs', function(err) { if(err){ - return; - } - //Tmpfs mounted successfully + return; + } + + // Tmpfs mounted successfully }); ``` **Mount DVD:** ```javascript var mount = require("mount"); -mount.mount('/dev/sr0', 'myDir', 'iso9660', function(err) { - if(err){ - return; - } +mount.mount('myDir', 'iso9660', {devFile: '/dev/sr0'}, function(err) { + if(err){ + return; + } - // + // }); ``` **Mount ReadOnly+Remount (easy)** ```javascript var mount = require("mount"); -mount.mount('tmpfs', 'tmpdir', 'tmpfs', ['remount', 'readonly'], function(err) { - if(err){ - return; - } +mount.mount('tmpdir', 'tmpfs', ['remount', 'readonly'], function(err) { + if(err){ + return; + } - // + // }); ``` **Mount ReadOnly+Remount (flags)** ```javascript var mount = require("mount"); -mount.mount('tmpfs', 'tmpdir', 'tmpfs', mount.MS_REMOUNT | mount.MS_RDONLY, function(err) { - if(err){ - return; - } - // +mount.mount('tmpdir', 'tmpfs', mount.MS_REMOUNT | mount.MS_RDONLY, +function(err) { + if(err){ + return; + } + + // }); ``` @@ -55,59 +63,77 @@ mount.mount('tmpfs', 'tmpdir', 'tmpfs', mount.MS_REMOUNT | mount.MS_RDONLY, func ```javascript var mount = requrie("mount"); mount.umount('myDir', function(err) { - if(err){ - console.log("Umount went wrong: " + err); - return; - } + if(err){ + console.log("Umount went wrong: " + err); + return; + } + // }); ``` ##Installation -This package is not featured in NPM (yet), so you have to add this dependency line to your package.json -file: +This package is not featured in NPM (yet), so you have to add this dependency +line to your package.json file: **Part of package.json:** -``` +```json { - "name" : "myproject", - "version" : "1.0", - ... - ... - "dependencies" : { - "mount" : "git+ssh://git@github.com:hertzg/node-mount.git" - } + "name" : "myproject", + "version" : "1.0", + ... + ... + "dependencies" : { + "mount" : "git+ssh://git@github.com:hertzg/node-mount.git" + } } ``` ## API -This module provides functionality to mount and unmount devices to and from specific targets. Module exports asynchronous and synchronous variants. +This module provides functionality to mount and unmount devices to and from +specific targets. Module exports asynchronous and synchronous variants. Most of the explanations here are from `mount(2)` and `umount(2)` * http://linux.die.net/man/2/umount * http://linux.die.net/man/2/mount -**WARNING: Using synchronous methods may block the process for along time. (ex: Mounting scratched CD/DVD/BD, Network shares.. etc..)** +**WARNING: Using synchronous methods may block the process for along time. (ex: + Mounting scratched CD/DVD/BD, Network shares.. etc..)** ### mount.mount(source, target, fsType, [options], [dataStr], callback) - -Attaches the file system specified by `source` (which is often a device name, but can also be a directory name or a dummy) to the directory specified by `target`. + +Attaches the file system specified by `source` (which is often a device name, +but can also be a directory name or a dummy) to the directory specified by +`target`. **Appropriate privilege is required to mount file systems.** -* `source` - `{String}` - Device-File being mounted (located in /dev) a.k.a. `devFile`. * `target` - `{String}` - Directory to mount the device to. * `fsType` - `{String}` - Filesystem identificator (one of /proc/filesystems). -* `options` - `{Array}|{Number}` - Number describing mount flags or an Array containing String options described below: - - `bind` - Perform a bind mount, making a file or a directory subtree visible at another point within a file system. Bind mounts may cross file system boundaries and span chroot(2) jails. The `fstype` and `dataStr` arguments are ignored. - - `readonly` - Mount file system read-only. - - `remount` - Remount an existing mount. This allows you to change the `options` and `dataStr` of an existing mount without having to unmount and remount the file system. `target` should be the same value specified in the initial `mount()` call; `source` and `fsType` are ignored. - - `noexec` - Do not allow programs to be executed from this file system. -* `dataStr` - The `data` argument is interpreted by the different file systems. Typically it is a string of comma-separated options understood by this file system. -* `callback` - Function called after the mount operation finishes. Receives only one argument `err`. - * `err` - Is `null` if mount succeeded or `Error` object similar to ones generated by `fs` module in case of failure. - -Values for the `fstype` argument supported by the kernel are listed in `/proc/filesystems` (e.g., "minix", "ext2", "ext3", "jfs", "xfs", "reiserfs", "msdos", "proc", "nfs", "iso9660"). +* `options` - `{Array}|{Number}` - Number describing mount flags or an Array + containing String options described below: + - `bind` - Perform a bind mount, making a file or a directory subtree visible + at another point within a file system. Bind mounts may cross file system + boundaries and span chroot(2) jails. The `fstype` and `dataStr` arguments + are ignored. + - `readonly` - Mount file system read-only. + - `remount` - Remount an existing mount. This allows you to change the + `options` and `dataStr` of an existing mount without having to unmount and + remount the file system. `target` should be the same value specified in the + initial `mount()` call; `source` and `fsType` are ignored. + - `noexec` - Do not allow programs to be executed from this file system. +* `dataStr` - The `data` argument is interpreted by the different file systems. + Typically it is a string of comma-separated options or an options bag + understood by this file system. `devFile` option can be used to define the + Device-File being mounted (located in /dev). +* `callback` - Function called after the mount operation finishes. Receives only + one argument `err`. + * `err` - Is `null` if mount succeeded or `Error` object similar to ones + generated by `fs` module in case of failure. + +Values for the `fstype` argument supported by the kernel are listed in +`/proc/filesystems` (e.g., "minix", "ext2", "ext3", "jfs", "xfs", "reiserfs", +"msdos", "proc", "nfs", "iso9660"). It can be `auto`, too. ### mount.umount(target, callback) @@ -116,23 +142,27 @@ Removes the attachment of the (topmost) file system mounted on `target`. **Appropriate privilege is required to unmount file systems.** * `target` - `{String}` - Directory to unmount. -* `callback` - Function called after the mount operation finishes. Receives only one argument `err`. - * `err` - `null` if umount succeeded or `Error` object similar to ones generated by `fs` module in case of failure. +* `callback` - Function called after the mount operation finishes. Receives only + one argument `err`. + * `err` - `null` if umount succeeded or `Error` object similar to ones + generated by `fs` module in case of failure. Returns `undefined` ### mount.mountSync(source, target, fsType, [options], [dataStr]) Synchronous variant of `mount.mount()` -Returns: `true` if mount succeeded or **throws** `Error` object similar to ones generated by `fs` module in case of failure. +Returns: `true` if mount succeeded or **throws** `Error` object similar to ones +generated by `fs` module in case of failure. ### mount.umountSync(target) Synchronous variant of `mount.umount()` -Returns: `true` if umount succeeded or **throws** `Error` object similar to ones generated by `fs` module in case of failure. +Returns: `true` if umount succeeded or **throws** `Error` object similar to ones +generated by `fs` module in case of failure. ### mount.unmount(target, callback) -This function is **deprecated**; please use `mount.umount()` instead. +This function is **deprecated**; please use `mount.umount()` instead. Alias of `mount.umount()` @@ -146,7 +176,6 @@ Constants for easy `mount` `flags` bitmask manipulation. ## TODO: - umount2 - force force unmounting -- unittests ## Credits - Directly forked from magicpat`s [repository](https://github.com/magicpat/node-mount) diff --git a/binding.gyp b/binding.gyp index 296b417..3751895 100644 --- a/binding.gyp +++ b/binding.gyp @@ -2,7 +2,8 @@ "targets": [ { "target_name": "mount", - "sources": [ "mount.cc" ] + "sources": [ "mount.cc" ], + "include_dirs": [ " #include #include - -//Uses an example of kkaefer's node addon tutorials for an async worker -// -//Link for the used template: -//https://github.com/kkaefer/node-cpp-modules/blob/master/05_threadpool/modulename.cpp#L88 +#include using namespace v8; -Handle Mount(const Arguments &args); -void AsyncMount(uv_work_t* req); -void AsyncUmount(uv_work_t *req); -void AsyncAfter(uv_work_t* req); - struct Mounty { - Persistent callback; - - //All values excpect target are only used by mount - std::string devFile; - std::string fsType; - std::string target; //used by umount - std::string data; - long flags; - int error; + // All values except target are only used by mount + std::string devFile; + std::string fsType; + std::string target; // used by umount + std::string data; + long flags; + int error; }; -void AsyncMount(uv_work_t* req){ - Mounty* mounty = static_cast(req->data); - - int ret = mount(mounty->devFile.c_str(), - mounty->target.c_str(), - mounty->fsType.c_str(), - mounty->flags, - mounty->data.c_str()); - //Save error-code - if(ret == -1){ - mounty->error = errno; +class MountWorker : public Nan::AsyncWorker { +public: + MountWorker(Nan::Callback *callback, Mounty *mounty) + : Nan::AsyncWorker(callback), mounty(mounty) {} + ~MountWorker() {} + + // This function is executed in another thread at some point after it has been + // scheduled. IT MUST NOT USE ANY V8 FUNCTIONALITY. + void Execute() { + #ifdef __linux__ + int ret = mount(mounty->devFile.c_str(), + mounty->target.c_str(), + mounty->fsType.c_str(), + mounty->flags, + mounty->data.c_str()); + #elif __APPLE__ + int ret = mount( + mounty->fsType.c_str(), + mounty->target.c_str(), + mounty->flags, + &mounty->data); + #endif + + if (ret == -1) { + mounty->error = errno; } -} + } -void AsyncUmount(uv_work_t *req){ - Mounty* mounty = static_cast(req->data); + void HandleOKCallback() { + Nan::HandleScope scope; - int ret = umount(mounty->target.c_str()); + Local argv[] = { + Nan::Null() + }; - //Save error-code - if(ret == -1){ - mounty->error = errno; + if (mounty->error > 0) { + argv[0] = Nan::ErrnoException(mounty->error, "mount", "", + mounty->devFile.c_str()); } -} -//Used for both, mount and umount since they have the same callback interface -void AsyncAfter(uv_work_t* req){ - HandleScope scope; - Mounty* mounty = static_cast(req->data); - - const unsigned argc = 1; - Local argv[argc]; - - //Call error-callback, if error... otherwise send result - if(mounty->error > 0){ - std::string syscall; - std::string path; - if(mounty->devFile.empty()) { - syscall = "umount"; - path = mounty->target; - } else { - syscall = "mount"; - path = mounty->devFile; - } - argv[0] = node::ErrnoException(mounty->error, syscall.c_str(), "", path.c_str()); - } else { - argv[0] = Local::New(Null()); + callback->Call(1, argv); + } + +private: + Mounty *mounty; +}; + +class UmountWorker : public Nan::AsyncWorker { +public: + UmountWorker(Nan::Callback *callback, Mounty *mounty) + : Nan::AsyncWorker(callback), mounty(mounty) {} + ~UmountWorker() {} + + void Execute() { + #ifdef __linux__ + int ret = umount(mounty->target.c_str()); + #elif __APPLE__ + int ret = unmount( + mounty->target.c_str(), + mounty->flags); + #endif + + if (ret == -1) { + mounty->error = errno; } + } - TryCatch tc; - mounty->callback->Call(Context::GetCurrent()->Global(), argc, argv); + void HandleOKCallback() { + Nan::HandleScope scope; + Local argv[] = { + Nan::Null() + }; - if(tc.HasCaught()){ - node::FatalException(tc); + if (mounty->error > 0) { + argv[0] = Nan::ErrnoException(mounty->error, "umount", "", + mounty->target.c_str()); } - mounty->callback.Dispose(); + callback->Call(1, argv); delete mounty; - delete req; -} + } +private: + Mounty *mounty; +}; -// 0 1 2 3 4 5 -//mount(devFile, target, fsType, options, data, cb) -Handle Mount(const Arguments &args) { - HandleScope scope; - if(args.Length() != 6) { - return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 6)"))); - } +// 0 1 2 3 4 5 +// mount(devFile, target, fsType, options, data, cb) +NAN_METHOD(Mount) { + Nan::HandleScope scope; - String::Utf8Value devFile(args[0]->ToString()); - String::Utf8Value target(args[1]->ToString()); - String::Utf8Value fsType(args[2]->ToString()); - Local options = args[3]->ToInteger(); - String::Utf8Value dataStr(args[4]->ToString()); - Local cb = Local::Cast(args[5]); - - //Prepare data for the async work - Mounty* mounty = new Mounty(); - mounty->devFile = std::string(*devFile); - mounty->target = std::string(*target); - mounty->fsType = std::string(*fsType); - mounty->flags = options->Value(); - mounty->data = std::string(*dataStr); - mounty->callback = Persistent::New(cb); - - //Create the Async work and set the prepared data - uv_work_t *req = new uv_work_t(); - req->data = mounty; - - int status = uv_queue_work(uv_default_loop(), req, AsyncMount, (uv_after_work_cb)AsyncAfter); - assert(status == 0); - return scope.Close(Undefined()); -} + if (info.Length() != 6) { + return Nan::ThrowError("Invalid number of arguments (must be 6)"); + } -Handle Umount(const Arguments &args) { - HandleScope scope; + String::Utf8Value devFile(info[0]->ToString()); + String::Utf8Value target(info[1]->ToString()); + String::Utf8Value fsType(info[2]->ToString()); + Local options = info[3]->ToInteger(); + String::Utf8Value dataStr(info[4]->ToString()); - if(args.Length() != 2) { - return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 2)"))); - } + // Prepare data for the async work + Mounty* mounty = new Mounty(); + mounty->devFile = std::string(*devFile); + mounty->target = std::string(*target); + mounty->fsType = std::string(*fsType); + mounty->flags = options->Value(); + mounty->data = std::string(*dataStr); - String::Utf8Value target(args[0]->ToString()); - Local cb = Local::Cast(args[1]); + Nan::Callback *callback = new Nan::Callback(info[5].As()); - //Prepare data for the async work - Mounty* mounty = new Mounty(); - mounty->target = std::string(*target); - mounty->callback = Persistent::New(cb); + Nan::AsyncQueueWorker(new MountWorker(callback, mounty)); + return; +} - //Create the Async work and set the prepared data - uv_work_t *req = new uv_work_t(); - req->data = mounty; +NAN_METHOD(Umount) { + Nan::HandleScope scope; - int status = uv_queue_work(uv_default_loop(), req, AsyncUmount, (uv_after_work_cb)AsyncAfter); - assert(status == 0); - return scope.Close(Undefined()); -} + if (info.Length() != 2) { + return Nan::ThrowError("Invalid number of arguments (must be 2)"); + } -Handle MountSync(const Arguments &args) { - HandleScope scope; + String::Utf8Value target(info[0]->ToString()); - if(args.Length() != 5) { - return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 5)"))); - } + // Prepare data for the async work + Mounty* mounty = new Mounty(); + mounty->target = std::string(*target); - String::Utf8Value devFile(args[0]->ToString()); - String::Utf8Value target(args[1]->ToString()); - String::Utf8Value fsType(args[2]->ToString()); - Handle options = args[3]->ToInteger(); - String::Utf8Value dataStr(args[4]->ToString()); - - std::string s_devFile(*devFile); - std::string s_target(*target); - std::string s_fsType(*fsType); - std::string s_dataStr(*dataStr); - - int ret = mount(s_devFile.c_str(), - s_target.c_str(), - s_fsType.c_str(), - options->Value(), - s_dataStr.c_str()); - - if(ret != 0){ - return ThrowException(node::ErrnoException(errno, "mount", "", s_devFile.c_str())); - } + Nan::Callback *callback = new Nan::Callback(info[1].As()); - return scope.Close(True()); + Nan::AsyncQueueWorker(new UmountWorker(callback, mounty)); + return; } -Handle UmountSync(const Arguments &args) { - HandleScope scope; - if(args.Length() != 1) { - return ThrowException(Exception::Error(String::New("Invalid number of arguments (must be 1)"))); - } +NAN_METHOD(MountSync) { + Nan::HandleScope scope; + + if (info.Length() != 5) { + return Nan::ThrowError("Invalid number of arguments (must be 5)"); + } + + String::Utf8Value devFile(info[0]->ToString()); + String::Utf8Value target(info[1]->ToString()); + String::Utf8Value fsType(info[2]->ToString()); + Handle options = info[3]->ToInteger(); + String::Utf8Value dataStr(info[4]->ToString()); + + std::string s_devFile(*devFile); + std::string s_target(*target); + std::string s_fsType(*fsType); + std::string s_dataStr(*dataStr); + + #ifdef __linux__ + int ret = mount(s_devFile.c_str(), + s_target.c_str(), + s_fsType.c_str(), + options->Value(), + s_dataStr.c_str()); + #elif __APPLE__ + int ret = mount( + s_fsType.c_str(), + s_target.c_str(), + options->Value(), + &s_dataStr); + #endif + + if (ret) { + return Nan::ThrowError(Nan::ErrnoException(errno, "mount", "", + s_devFile.c_str())); + } + + info.GetReturnValue().Set(Nan::True()); +} - String::Utf8Value target(args[0]->ToString()); +NAN_METHOD(UmountSync) { + Nan::HandleScope scope; - std::string s_target(*target); + if (info.Length() != 1) { + return Nan::ThrowError("Invalid number of arguments (must be 1)"); + } - int ret = umount(s_target.c_str()); - if(ret != 0){ - return ThrowException(node::ErrnoException(errno, "umount", "", s_target.c_str())); - } + String::Utf8Value target(info[0]->ToString()); - return scope.Close(True()); + std::string s_target(*target); + + #ifdef __linux__ + int ret = umount(s_target.c_str()); + #elif __APPLE__ + int ret = unmount( + s_target.c_str(), + 0); + #endif + + if (ret) { + return Nan::ThrowError(Nan::ErrnoException(errno, "umount", "", + s_target.c_str())); + } + + info.GetReturnValue().Set(Nan::True()); } -void init (Handle exports, Handle module) { - exports->Set(String::NewSymbol("mount"), FunctionTemplate::New(Mount)->GetFunction()); - exports->Set(String::NewSymbol("umount"), FunctionTemplate::New(Umount)->GetFunction()); - exports->Set(String::NewSymbol("mountSync"), FunctionTemplate::New(MountSync)->GetFunction()); - exports->Set(String::NewSymbol("umountSync"), FunctionTemplate::New(UmountSync)->GetFunction()); + +void init (Handle exports) { + exports->Set(Nan::New("mount").ToLocalChecked(), + Nan::New(Mount)->GetFunction()); + exports->Set(Nan::New("umount").ToLocalChecked(), + Nan::New(Umount)->GetFunction()); + exports->Set(Nan::New("mountSync").ToLocalChecked(), + Nan::New(MountSync)->GetFunction()); + exports->Set(Nan::New("umountSync").ToLocalChecked(), + Nan::New(UmountSync)->GetFunction()); } NODE_MODULE(mount, init) diff --git a/mount.js b/mount.js index 23a3578..9a21231 100644 --- a/mount.js +++ b/mount.js @@ -1,172 +1,263 @@ "use strict"; + +var fs = require('fs') + +var detectSeries = require('async').detectSeries + var _binding = require('./build/Release/mount') - , Util = require('util') -; - -module.exports = { - _binding: _binding, - - mount: _mount, - umount: _umount, - mountSync: _mountSync, - umountSync: _umountSync, - - unmountSync: Util.deprecate(_umount, 'mount.unmountSync: Use mount.umountSync() instead'), - unmount: Util.deprecate(_umount, 'mount.unmount: Use mount.umount() instead'), - MS_RDONLY: 1, - MS_NOSUID: 2, - MS_NODEV: 4, - MS_NOEXEC: 8, - MS_SYNCHRONOUS: 16, - MS_REMOUNT: 32, - MS_MANDLOCK: 64, - MS_DIRSYNC: 128, - MS_NOATIME: 1024, - MS_NODIRATIME: 2048, - MS_BIND: 4096, - MS_MOVE: 8192, - MS_REC: 16384, - MS_VERBOSE: 32768, - MS_SILENT: 32768, - MS_POSIXACL: (1<<16), - MS_UNBINDABLE: (1<<17), - MS_PRIVATE: (1<<18), - MS_SLAVE: (1<<19), - MS_SHARED: (1<<20), - MS_RELATIME: (1<<21), - MS_KERNMOUNT: (1<<22), - MS_I_VERSION: (1<<23), - MS_STRICTATIME: (1<<24), - MS_NOSEC: (1<<28), - MS_BORN: (1<<29), - MS_ACTIVE: (1<<30), - MS_NOUSER: (1<<31), + + +const IS_LINUX = require('os').platform() === 'linux' + + +module.exports = +{ + _binding: _binding, + + mount: _mount, + umount: _umount, + mountSync: _mountSync, + umountSync: _umountSync, + + overrideOrder: ['ext4', 'ext3', 'ext2'], + + MS_RDONLY: 1, + MS_NOSUID: 2, + MS_NODEV: 4, + MS_NOEXEC: 8, + MS_SYNCHRONOUS: 16, + MS_REMOUNT: 32, + MS_MANDLOCK: 64, + MS_DIRSYNC: 128, + + MS_NOATIME: 1024, + MS_NODIRATIME: 2048, + MS_BIND: 4096, + MS_MOVE: 8192, + MS_REC: 16384, + MS_VERBOSE: 32768, + MS_SILENT: 32768, + + MS_POSIXACL: (1<<16), + MS_UNBINDABLE: (1<<17), + MS_PRIVATE: (1<<18), + MS_SLAVE: (1<<19), + MS_SHARED: (1<<20), + MS_RELATIME: (1<<21), + MS_KERNMOUNT: (1<<22), + MS_I_VERSION: (1<<23), + MS_STRICTATIME: (1<<24), + MS_NOSEC: (1<<28), + MS_BORN: (1<<29), + MS_ACTIVE: (1<<30), + MS_NOUSER: (1<<31), } -function __makeMountFlags(array) { - var flags = 0 - for(var i=0; i 4 && (typeof arguments[3] !== 'number' && (typeof arguments[3] === 'object' && arguments[3].constructor !== Array))) { - throw new Error('Argument options must be an array or number') - } + for(var key in object) + result.push(key+'='+object[key]) - if(argc > 5 && typeof arguments[4] !== 'string') { - throw new Error('Argument dataStr must be a string') - } + return result.join(',') +} - if(argc > 6) { - throw new Error('Too many arguments') - } - //Last param is always callback - var devFile = String(arguments[0]) - , target = String(arguments[1]) - , fsType = String(arguments[2]) - , options = 0 - , dataStr = '' - ; - - if(argc === 5) { - options = arguments[3] - } else if(argc === 6) { - options = arguments[3] - dataStr = arguments[4] - } +function checkArguments(target, fsType, options, dataStr, callback) +{ + if(target === undefined) throw new Error('target is mandatory') + + if(typeof fsType === 'number' || fsType instanceof Array) + { + callback = dataStr + dataStr = options + options = fsType + fsType = undefined + } + + if(options != null && options.constructor.name === 'Object' + || options instanceof Function) + { + callback = dataStr + dataStr = options + options = undefined + } + + if(dataStr instanceof Function) + { + callback = dataStr + dataStr = undefined + } - if(options.constructor !== Number) { - options = __makeMountFlags(options) + // default values + fsType = fsType || 'auto' + options = options || 0 + dataStr = dataStr || '' + + // ensure that `options` is an array or number + if(typeof options !== 'number' && options.constructor !== Array) + throw new Error('options must be an array or a number, not '+typeof options) + + // ensure that `dataStr` is a string or a literal object + if(typeof dataStr !== 'string' && dataStr.constructor !== Object) + throw new Error('dataStr must be a string or an object, not '+typeof dataStr) + + if(options instanceof Array) + options = makeMountFlags(options) + + var devFile = fsType + if(dataStr.constructor === Object) + { + if(IS_LINUX) + { + devFile = dataStr.devFile || fsType // TODO: find correct BSD flag name + delete dataStr.devFile } - _binding.mount(devFile, target, fsType, options, dataStr, cb) + dataStr = makeMountDataStr(dataStr) + } + + return [devFile, target, fsType, options, dataStr, callback] } -function _mountSync() { - var argc = arguments.length; - if(argc < 3) { - throw new Error('Invalid arguments') - } +function removeNoDev(value) +{ + return value && value.indexOf('nodev') < 0 +} - //ensure that options is an array or number - if(argc > 4 && (typeof arguments[3] !== 'number' && (typeof arguments[3] === 'object' && arguments[3].constructor !== Array))) { - throw new Error('Argument options must be an array or number') - } +function trim(value) +{ + return value.trim() +} - if(argc > 4 && typeof arguments[4] !== 'string') { - throw new Error('Argument dataStr must be a string') - } +function removeDuplicates(item, pos, self) +{ + return self.indexOf(item) === pos; +} - if(argc > 5) { - throw new Error('Too many arguments') - } +function fsList(data) +{ + var supported = data.split('\n').filter(removeNoDev).map(trim) - var devFile = String(arguments[0]) - , target = String(arguments[1]) - , fsType = String(arguments[2]) - , options = [] - , dataStr = '' - ; - - if(argc === 4) { - options = arguments[3] - } else if(argc === 5) { - options = arguments[3] - dataStr = arguments[4] - } + return module.exports.overrideOrder.concat(supported).filter(removeDuplicates) +} - if(options.constructor !== Number) { - options = __makeMountFlags(options) - } +function _mount(target, fsType, options, dataStr, cb) +{ + var argv = checkArguments(target, fsType, options, dataStr, cb) - return _binding.mountSync(devFile, target, fsType, options, dataStr); + cb = argv[5] + + //Last param is always callback + if(typeof cb !== 'function') + throw new Error('Last argument must be a callback function') + + if(argv[2] === 'auto' && !(argv[3] & module.exports.MS_MOVE)) + fs.readFile('/proc/filesystems', 'utf8', function(error, filesystems) + { + if(error) return cb(error) + + filesystems = fsList(filesystems) + + detectSeries(filesystems, function(item, callback) + { + argv[2] = item + argv[5] = function(error) + { + callback(!error) + } + + _binding.mount.apply(_binding, argv) + }, + function(result) + { + cb(result ? null : new Error('Unknown filesystem for ' + target)) + }) + }) + else + _binding.mount.apply(_binding, argv) } -function _umount(target, cb) { +function _mountSync(target, fsType, options, dataStr) +{ + var argv = checkArguments(target, fsType, options, dataStr) - //Require exactly 2 parameters - if(arguments.length !== 2 || typeof cb !== 'function') { - throw new Error('Invalid arguments') - } + argv.length = 5 + + if(argv[2] === 'auto' && !(argv[3] & module.exports.MS_MOVE)) + { + var filesystems = fs.readFileSync('/proc/filesystems', 'utf8') - _binding.umount(target, cb) + filesystems = fsList(filesystems) + + for(argv[2] in filesystems) + if(_binding.mountSync.apply(_binding, argv)) + return true + + throw new Error('Unknown filesystem for ' + target) + } + + return _binding.mountSync.apply(_binding, argv) } -function _umountSync(target) { - //Require exactly 1 parameter - if(typeof target !== 'string') { - throw new Error('Invalid arguments') - } +function _umount(target, cb) +{ + //Require exactly 2 parameters + if(arguments.length !== 2 || typeof cb !== 'function') + throw new Error('Invalid arguments') + + _binding.umount(target, cb) +} + +function _umountSync(target) +{ + //Require exactly 1 parameter + if(typeof target !== 'string') + throw new Error('Invalid arguments') - return _binding.umountSync(target) + return _binding.umountSync(target) } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..426c68d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2004 @@ +{ + "name": "nodeos-mount", + "version": "0.3.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", + "dev": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assertion-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", + "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "dev": true + }, + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "requires": { + "lodash": "4.17.4" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "body-parser": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", + "integrity": "sha1-EBXLH+LEQ4WCWVgdtTMy+NDPUPk=", + "dev": true, + "requires": { + "bytes": "2.2.0", + "content-type": "1.0.2", + "debug": "2.2.0", + "depd": "1.1.1", + "http-errors": "1.3.1", + "iconv-lite": "0.4.13", + "on-finished": "2.3.0", + "qs": "5.2.0", + "raw-body": "2.1.7", + "type-is": "1.6.15" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + }, + "qs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", + "integrity": "sha1-qfMRQq9GjLcrJbMBNrokVoNJFr4=", + "dev": true + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "bytes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", + "integrity": "sha1-/TVGSkA/b5EXwt42Cez/nK4ABYg=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chai": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.1.tgz", + "integrity": "sha1-ZuISeebzxkFf+CMYeCJ5AOIXGzk=", + "dev": true, + "requires": { + "assertion-error": "1.0.2", + "check-error": "1.0.2", + "deep-eql": "2.0.2", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz", + "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-2.0.2.tgz", + "integrity": "sha1-sbrAblbwp2d3aG1Qyf63XC7XZ5o=", + "dev": true, + "requires": { + "type-detect": "3.0.0" + }, + "dependencies": { + "type-detect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-3.0.0.tgz", + "integrity": "sha1-RtDMhVOrt7E6NSsNbeov1Y8tm1U=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.6.5" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "5.0.15" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.16" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.2.8" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.1.2", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "1.2.0" + } + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "grunt": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.1.tgz", + "integrity": "sha1-6HeHZOlEsY8yuw8QuQeEdcnftWs=", + "dev": true, + "requires": { + "coffee-script": "1.10.0", + "dateformat": "1.0.12", + "eventemitter2": "0.4.14", + "exit": "0.1.2", + "findup-sync": "0.3.0", + "glob": "7.0.6", + "grunt-cli": "1.2.0", + "grunt-known-options": "1.1.0", + "grunt-legacy-log": "1.0.0", + "grunt-legacy-util": "1.0.0", + "iconv-lite": "0.4.18", + "js-yaml": "3.5.5", + "minimatch": "3.0.4", + "nopt": "3.0.6", + "path-is-absolute": "1.0.1", + "rimraf": "2.2.8" + }, + "dependencies": { + "grunt-cli": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "0.3.0", + "grunt-known-options": "1.1.0", + "nopt": "3.0.6", + "resolve": "1.1.7" + } + } + } + }, + "grunt-contrib-watch": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.0.0.tgz", + "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=", + "dev": true, + "requires": { + "async": "1.5.2", + "gaze": "1.1.2", + "lodash": "3.10.1", + "tiny-lr": "0.2.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "grunt-known-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz", + "integrity": "sha1-pCdO6zL6dl2lp6OxcSYXzjsUQUk=", + "dev": true + }, + "grunt-legacy-log": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz", + "integrity": "sha1-+4bxgJhHvAfcR4Q/ns1srLYt8tU=", + "dev": true, + "requires": { + "colors": "1.1.2", + "grunt-legacy-log-utils": "1.0.0", + "hooker": "0.2.3", + "lodash": "3.10.1", + "underscore.string": "3.2.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", + "dev": true + } + } + }, + "grunt-legacy-log-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz", + "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.3.0" + }, + "dependencies": { + "lodash": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "dev": true + } + } + }, + "grunt-legacy-util": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz", + "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=", + "dev": true, + "requires": { + "async": "1.5.2", + "exit": "0.1.2", + "getobject": "0.1.0", + "hooker": "0.2.3", + "lodash": "4.3.0", + "underscore.string": "3.2.3", + "which": "1.2.14" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "lodash": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", + "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "dev": true + } + } + }, + "grunt-mocha-test": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.2.tgz", + "integrity": "sha1-Dzq8xqtUNkex7/xatE69NwLwq4w=", + "dev": true, + "requires": { + "hooker": "0.2.3", + "mkdirp": "0.5.1" + } + }, + "grunt-node-gyp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/grunt-node-gyp/-/grunt-node-gyp-4.0.0.tgz", + "integrity": "sha512-vKCYNsmSvkVyCI+ajxOqWwHiVqvYlMQnVslXn5LU8kAtz9rdiYFeGaXjakMFtpeSnK6HqPxDbNgfzSuPvTFY0A==", + "dev": true, + "requires": { + "node-gyp": "3.6.2" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "http-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", + "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "statuses": "1.3.1" + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "livereload-js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.2.2.tgz", + "integrity": "sha1-bIclfmSKtHW8JOoldFftzB+NC8I=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + } + }, + "mime-db": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=", + "dev": true + }, + "mime-types": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", + "dev": true, + "requires": { + "mime-db": "1.29.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.0.tgz", + "integrity": "sha512-pIU2PJjrPYvYRqVpjXzj76qltO9uBYI7woYAMoxbSefsa+vqAfptjoeevd6bUgwD0mPIO+hv9f7ltvsNreL2PA==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "nan": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", + "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" + }, + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.0.6", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.4", + "request": "2.81.0", + "rimraf": "2.2.8", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.2.14" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.0" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", + "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=", + "dev": true + }, + "qs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", + "integrity": "sha1-TZMuXH6kEcynajEtOaYGIA/VDNk=", + "dev": true + }, + "raw-body": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.7.tgz", + "integrity": "sha1-rf6s4uT7MJgFgBTQjActzFl1h3Q=", + "dev": true, + "requires": { + "bytes": "2.4.0", + "iconv-lite": "0.4.13", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", + "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.16", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + }, + "dependencies": { + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + } + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tiny-lr": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", + "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", + "dev": true, + "requires": { + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.2.2", + "parseurl": "1.3.1", + "qs": "5.1.0" + } + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-detect": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.3.tgz", + "integrity": "sha1-Dj8mcLRAmbC0bChNE2p+9Jx0wuo=", + "dev": true + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.16" + } + }, + "underscore.string": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", + "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true, + "requires": { + "websocket-extensions": "0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "dev": true + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 6f1f8fa..5b64d96 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,62 @@ { - "name": "mount", + "name": "nodeos-mount", "description": "Async mount / umount system devices", "main": "./mount", - "os" : [ "linux", "darwin", "!win32" ], + "os": [ + "linux", + "darwin", + "!win32" + ], "keywords": [ "mount", "linux", "device", "async" ], - "version": "0.1.1", - "homepage": "https://github.com/hertzg/node-mount", - "bugs": "https://github.com/hertzg/node-mount/issues", + "version": "0.3.2", + "homepage": "https://github.com/NodeOS/nodeos-mount", + "bugs": "https://github.com/NodeOS/nodeos-mount/issues", "repository": { "type": "git", - "url": "git://github.com/hertzg/node-mount.git" + "url": "git://github.com/NodeOS/nodeos-mount.git" }, "engines": { - "node": ">=0.8.0" + "node": ">= 4" }, - "private": true, "author": "George Kotchlamazashvili ", - "contributors": [{ + "contributors": [ + { "name": "Justas Brazauskas", "email": "brazauskasjustas@gmail.com" - }, { + }, + { "name": "Patrick Stapfer", "email": "p.stapfer@deadlock.at", "url": "http://www.deadlock.at" - }], + }, + { + "name": "Jesús Leganés Combarro 'piranna'", + "email": "piranna@gmail.com", + "url": "http://pirannafs.blogspot.com" + } + ], + "scripts": { + "test": "grunt test" + }, "license": "MIT", "gypfile": true, "readmeFilename": "README.md", - "dependencies": {}, + "dependencies": { + "async": "^2.5.0", + "nan": "^2.6.2" + }, "devDependencies": { - "mocha": "~1.18.2", - "chai": "~1.9.1", - "grunt": "~0.4.4", - "grunt-mocha-test": "~0.10.2", - "grunt-contrib-watch": "~0.6.1", - "grunt-node-gyp": "~0.3.0", - "q": "~1.0.1" + "mocha": "~3.5.0", + "chai": "~4.1.1", + "grunt": "~1.0.1", + "grunt-mocha-test": "~0.13.2", + "grunt-contrib-watch": "~1.0.0", + "grunt-node-gyp": "~4.0.0", + "q": "~1.5.0" } } diff --git a/test/mount.spec.js b/test/mount.spec.js index 6e6b564..a94e732 100644 --- a/test/mount.spec.js +++ b/test/mount.spec.js @@ -1,4 +1,4 @@ -/* jshint -W024 */ +/* jshint -W024 */ /* jshint expr:true */ "use strict"; @@ -11,26 +11,32 @@ var fs = require("fs"); var util = require("util"); var Q = require("q"); -var TMP_DIR = path.join(__dirname, "tmp"); +var TMP_DIR = path.join(__dirname, "tmp"); + + +function expectErrToBeNotOk(done, err) +{ + expect(err).to.be.not.ok; + done(); +} + describe("mount", function(){ //Create the target directory for mounting before(function(){ if(!fs.existsSync(TMP_DIR)){ - fs.mkdirSync(TMP_DIR); + fs.mkdirSync(TMP_DIR); } }); //Delete it afterwards after(function(done){ mount.umount(TMP_DIR, function(err){ - fs.rmdirSync(TMP_DIR); - done(); + fs.rmdir(TMP_DIR, done); }); }); describe("#mount", function(){ - afterEach(function(done){ mount.umount(TMP_DIR, function(){ done(); @@ -38,11 +44,11 @@ describe("mount", function(){ }); it("should mount tmpfs filesystem", function(done){ - mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){ + if(process.getuid()) return this.skip() + + mount.mount(TMP_DIR, "tmpfs", function(err){ expect(err).to.be.not.ok; - mount.umount(TMP_DIR, function(err){ - done(); - }); + mount.umount(TMP_DIR, done); }); }); @@ -53,58 +59,61 @@ describe("mount", function(){ var p4 = function(err){}; //Should all fail - expect(mount.mount.bind(mount, p1, p4)).to.throw(Error); +// expect(mount.mount.bind(mount, p1, p4)).to.throw(Error); expect(mount.mount.bind(mount, p1, p4, p2)).to.throw(Error); }); it("should not mount on nonexisting target", function(done){ - mount.mount("tmpfs", "notexist", "tmpfs", function(err){ + mount.mount("notexist", "tmpfs", function(err){ expect(err).to.be.ok; - expect(err.message).to.be.equal("2"); + expect(err.message).to.be.equal("ENOENT, No such file or "+ + "directory 'tmpfs'"); done(); }); }); it("should mount tmpfs", function(done){ - mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){ - expect(err).to.be.not.ok; - done(); - }); + if(process.getuid()) return this.skip() + + mount.mount(TMP_DIR, "tmpfs", + expectErrToBeNotOk.bind(undefined, done)); }); it("should mount / remount tmpfs with flags", function(done){ - mount.mount("tmpfs", TMP_DIR, "tmpfs", ["readonly", "noexec"], function(err){ + if(process.getuid()) return this.skip() + + mount.mount(TMP_DIR, "tmpfs", ["readonly", "noexec"], function(err){ expect(err).to.be.not.ok; - mount.mount("tmpfs", TMP_DIR, "tmpfs", ["remount"], function(err){ - expect(err).to.be.not.ok; - done(); - }); + mount.mount(TMP_DIR, "tmpfs", ["remount"], + expectErrToBeNotOk.bind(undefined, done)); }); }); it("should throw error on wrong flag", function(){ expect(mount.mount.bind(mount, "tmpfs", TMP_DIR, ["readonly", "fail"])).to.throw(Error); }); - }); describe("#umount", function(){ it("should umount mounting point", function(done){ - mount.mount("tmpfs", TMP_DIR, "tmpfs", function(err){ + if(process.getuid()) return this.skip() + + mount.mount(TMP_DIR, "tmpfs", function(err){ expect(err).to.be.not.ok; - mount.umount(TMP_DIR, function(err){ - expect(err).to.be.not.ok; - done(); - }); + mount.umount(TMP_DIR, expectErrToBeNotOk.bind(undefined, done)); }); }); - it("should raise error on umounting a nonexisting mountpoint", function(done){ + it("should raise error on umounting a nonexisting mountpoint", + function(done){ + if(process.getuid()) return this.skip() + mount.umount("nonexistent", function(err){ expect(err).to.be.ok; - expect(err.message).to.be.equal("2"); + expect(err.message).to.be.equal("ENOENT, No such file or "+ + "directory 'nonexistent'"); done(); }); });