diff --git a/Info.plist b/Info.plist
new file mode 100644
index 0000000..7616293
--- /dev/null
+++ b/Info.plist
@@ -0,0 +1,103 @@
+
+
+
+
+ BuildMachineOSBuild
+ 12C3006
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ IPyApp
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeIconFile
+ nw.icns
+ CFBundleTypeName
+ node-webkit App
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Owner
+ LSItemContentTypes
+
+ com.intel.nw.app
+
+
+
+ CFBundleTypeName
+ Folder
+ CFBundleTypeOSTypes
+
+ fold
+
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ None
+
+
+ CFBundleExecutable
+ node-webkit
+ CFBundleIconFile
+ app.nw/app.icns
+ CFBundleIdentifier
+ org.ipython.ipyapp
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ IPyApp
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 32.0.1700.107
+ CFBundleVersion
+ 1700.107
+ DTSDKBuild
+ 11E52
+ DTSDKName
+ macosx10.7
+ DTXcode
+ 0452
+ DTXcodeBuild
+ 4G2008a
+ LSFileQuarantineEnabled
+
+ LSMinimumSystemVersion
+ 10.6.0
+ NSPrincipalClass
+ NSApplication
+ NSSupportsAutomaticGraphicsSwitching
+
+ SCMRevision
+ 239963
+ UTExportedTypeDeclarations
+
+
+ UTTypeConformsTo
+
+ com.pkware.zip-archive
+
+ UTTypeDescription
+ node-webkit App
+ UTTypeIconFile
+ nw.icns
+ UTTypeIdentifier
+ com.intel.nw.app
+ UTTypeReferenceURL
+ https://github.com/rogerwang/node-webkit/wiki/How-to-package-and-distribute-your-apps
+ UTTypeTagSpecification
+
+ com.apple.ostype
+ node-webkit
+ public.filename-extension
+
+ nw
+
+ public.mime-type
+ application/x-node-webkit-app
+
+
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5c420da
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2014 Preston Holmes
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..94d5873
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+# IPyApp
+
+
+This package currently serves as a proof of concept for bundling IPython notebook into a standalone executable application.
+
+There are basically two components to bundling this. The first is to take Python and IPython and any other python libraries, and bundle them into a platform executable.
+
+Then wrap this executable in a [node-webkit](https://github.com/rogerwang/node-webkit) app to provide the web UI to the notebook server.
+
+Current this POC is limited to Mac OS using [Py2App](https://pypi.python.org/pypi/py2app/).
+
+However node-webkit is cross platform, so as long as an executable can be created (ie py2exe), then this general approach should be cross platform.
+
+## How to create the bundle
+
+First, create a virtualenv and install IPython, py2app and any packages you want included.
+
+Then cd into the py2app directory and build the executable
+
+ rm -r build dist; python setup.py py2app --packages IPython
+
+Include any additional --packages
+
+This will create a nb.app executable in the dist folder. Copy this into the app.nw folder.
+
+Next download the [node-webkit binary](https://github.com/rogerwang/node-webkit#downloads)
+
+Right click on the node-webkit.app binary that you downloaded and choose "Show Package Contents"
+
+Copy the provided Info.plist file into the Contents folder of the package, and copy the app.nw folder into the Contents/Resources folder of the package.
+
+You should now be able to launch the app by double clicking.
+
+The layout of the app should look something like:
+
+
+
+ IPyApp.app
+ └── Contents
+ ├── Frameworks
+ │ ├── crash_inspector
+ │ ├── node-webkit\ Framework.framework
+ │ │ ├── Libraries
+ │ │ ├── Resources
+ │ │ ├── node-webkit\ Framework
+ │ │ ├── node-webkit\ Framework.TOC
+ │ │ └── node-webkit\ Framework.tmp
+ │ ├── node-webkit\ Helper\ EH.app
+ │ │ └── Contents
+ │ ├── node-webkit\ Helper\ NP.app
+ │ │ └── Contents
+ │ └── node-webkit\ Helper.app
+ │ └── Contents
+ ├── Info.plist
+ ├── MacOS
+ │ └── node-webkit
+ ├── PkgInfo
+ └── Resources
+ ├── app.nw
+ │ ├── app.icns
+ │ ├── IPythonConsole.png
+ │ ├── nb.app
+ │ ├── node_modules
+ │ ├── package.json
+ │ ├── start.html
+ │ └── test.js
+ └── nw.icns
+
+
+
+### Similar projects:
+
+* https://github.com/liyanage/ipython-notebook - A similar project that uses node-webkit, but does not bundle the python environment, but provides an alternative to opening in the browser.
+* https://github.com/mangecoeur/ipython-desktop - A project to embed IPython notebook into a native Mac App using OS X only web ui views
+
+
+
diff --git a/app.nw/IPythonConsole.png b/app.nw/IPythonConsole.png
new file mode 100644
index 0000000..06ea47b
Binary files /dev/null and b/app.nw/IPythonConsole.png differ
diff --git a/app.nw/app.icns b/app.nw/app.icns
new file mode 100644
index 0000000..37db452
Binary files /dev/null and b/app.nw/app.icns differ
diff --git a/app.nw/node_modules/sleep/.jshintignore b/app.nw/node_modules/sleep/.jshintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/app.nw/node_modules/sleep/.jshintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/app.nw/node_modules/sleep/.jshintrc b/app.nw/node_modules/sleep/.jshintrc
new file mode 100644
index 0000000..fde1d96
--- /dev/null
+++ b/app.nw/node_modules/sleep/.jshintrc
@@ -0,0 +1,33 @@
+{
+ "predef": [
+ "ve",
+
+ "setImmediate",
+
+ "QUnit"
+ ],
+
+ "bitwise": true,
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "noempty": true,
+ "nonew": true,
+ "regexp": false,
+ "undef": true,
+ "strict": false,
+ "trailing": true,
+ "unused":true,
+
+ "smarttabs": true,
+ "multistr": true,
+
+ "node": true,
+
+ "nomen": false,
+ "loopfunc": true
+ //"onevar": true
+}
diff --git a/app.nw/node_modules/sleep/.npmignore b/app.nw/node_modules/sleep/.npmignore
new file mode 100644
index 0000000..26fefbc
--- /dev/null
+++ b/app.nw/node_modules/sleep/.npmignore
@@ -0,0 +1,4 @@
+.lock-wscript
+build
+node_modules
+lib/binding
diff --git a/app.nw/node_modules/sleep/README.md b/app.nw/node_modules/sleep/README.md
new file mode 100644
index 0000000..ddaa569
--- /dev/null
+++ b/app.nw/node_modules/sleep/README.md
@@ -0,0 +1,25 @@
+sleep
+=====
+
+Add `sleep()` and `usleep()` to nodejs.
+
+This is mainly useful for debugging.
+
+**Sleep will block execution of all javascript!**
+===================================================
+
+On windows the module will fall back to a while loop which will use 100% CPU!
+
+Usage
+-----
+
+`var sleep = require('sleep');`
+
+* `sleep.sleep(n)`: sleep for n seconds
+* `sleep.usleep(n)`: sleep for n microseconds (1 second is 1000000 microseconds)
+
+Update
+------
+
+Now bulids properly using node-gyp :)
+
diff --git a/app.nw/node_modules/sleep/binding.gyp b/app.nw/node_modules/sleep/binding.gyp
new file mode 100644
index 0000000..4f61533
--- /dev/null
+++ b/app.nw/node_modules/sleep/binding.gyp
@@ -0,0 +1,10 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'node_sleep',
+ 'sources': [
+ 'sleep.cc',
+ ],
+ }
+ ]
+}
diff --git a/app.nw/node_modules/sleep/build-util/tools.js b/app.nw/node_modules/sleep/build-util/tools.js
new file mode 100644
index 0000000..2e8c79b
--- /dev/null
+++ b/app.nw/node_modules/sleep/build-util/tools.js
@@ -0,0 +1,88 @@
+var http = require('http');
+var url = require('url');
+
+function download(from,options,callback) {
+ options = options || {};
+ var uri = url.parse(from);
+ var req = http.request(uri);
+ req.on('response', function(res){
+ // needed for end to be called
+ res.resume();
+ if (res.statusCode !== 200) {
+ return callback(new Error('Server returned '+ res.statusCode));
+ }
+ function returnBuffer() {
+ // todo - use http://nodejs.org/api/buffer.html#buffer_class_method_buffer_concat_list_totallength
+ for (var length = 0, i = 0; i < out.length; ++i) {
+ length += out[i].length;
+ }
+ var result = new Buffer(length);
+ for (var pos = 0, j = 0; j < out.length; ++j) {
+ out[j].copy(result, pos);
+ pos += out[j].length;
+ }
+ return callback(null,result);
+ }
+ var out = [];
+ res.on('data', function(chunk) {
+ out.push(chunk);
+ });
+ res.on('end', function(){
+ returnBuffer();
+ });
+ res.on('close', function(){
+ returnBuffer();
+ });
+ });
+ req.on('error', function(err){
+ callback(err);
+ });
+ req.end();
+}
+
+
+function parse_args(_args, opts) {
+ // first split them like npm returns
+ var args = [], next_arg;
+ _args.forEach(function(a) {
+ var parts = a.split('=');
+ parts.forEach(function(p) {
+ args.push(p);
+ });
+ });
+ // respect flags passed to npm install
+ if (process.env.npm_config_argv) {
+ var argv_obj = JSON.parse(process.env.npm_config_argv);
+ args = args.concat(argv_obj.cooked.slice(1));
+ }
+ var debug = (args.indexOf('--debug') > -1);
+ if (debug) { opts.configuration = 'Debug'; }
+
+ opts.stage = (args.indexOf('--stage') > -1);
+ if (opts.stage) {
+ opts.force = true;
+ } else {
+ var from_source = args.indexOf('--build-from-source');
+ if ( from_source > -1) {
+ // no specific module name passed
+ next_arg = args[from_source+1];
+ if (!next_arg || next_arg.indexOf('--') <= 0) {
+ opts.force = true;
+ } else if (next_arg === 'sqlite3'){
+ opts.force = true;
+ }
+ }
+ }
+ var target_arch = args.indexOf('--target_arch');
+ if (target_arch > -1) {
+ next_arg = args[target_arch+1];
+ if (next_arg && next_arg.indexOf('--') < 0) {
+ opts.target_arch = next_arg;
+ }
+ }
+ opts.args = args;
+ return opts;
+}
+
+module.exports.parse_args = parse_args;
+module.exports.download = download;
diff --git a/app.nw/node_modules/sleep/build.js b/app.nw/node_modules/sleep/build.js
new file mode 100644
index 0000000..b81b116
--- /dev/null
+++ b/app.nw/node_modules/sleep/build.js
@@ -0,0 +1,113 @@
+// we borrow some build system tooling from node-sqlite3
+var package_json = require('./package.json');
+var Binary = require('./lib/binary_name.js').Binary;
+var util = require('./build-util/tools.js');
+
+var cp = require('child_process');
+var fs = require('fs');
+var mkdirp = require('mkdirp');
+var path = require('path');
+
+var opts = {
+ name: 'node_sleep',
+ force: false,
+ stage: false,
+ configuration: 'Release',
+ target_arch: process.arch,
+ platform: process.platform,
+ uri: 'http://node-sleep.s3.amazonaws.com/',
+ tool: 'node-gyp',
+ paths: {}
+};
+
+function log(msg) {
+ console.log('['+package_json.name+']: ' + msg);
+}
+
+// only for dev
+function log_debug(msg) {
+ log(msg);
+}
+
+function done(err) {
+ if (err) {
+ log(err);
+ process.exit(1);
+ }
+ process.exit(0);
+}
+
+function build(opts,callback) {
+ var shell_cmd = opts.tool;
+ if (opts.tool === 'node-gyp' && process.platform === 'win32') {
+ shell_cmd = 'node-gyp.cmd';
+ }
+ var shell_args = ['rebuild'].concat(opts.args);
+ var cmd = cp.spawn(shell_cmd,shell_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 + ' ' + shell_args.join(' ') + "' (" + err + ")"));
+ }
+ });
+ // exit not close to support node v0.6.x
+ cmd.on('exit', function (code) {
+ if (code !== 0) {
+ return callback(new Error("Failed to execute '" + shell_cmd + ' ' + shell_args.join(' ') + "' (" + code + ")"));
+ }
+ move(opts,callback);
+ });
+}
+
+function move(opts,callback) {
+ try {
+ fs.statSync(opts.paths.build_module_path);
+ } catch (ex) {
+ return callback(new Error('Build succeeded but target not found at ' + opts.paths.build_module_path));
+ }
+ try {
+ mkdirp.sync(path.dirname(opts.paths.runtime_module_path));
+ log('Created: ' + path.dirname(opts.paths.runtime_module_path));
+ } catch (err) {
+ log_debug(err);
+ }
+ fs.renameSync(opts.paths.build_module_path,opts.paths.runtime_module_path);
+ if (opts.stage) {
+ try {
+ mkdirp.sync(path.dirname(opts.paths.staged_module_file_name));
+ log('Created: ' + path.dirname(opts.paths.staged_module_file_name));
+ } catch (err) {
+ log_debug(err);
+ }
+ fs.writeFileSync(opts.paths.staged_module_file_name,fs.readFileSync(opts.paths.runtime_module_path));
+ // drop build metadata into build folder
+ var metapath = path.join(path.dirname(opts.paths.staged_module_file_name),'build-info.json');
+ // more build info
+ opts.date = new Date();
+ opts.node_features = process.features;
+ opts.versions = process.versions;
+ opts.config = process.config;
+ opts.execPath = process.execPath;
+ fs.writeFileSync(metapath,JSON.stringify(opts,null,2));
+ //tarball(opts,callback);
+ return callback();
+ } else {
+ log('Installed in ' + opts.paths.runtime_module_path + '');
+ return callback();
+ }
+}
+
+function rel(p) {
+ return path.relative(process.cwd(),p);
+}
+
+// build it!
+opts = util.parse_args(process.argv.slice(2), opts);
+opts.binary = new Binary(opts);
+var versioned = opts.binary.getRequirePath();
+opts.paths.runtime_module_path = rel(path.join(__dirname, 'lib', versioned));
+opts.paths.runtime_folder = rel(path.join(__dirname, 'lib', 'binding',opts.binary.configuration));
+var staged_module_path = path.join(__dirname, 'stage', opts.binary.getModuleAbi(), opts.binary.getBasePath());
+opts.paths.staged_module_file_name = rel(path.join(staged_module_path,opts.binary.filename()));
+opts.paths.build_module_path = rel(path.join(__dirname, 'build', opts.binary.configuration, opts.binary.filename()));
+
+build(opts, done);
diff --git a/app.nw/node_modules/sleep/lib/binary_name.js b/app.nw/node_modules/sleep/lib/binary_name.js
new file mode 100644
index 0000000..34f1173
--- /dev/null
+++ b/app.nw/node_modules/sleep/lib/binary_name.js
@@ -0,0 +1,58 @@
+
+var path = require('path');
+
+var Binary = function(options) {
+ options = options || {};
+ var package_json = options.package_json || require('../package.json');
+ this.name = options.name || 'binding';
+ this.configuration = options.configuration || 'Release';
+ this.uri = options.uri || 'http://'+this.name+'.s3.amazonaws.com/';
+ this.module_maj_min = package_json.version.split('.').slice(0,2).join('.');
+ this.module_abi = package_json.abi;
+ this.platform = options.platform || process.platform;
+ this.target_arch = options.target_arch || process.arch;
+ if (process.versions.modules) {
+ // added in >= v0.10.4 and v0.11.7
+ // https://github.com/joyent/node/commit/ccabd4a6fa8a6eb79d29bc3bbe9fe2b6531c2d8e
+ this.node_abi = 'node-v' + (+process.versions.modules);
+ } else {
+ this.node_abi = 'v8-' + process.versions.v8.split('.').slice(0,2).join('.');
+ }
+};
+
+Binary.prototype.filename = function() {
+ return this.name + '.node';
+};
+
+Binary.prototype.compression = function() {
+ return '.tar.gz';
+};
+
+Binary.prototype.getBasePath = function() {
+ return this.node_abi +
+ '-' + this.platform +
+ '-' + this.target_arch;
+};
+
+Binary.prototype.getRequirePath = function(configuration) {
+ return '../' + path.join('Build',
+ configuration || this.configuration,
+ this.filename());
+};
+
+Binary.prototype.getModuleAbi = function() {
+ return this.name + '-v' + this.module_maj_min + '.' + this.module_abi;
+};
+
+Binary.prototype.getArchivePath = function() {
+ return this.getModuleAbi() +
+ '-' +
+ this.getBasePath() +
+ this.compression();
+};
+
+Binary.prototype.getRemotePath = function() {
+ return this.uri+this.configuration+'/'+this.getArchivePath();
+};
+
+module.exports.Binary = Binary;
diff --git a/app.nw/node_modules/sleep/lib/index.js b/app.nw/node_modules/sleep/lib/index.js
new file mode 100644
index 0000000..80e7572
--- /dev/null
+++ b/app.nw/node_modules/sleep/lib/index.js
@@ -0,0 +1,35 @@
+var Binary = require('./binary_name.js').Binary;
+var binary = new Binary({name:'node_sleep'});
+var binding;
+try {
+ binding = require(binary.getRequirePath('Debug'));
+} catch (err) { /* ignore */ }
+if (!binding) {
+ try {
+ binding = require(binary.getRequirePath('Release'));
+ } catch (err) { /* ignore */ }
+}
+if (!binding) {
+ console.error("Using busy loop implementation of sleep.");
+ binding = {
+ sleep: function(s) {
+ var e = new Date().getTime() + (s * 1000);
+
+ while (new Date().getTime() <= e) {
+ /* do nothing, but burn a lot of CPU while doing so */
+ /* jshint noempty: false */
+ }
+ },
+
+ usleep: function(s) {
+ var e = new Date().getTime() + (s / 1000);
+
+ while (new Date().getTime() <= e) {
+ /* do nothing, but burn a lot of CPU while doing so */
+ /* jshint noempty: false */
+ }
+ }
+ };
+}
+
+module.exports = binding;
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/.npmignore b/app.nw/node_modules/sleep/node_modules/mkdirp/.npmignore
new file mode 100644
index 0000000..9303c34
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/.npmignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
\ No newline at end of file
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/.travis.yml b/app.nw/node_modules/sleep/node_modules/mkdirp/.travis.yml
new file mode 100644
index 0000000..84fd7ca
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/LICENSE b/app.nw/node_modules/sleep/node_modules/mkdirp/LICENSE
new file mode 100644
index 0000000..432d1ae
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/LICENSE
@@ -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.
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/examples/pow.js b/app.nw/node_modules/sleep/node_modules/mkdirp/examples/pow.js
new file mode 100644
index 0000000..e692421
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/examples/pow.js
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/index.js b/app.nw/node_modules/sleep/node_modules/mkdirp/index.js
new file mode 100644
index 0000000..fda6de8
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/index.js
@@ -0,0 +1,82 @@
+var path = require('path');
+var fs = require('fs');
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, mode, f, made) {
+ if (typeof mode === 'function' || mode === undefined) {
+ f = mode;
+ mode = 0777 & (~process.umask());
+ }
+ if (!made) made = null;
+
+ var cb = f || function () {};
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ fs.mkdir(p, mode, function (er) {
+ if (!er) {
+ made = made || p;
+ return cb(null, made);
+ }
+ switch (er.code) {
+ case 'ENOENT':
+ mkdirP(path.dirname(p), mode, function (er, made) {
+ if (er) cb(er, made);
+ else mkdirP(p, mode, 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:
+ fs.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, mode, made) {
+ if (mode === undefined) {
+ mode = 0777 & (~process.umask());
+ }
+ if (!made) made = null;
+
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ try {
+ fs.mkdirSync(p, mode);
+ made = made || p;
+ }
+ catch (err0) {
+ switch (err0.code) {
+ case 'ENOENT' :
+ made = sync(path.dirname(p), mode, made);
+ sync(p, mode, 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 = fs.statSync(p);
+ }
+ catch (err1) {
+ throw err0;
+ }
+ if (!stat.isDirectory()) throw err0;
+ break;
+ }
+ }
+
+ return made;
+};
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/package.json b/app.nw/node_modules/sleep/node_modules/mkdirp/package.json
new file mode 100644
index 0000000..59d66e1
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "mkdirp",
+ "description": "Recursively mkdir, like `mkdir -p`",
+ "version": "0.3.5",
+ "author": {
+ "name": "James Halliday",
+ "email": "mail@substack.net",
+ "url": "http://substack.net"
+ },
+ "main": "./index",
+ "keywords": [
+ "mkdir",
+ "directory"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/substack/node-mkdirp.git"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "devDependencies": {
+ "tap": "~0.4.0"
+ },
+ "license": "MIT",
+ "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n",
+ "readmeFilename": "readme.markdown",
+ "bugs": {
+ "url": "https://github.com/substack/node-mkdirp/issues"
+ },
+ "homepage": "https://github.com/substack/node-mkdirp",
+ "_id": "mkdirp@0.3.5",
+ "dist": {
+ "shasum": "d7def7349d674800fac371eef2ecaff11c41ccde"
+ },
+ "_from": "mkdirp@~0.3.5",
+ "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz"
+}
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/readme.markdown b/app.nw/node_modules/sleep/node_modules/mkdirp/readme.markdown
new file mode 100644
index 0000000..83b0216
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/readme.markdown
@@ -0,0 +1,63 @@
+# 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, mode, cb)
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `mode`.
+
+If `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.
+
+## mkdirp.sync(dir, mode)
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+Returns the first directory that had to be created, if any.
+
+# install
+
+With [npm](http://npmjs.org) do:
+
+```
+npm install mkdirp
+```
+
+# license
+
+MIT
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/chmod.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/chmod.js
new file mode 100644
index 0000000..520dcb8
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/chmod.js
@@ -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();
+ });
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/clobber.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/clobber.js
new file mode 100644
index 0000000..0eb7099
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/clobber.js
@@ -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();
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/mkdirp.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/mkdirp.js
new file mode 100644
index 0000000..b07cd70
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/mkdirp.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('woo', 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('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm.js
new file mode 100644
index 0000000..23a7abb
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('async perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
+
+test('async root perm', function (t) {
+ mkdirp('/tmp', 0755, function (err) {
+ if (err) t.fail(err);
+ t.end();
+ });
+ t.end();
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm_sync.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm_sync.js
new file mode 100644
index 0000000..f685f60
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/perm_sync.js
@@ -0,0 +1,39 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
+
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
+
+test('sync root perm', function (t) {
+ t.plan(1);
+
+ var file = '/tmp';
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/race.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/race.js
new file mode 100644
index 0000000..96a0447
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/race.js
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('race', function (t) {
+ t.plan(4);
+ 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) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ if (cb) cb();
+ }
+ })
+ })
+ });
+ }
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/rel.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/rel.js
new file mode 100644
index 0000000..7985824
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/rel.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('rel', 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 cwd = process.cwd();
+ process.chdir('/tmp');
+
+ var file = [x,y,z].join('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ process.chdir(cwd);
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/return.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/return.js
new file mode 100644
index 0000000..bce68e5
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/return.js
@@ -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);
+ });
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/return_sync.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/return_sync.js
new file mode 100644
index 0000000..7c222d3
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/return_sync.js
@@ -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);
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/root.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/root.js
new file mode 100644
index 0000000..97ad7a2
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/root.js
@@ -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();
+ })
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/sync.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/sync.js
new file mode 100644
index 0000000..7530cad
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync', 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('/');
+
+ try {
+ mkdirp.sync(file, 0755);
+ } catch (err) {
+ t.fail(err);
+ return t.end();
+ }
+
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ });
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask.js
new file mode 100644
index 0000000..64ccafe
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('implicit mode from umask', 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('/');
+
+ mkdirp(file, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0777 & (~process.umask()));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
diff --git a/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask_sync.js b/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask_sync.js
new file mode 100644
index 0000000..35bd5cb
--- /dev/null
+++ b/app.nw/node_modules/sleep/node_modules/mkdirp/test/umask_sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('umask sync modes', 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('/');
+
+ try {
+ mkdirp.sync(file);
+ } catch (err) {
+ t.fail(err);
+ return t.end();
+ }
+
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, (0777 & (~process.umask())));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ });
+ });
+});
diff --git a/app.nw/node_modules/sleep/package.json b/app.nw/node_modules/sleep/package.json
new file mode 100644
index 0000000..644c149
--- /dev/null
+++ b/app.nw/node_modules/sleep/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "sleep",
+ "version": "1.1.4",
+ "main": "./lib/index.js",
+ "description": "Add sleep() and usleep() to nodejs",
+ "homepage": "http://github.com/ErikDubbelboer/node-sleep",
+ "author": {
+ "name": "Erik Dubbelboer",
+ "email": "erik@dubbelboer.com"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ },
+ "keywords": [
+ "sleep",
+ "usleep"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ErikDubbelboer/node-sleep.git"
+ },
+ "repositories": [
+ {
+ "type": "git",
+ "url": "https://github.com/ErikDubbelboer/node-sleep.git"
+ }
+ ],
+ "dependencies": {
+ "mkdirp": "~0.3.5"
+ },
+ "scripts": {
+ "install": "node build.js || nodejs build.js"
+ },
+ "gypfile": true,
+ "readme": "sleep\n=====\n\nAdd `sleep()` and `usleep()` to nodejs.\n\nThis is mainly useful for debugging.\n\n**Sleep will block execution of all javascript!**\n===================================================\n\nOn windows the module will fall back to a while loop which will use 100% CPU!\n\nUsage\n-----\n\n`var sleep = require('sleep');`\n\n* `sleep.sleep(n)`: sleep for n seconds\n* `sleep.usleep(n)`: sleep for n microseconds (1 second is 1000000 microseconds)\n\nUpdate\n------\n\nNow bulids properly using node-gyp :)\n\n",
+ "readmeFilename": "README.md",
+ "bugs": {
+ "url": "https://github.com/ErikDubbelboer/node-sleep/issues"
+ },
+ "_id": "sleep@1.1.4",
+ "dist": {
+ "shasum": "514d79e04ea79ed6e81761f4ca5c4c9aa866f169"
+ },
+ "_from": "sleep@",
+ "_resolved": "https://registry.npmjs.org/sleep/-/sleep-1.1.4.tgz"
+}
diff --git a/app.nw/node_modules/sleep/sleep.cc b/app.nw/node_modules/sleep/sleep.cc
new file mode 100644
index 0000000..4faaa12
--- /dev/null
+++ b/app.nw/node_modules/sleep/sleep.cc
@@ -0,0 +1,70 @@
+#ifndef BUILDING_NODE_EXTENSION
+#define BUILDING_NODE_EXTENSION
+#endif // BUILDING_NODE_EXTENSION
+
+#include
+#include
+
+#ifdef _WIN32 || _WIN64
+unsigned int sleep(unsigned int seconds)
+{
+ Sleep(seconds * 1000);
+ return 0;
+}
+int usleep(unsigned __int64 usec)
+{
+ LARGE_INTEGER li;
+ li.QuadPart = -10 * usec; // negative values for relative time
+
+ HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
+ if(!timer) return -1;
+
+ SetWaitableTimer(timer, &li, 0, NULL, NULL, 0);
+ WaitForSingleObject(timer, INFINITE);
+ CloseHandle(timer);
+ return 0;
+}
+#else
+# include
+#endif
+
+
+using namespace v8;
+using namespace node;
+
+
+Handle Sleep(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 1 || !args[0]->IsUint32()) {
+ return ThrowException(Exception::TypeError(String::New("Expected number of seconds")));
+ }
+
+ sleep(args[0]->Uint32Value());
+
+ return scope.Close(Undefined());
+}
+
+Handle USleep(const Arguments& args) {
+ HandleScope scope;
+
+ if (args.Length() < 1 || !args[0]->IsUint32()) {
+ return ThrowException(Exception::TypeError(String::New("Expected number of micro")));
+ }
+
+ usleep(args[0]->Uint32Value());
+
+ return scope.Close(Undefined());
+}
+
+
+extern "C" void init(Handle