diff --git a/bin/nexe b/bin/nexe old mode 100644 new mode 100755 index 41de4b4..2326de4 --- a/bin/nexe +++ b/bin/nexe @@ -1,2 +1,25 @@ #!/usr/bin/env node +var argv = require('optimist'). +usage('Usage: $0 -i [sources] -o [binary]'). +options('i', { + demand: true, + alias: 'input', + desc: 'The entry javascript files' +}). +options('o', { + demand: true, + alias: 'output', + desc: 'The output binary' +}). +options('r', { + alias: 'runtime', + default: '0.6.3', + description: 'The node.js runtime to use' +}).argv; + + +require('../lib').compile({ entries: argv.input.split(' '), output: argv.output, runtime: argv.r }, function(error) { + + if(error) console.log(error.message); +}); \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index 4fe7b43..4312e51 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,3 +1,227 @@ -exports.compile = function(ops, callback) { +var sardines = require('sardines'), +child_process = require('child_process'), +spawn = child_process.spawn, +exec = child_process.exec, +fs = require('fs'), +mkdirp = require('mkdirp'), +http = require('http'), +celeri = require('celeri'); + +const ETC_DIR = '/usr/local/etc/nexe'; +const RUNTIMES_DIR = ETC_DIR + '/runtimes'; +const CURRENT_RUNTIME_DIR = ETC_DIR + '/current-runtime'; + + +/** + */ + +function fileExists(file) { + try { + return !!fs.lstatSync(file); + } catch(e) { + return false; + } +} + +/** + * modify the input node.js file to evaluate nexe + */ + +function wrapNode(path) { + + var nodePath = path + '/src/node.js', + content = fs.readFileSync(nodePath,'utf8'); + + content = content.replace(/\(function\(process\) \{/,'function(process){ \n process._eval = require("nexe"); '); + + fs.writeFileSync(nodePath, content); +} + +/** + */ + +function nexeMain(path) { + var pkgPath = path + '/package.json'; + + if(!fileExists(pkgPath)) return null; + + var script = JSON.parse(fs.readFileSync(pkgPath,'utf8'))['nexe-main']; + + return script ? fs.realpathSync(path+'/' + script) : null; +} + +/** + */ + +function prepare(version, callback) { + + var runtimeDir = 'node-v' + version, + runtimeDirPath = RUNTIMES_DIR + '/' + runtimeDir, + runtimeTarPath = RUNTIMES_DIR + '/'+ runtimeDir + '.tar'; + + function onComplete() { + callback(false, { + path: runtimeDirPath, + libDir: runtimeDirPath + '/lib' + }); + } + + //file exists? already prepared + if(fileExists(runtimeDirPath)) return onComplete(); + + + mkdirp(runtimeDirPath, 0755, function(err) { + if(err) return callback(err); + + + //download the node.js runtime if it doesn't exist + http.get({ host: 'nodejs.org', port: 80, path: '/dist/v' + version + '/node-v' + version + '.tar.gz' }, function(res) { + + res.setEncoding('binary'); + + var output = fs.createWriteStream(runtimeTarPath, { 'flags': 'a' }), + size = Number(res.headers['content-length'] || 0), + progress = 0; + + res.on('data', function(chunk) { + progress += chunk.length; + celeri.progress('Downloading ' + runtimeDir, Math.floor(progress/size * 100)); + output.write(chunk, 'binary'); + }); + + res.on('end', function() { + + output.end(); + + + function onUnzipped(err) { + + fs.unlinkSync(runtimeTarPath); + if(err) return callback(err); + + wrapNode(runtimeDirPath); + + onComplete(); + } + + console.log('Configuring %s', runtimeDirPath); + exec('tar -xf ' + runtimeTarPath + '; cd ' + runtimeDirPath + '; ./configure', { cwd: RUNTIMES_DIR }, onUnzipped); + }); + + + + + }).on('error', function(e) { + + try { + fs.rmdirSync(runtimeDirPath); + } catch(e) { } + + callback(new Error('Unable to download node '+version+': '+e.message)); + }); + + + }); + + +} + +/** + */ + +function findIncludes(dir, inc) { + + if(!inc) inc = []; + + fs.readdirSync(dir).forEach(function(name) { + + if(name.substr(0,1) == '.' || name == 'node_modules') return; + + var subPath = dir + '/' + name; + + if(fs.statSync(subPath).isDirectory()) { + + findIncludes(subPath, inc); + + } else if(name.match(/\.js$/)) { + + inc.push(subPath); + } + }); + + return inc; +} + +/** + */ + +exports.compile = function(ops, callback) { + + if(!ops.entries) throw new Error('You must provide entry javascript files.'); + if(!ops.runtime) throw new Error('A node.js runtime version must be provided.'); + if(!ops.output) throw new Error('Output must be provided.'); + + + ops.output = ops.output.replace('~', process.env.HOME); + + prepare(ops.runtime, function(err, node) { + + if(err) return callback(err); + + var include = [], + entries = []; + + ops.entries.forEach(function(entry) { + + var main = nexeMain(entry); + + if(main) { + + findIncludes(entry).forEach(function(path) { + + include.push({ + script: path, + alias: path.replace(entry,'') + }); + + }); + + entries.push(main); + } else { + + entries.push(entry); + } + + + }); + + console.log('Making nexe.js'); + + //combine the JS + sardines.package({ input: entries, include: include, output: node.libDir + '/nexe.js' }, function(err) { + + if(err) return callback(new Error('Unable to make nexe.js')); + + console.log('Making executable'); + + var proc = spawn('make', [], { cwd: node.path }); + + proc.stdout.on('data', function(data) { + console.log(data.toString()); + }); + + proc.stderr.on('data', function(data) { + console.error(data.toString()); + }); + + proc.on('exit', function() { + exec('cp ./out/Release/node ' + ops.output, { cwd: node.path }, callback); + }); + + + }); + + + }); } \ No newline at end of file diff --git a/node_modules/.bin/sardines b/node_modules/.bin/sardines new file mode 120000 index 0000000..6a4bc8f --- /dev/null +++ b/node_modules/.bin/sardines @@ -0,0 +1 @@ +../sardines/bin/sardines \ No newline at end of file diff --git a/node_modules/celeri/.cupboard b/node_modules/celeri/.cupboard new file mode 100644 index 0000000..46d2b19 --- /dev/null +++ b/node_modules/celeri/.cupboard @@ -0,0 +1,2 @@ +[commands] +proj = subl --project project.sublime-project diff --git a/node_modules/celeri/.cupboard (minimacblack's conflicted copy 2011-11-04) b/node_modules/celeri/.cupboard (minimacblack's conflicted copy 2011-11-04) new file mode 100644 index 0000000..b1670fd --- /dev/null +++ b/node_modules/celeri/.cupboard (minimacblack's conflicted copy 2011-11-04) @@ -0,0 +1,7 @@ +[project] +name = celeri +[commands] +publish = npm publish --force, git add ., git commit -m "$@", git push origin master +rm = git rm -r $@ +ignore = echo $@ >> .gitignore + = true diff --git a/node_modules/celeri/.gitignore b/node_modules/celeri/.gitignore new file mode 100755 index 0000000..6e9e865 --- /dev/null +++ b/node_modules/celeri/.gitignore @@ -0,0 +1,2 @@ +node_modulesnode_modules + diff --git a/node_modules/celeri/MIT-LICENSE.txt b/node_modules/celeri/MIT-LICENSE.txt new file mode 100755 index 0000000..31d6550 --- /dev/null +++ b/node_modules/celeri/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Craig Condon + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/celeri/README.md b/node_modules/celeri/README.md new file mode 100755 index 0000000..bc81c9a --- /dev/null +++ b/node_modules/celeri/README.md @@ -0,0 +1,357 @@ + +### C-e-L-er-I + +![Alt command line](http://i.imgur.com/DA77U.png) + +### Features: + +- History (up/down arrows) +- Progress Bar +- Loading/busy spinner +- Password input +- Confirmation +- Prompt +- Multi-line tables +- Build flexible commands via [beanpole](https://github.com/spiceapps/beanpole) + - OR statement + - Middleware + - Parameters +- Trees + +### To Do: + +- Help menu api +- Title View +- Custom colors for each view (input, loader, progress, table, etc.): exports.colors = {} +- Error handling (display of command not found) +- Add transports instead of depending on native stdin/stdout + - Ability to use online + +## Usage: + + +### .on(event, callback) + +Listens for a key (enter, up, left, backspace, etc.), or command. See [beanpole](https://github.com/spiceapps/beanpole) for documentation. + +#### Hello World: + +```javascript + +var celeri = require('celeri'); + +celeri.on('hello :name', function(data) +{ + console.log("Hello %s!", data.name); +}); + +//open up character input! +celeri.open(); + +//parse the command line args +celeri.parse(process.argv); + +``` + +In terminal: + + node ./hello ↩ + > hello world ↩ + hello world! + +passed as arguments: + + node ./hello hello:world ↩ + hello world! + +#### "OR" statement: + +```javascript + + +celeri.on('hello :name OR hi :name', function(data) +{ + console.log('Hello ' + data.name +'!'); +}); + +celeri.on('set address :zip OR set address :city :state :zip', function(data) +{ + console.log("City: %s, State: %s, Zip: %s ", data.city || 'None provided', data.state || 'None provided', data.zip); +}); + +``` + +#### Middleware "->" statement: + + +```javascript + +celeri.on('delay :seconds', function(data) +{ + console.log("delaying for %s seconds", data.seconds); + + setTimeout(function(self) + { + if(!self.next()) console.log("done!"); + }, Number(data.seconds) * 1000, this); +}); + + +celeri.on('delay 1 -> say hello :name', function(data) +{ + console.log('hello %s!', data.name); +}); + +``` + +here's what you get: + + > delay 5 ↩ + delaying for 5 seconds + done + > say hello craig ↩ + delaying for 1 seconds + hello craig! + + + +### .progress(label, percent) + +```javascript + +var i = 0; + +var interval = setInterval(function() +{ + celeri.progress('Label: ', i++); + + if(i == 100) clearInterval(i); +}, 10); + +``` + +### .loading(label) + +```javascript + +var spinner = celeri.loading('Processing: '); + +setTimeout(function() +{ + spinner.done(true);//undefined = done, true = success, false = fail +}, 1000); + +```` + +### .prompt(label, callback) + +```javascript + +celeri.prompt('Username: ', function(input) +{ + +}); + +```` + +### .confirm(message, callback) + +```javascript + +celeri.confirm("Do you want to continue?", function(yes) +{ + if(yes) + { + //continue + } +}); + +``` + +### .password(label[, mask], callback) + +```javascript + +//mask = * +celeri.password('Password: ', '*', function(input) +{ + //password +}); + +//no mask +celeri.password('Password: ', function(input) +{ + //password +}); + +``` + +### .auth(callback) + +```javascript + +celeri.auth(function(user, pass) +{ + //auth here +}); + +``` + +### .loadHelp(filePath) + +```javascript + +celeri.on('help', function() +{ + celeri.loadHelp(__dirname +'/help.txt'); +}); + +``` + + +### .drawTable(objects, ops) + +```javascript + +var objects = [ + + { + name: 'Craig', + age: 21, + interests: 'Cooking, espresso, backpacking, coding' + }, + + + { + name: 'Tim', + age: 21, + interests: 'Design, Traveling, Photography' + + } + +]; + +celeri.drawTable(objects, { + columns: ['name','age','interests'] +}); + + +``` + + +Gives you something like: + + +![Alt command line](http://i.imgur.com/oUtC9.png) + + +Here's a multi-line table: + + +![Alt command line](http://i.imgur.com/O5o47.png) + +### .drawTree(tree) + +Draws a tree + +````javascript + +//print out the contents of the celeri object +celeri.drawTree(celeri); + +```` + +Here's another example: + +![Alt command line](http://i.imgur.com/4F0e0.png) + + +### Let's kick it up a notch + + +```javascript + +var celeri = require('../lib'); + + +var credentials; + + + +celeri.on('login OR login :user :pass', function(data) +{ + + //reference to the current request + var self = this; + + + //called after auth credentials have been entered in + function onAuth(creds) + { + + //credits wrong? DO NOT CONTINUE + if(creds.user != 'user' || creds.pass != 'pass') + { + return console.log("Incorrect user / pass".red); + } + + //otherwise, add the user to the CURRENT request so it can be passed + //onto the next route listener + self.user = creds.user; + + //cache the credentials so the user doesn't have to login each time + credentials = creds; + + //not another listener? display a success response + if(!self.next()) console.log("Logged in as %s", creds.user.green); + } + + + //user already logged in? pass! + if(credentials) + { + onAuth(credentials); + } + + //otherwise check if the user is passed in the route + else + if(data.user && data.pass) + { + onAuth(data); + } + + //or prompt for authentication + else + { + celeri.auth(function(user, pass) + { + onAuth({ user: user, pass: pass }); + }); + } +}); + + + +/** + * This stuff's private. The user has to be authenticated *before* this command is executed + */ + +celeri.on('login -> account', function() +{ + console.log('Here\'s your account info %s!', this.user.green); +}); + +celeri.open(); + + + +celeri.parse(process.argv); + + +``` + +Here's what you get: + +![Alt command line](http://i.imgur.com/g7ywq.png) + + diff --git a/node_modules/celeri/examples/auth.js b/node_modules/celeri/examples/auth.js new file mode 100755 index 0000000..921aab6 --- /dev/null +++ b/node_modules/celeri/examples/auth.js @@ -0,0 +1,13 @@ +var celery = require('../lib'); + +celery.prompt('Username: ', function(user) +{ + celery.password('Password: ', function(pass) + { + console.log('user: %s'.green, user); + console.log('pass: %s'.green, pass); + }); +}); + + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/authadv.js b/node_modules/celeri/examples/authadv.js new file mode 100755 index 0000000..b53875e --- /dev/null +++ b/node_modules/celeri/examples/authadv.js @@ -0,0 +1,69 @@ +var celery = require('../lib'); + +celery.open({ + + //required for middleware / or statements + //delimiter: '/', +}); + + +var credentials; + + + +celery.on('login OR login :user :pass', function(data) +{ + var self = this; + + function onAuth(creds) + { + if(creds.user != 'user' || creds.pass != 'pass') + { + return console.log("Incorrect user / pass".red); + } + + self.user = creds.user; + + //cache the credentials so the user doesn't have to login each time + credentials = creds; + + if(!self.next()) console.log("Logged in as %s", creds.user.green); + } + + + //user already logged in? pass! + if(credentials) + { + onAuth(credentials); + } + + //otherwise check if the user is passed in the route + else + if(data.user && data.pass) + { + onAuth(data); + } + + //or prompt for authentication + else + { + celery.auth(function(user, pass) + { + onAuth({ user: user, pass: pass }); + }); + } +}); + + + +/** + * private account into + */ + +celery.on('login -> account', function() +{ + console.log('Here\'s your account info %s!', this.user.green); +}); + + +celery.parse(process.argv); \ No newline at end of file diff --git a/node_modules/celeri/examples/confirm.js b/node_modules/celeri/examples/confirm.js new file mode 100755 index 0000000..6573244 --- /dev/null +++ b/node_modules/celeri/examples/confirm.js @@ -0,0 +1,16 @@ +var celery = require('../lib'); + +celery.confirm('Do you want to continue?', function(yes) +{ + if(yes) + { + console.log("YES!".green); + } + else + { + console.log("NO!".red); + } +}); + + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/exec.js b/node_modules/celeri/examples/exec.js new file mode 100755 index 0000000..016b5b0 --- /dev/null +++ b/node_modules/celeri/examples/exec.js @@ -0,0 +1,11 @@ +var celeri = require('../lib'); + + +celeri.exec('ls', ['-help'], { + exit: function() + { + console.log("DONE"); + } +}); + +celeri.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/hello.js b/node_modules/celeri/examples/hello.js new file mode 100755 index 0000000..f9bf4bb --- /dev/null +++ b/node_modules/celeri/examples/hello.js @@ -0,0 +1,52 @@ +var celery = require('../lib'); + +celery.open({ + prefix: 'hello > ' +}); +celery.on('hello :name', function(data) +{ + console.log('hello %s, how are you doing?', data.name); +}); + +celery.on('download/:file', function(data) +{ + console.log("starting"); + + var i = 0; + + data.file = decodeURIComponent(data.file); + + var interval = setInterval(function() + { + + celery.progress('Downloading '+data.file+':', i++); + + if(i > 100) + { + clearInterval(interval); + celery.newLine('done!'); + } + }, 10); +}); + + +celery.on(['timeout :ttl','timeout :ttl :status'], function(data) +{ + var loader = celery.loading('timeout for '+data.ttl+' seconds: '); + + setTimeout(function() + { + if(data.status != undefined) + { + loader.done(data.status == 'success'); + } + else + { + loader.done(); + } + + }, Number(data.ttl) * 1000); +}); + + +celery.parse(process.argv); \ No newline at end of file diff --git a/node_modules/celeri/examples/hello2.js b/node_modules/celeri/examples/hello2.js new file mode 100755 index 0000000..cfbd773 --- /dev/null +++ b/node_modules/celeri/examples/hello2.js @@ -0,0 +1,19 @@ +var celery = require('../lib'); + +celery.on('delay :seconds', function(data) +{ + console.log("delaying for %s seconds", data.seconds); + + setTimeout(function(self) + { + if(!self.next()) console.log("done!"); + }, Number(data.seconds) * 1000, this); +}); + + +celery.on('delay 1 -> say hello :name', function(data) +{ + console.log('hello %s!', data.name); +}); + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/table.js b/node_modules/celeri/examples/table.js new file mode 100755 index 0000000..ae06cb0 --- /dev/null +++ b/node_modules/celeri/examples/table.js @@ -0,0 +1,44 @@ +var celery = require('../lib'); + +var objects = [ + + { + name: 'Craig', + age: 21, + bio: 'Cras dictum convallis fermentum. Quisque ut urna velit, at porta nibh. Nam iaculis dignissim nisl, non elementum tortor iaculis et. Curabitur vulputate, sapien eget' + }, + + + { + name: 'Tim', + age: 21, + bio: 'Praesent ligula est, pellentesque vel euismod vitae, condimentum convallis odio. Suspendisse potenti. Fusce lacus arcu, bibendum in gravida at, dictum vitae mauris. Cras viverra, dui ac elementum fringilla, purus mauris rutrum nibh, id ultrices diam magna id ante. Integer elit ligula, cursus at accumsan in, scelerisque at dui. Sed pellentesque justo sit amet nibh sodales sed malesuada nulla cursus. Maecenas eu felis leo, a volutpat sapien. Duis eget porta urna. Maecenas ligula elit, vulputate ac bibendum eu, dapibus ut lacus. Fusce ac tincidunt eros. Pellentesque ut turpis ac ante interdum rutrum. Suspendisse tempor lobortis semper.' + }, + + { + name: 'Michael', + age: 23, + bio: 'Vestibulum ligula elit, vehicula a lacinia at, aliquet sed felis. In rutrum pulvinar ultrices. Donec interdum ullamcorper neque ut pretium. Donec varius massa vitae ipsum feugiat feugiat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Fusce a nulla a odio congue hendrerit in non tellus. Cras gravida vestibulum augue vitae dapibus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce porttitor rutrum faucibus. Vivamus interdum porta orci, vitae fermentum nunc vestibulum at. Maecenas porttitor sollicitudin pharetra. Ut risus mauris, tincidunt vitae laoreet quis, rhoncus eget risus' + }, + + { + name: 'Sarah', + age: 19, + bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin fringilla interdum nibh eget luctus. In facilisis varius lacus, ut adipiscing turpis posuere a. Nunc id sapien eu urna' + } + +]; + + +celery.drawTable(objects, { + columns: { + name: 15, + age: 5, + bio: 30 + }, + + horz: ' ', + +}); + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/table2.js b/node_modules/celeri/examples/table2.js new file mode 100644 index 0000000..13c47d1 --- /dev/null +++ b/node_modules/celeri/examples/table2.js @@ -0,0 +1,29 @@ +var celery = require('../lib'); + +var objects = [ { name: 'bean.cupboard.scaffold', + hasUpdates: '', + published: 'published: 2 hours agofdsfsafsfadffdsf afsd fasf as fsd fsdf sdf sdf sd ' }, + { name: 'teamdigest', + hasUpdates: '', + published: 'published: 2 hours ago' }]; + +console.log(celery.columns()) + +celery.drawTable(objects, { + columns: [{ + width: 15, + minWidth:20, + name: 'name' + }, + { + name: 'published', + width:15, + align:'right' + }], + + horz: ' ', + vert: '|' + +}); + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/table3.js b/node_modules/celeri/examples/table3.js new file mode 100644 index 0000000..f7ac0c4 --- /dev/null +++ b/node_modules/celeri/examples/table3.js @@ -0,0 +1,59 @@ +var celery = require('../lib'); + +var objects = [ { command: 'init', + desc: 'Adds a project in cwd to cupboard.' }, + { command: 'remove ', + desc: 'Removes project from cupboard.' }, + { command: ' ', + desc: 'Calls custom command specified in project cupboard config.' }, + { command: 'untouch ', + desc: 'Flags given project as updated.' }, + { command: 'publish ', + desc: 'Publishes target project.' }, + { command: 'updates', + desc: 'List all projects with updates.' }, + { command: 'list', + desc: 'List all projects in cupboard organized by most recently updated.' }, + { command: 'install ', + desc: 'Installs a third-party cupboard plugin.' }, + { command: 'uninstall ', + desc: 'Uninstalls a third-party cupboard plugin.' }, + { command: 'plugins', + desc: 'Lists all third-party plugins.' }, + { command: 'scaffold ', + desc: 'Initializes target scaffold in cwd' }, + { command: 'github ', + desc: 'Open github page of target project' }, + { command: 'github-issues ', + desc: 'Open github issues of target project.' }, + { command: 'help', desc: 'Shows the help menu.' }, + { command: 'dir ', + desc: 'Returns the project path.' }, + { command: 'details ', + desc: 'Returns details about the given project such as modified files, and number of updates.' } ]; + + +celery.drawTable(objects, { + columns: [ { + minWidth: 25, + width: 20, + name: 'command' + }, + { + name: 'desc', + width: 80, + align: 'left' + } ], + + pad: { + left: 10, + right: 10, + top: 2, + bottom: 2 + }, + +ellipsis: true + +}); + +celery.open(); \ No newline at end of file diff --git a/node_modules/celeri/examples/tree.js b/node_modules/celeri/examples/tree.js new file mode 100755 index 0000000..48f5087 --- /dev/null +++ b/node_modules/celeri/examples/tree.js @@ -0,0 +1,34 @@ +var celeri = require('../lib'); + +celeri.drawTree({ + 'home/':{ + 'network/':{ + 'apps/' :[ + "cliqly", + "clove", + "team digest" + ], + 'public/': { + 'git/':{ + 'some-project':[ + 'index.js' + ] + }, + 'npm/':{ + 'some-project':['index.js'] + } + } + } + }, + 'downloads/': { + 'libcpp': [ + 'makefile' + ] + } +}) + + +//celeri.drawTree(celeri); + + +celeri.open(); \ No newline at end of file diff --git a/node_modules/celeri/images/screen.png b/node_modules/celeri/images/screen.png new file mode 100755 index 0000000..69fa5c5 Binary files /dev/null and b/node_modules/celeri/images/screen.png differ diff --git a/node_modules/celeri/lib/index.js b/node_modules/celeri/lib/index.js new file mode 100755 index 0000000..e9e7644 --- /dev/null +++ b/node_modules/celeri/lib/index.js @@ -0,0 +1,401 @@ +var tty = require('tty'), +fs = require('fs'), +Structr = require('structr'), +beanpole = require('beanpole'), +_buffer = '', +router = beanpole.router(); + +exports.utils = require('./utils'); + + +//CLEAN ME!!!!!!!!!!!!!!!!! + +_delimiterRepl = /\s+/g, +_delimiter = ' '; + + +var _queue = [], +_queueRunning = false; + + +/** + * queued commands + */ + +exports.next = function(callback) +{ + exports.queue(callback)(); + + return this; +} + + +exports.queue = function(callback) +{ + return function() + { + var args = arguments, + listeners = [], + self = { + next: function() + { + var args = arguments; + + listeners.forEach(function(listener) + { + listener.apply(null, args); + }) + + _queueRunning = true; + if(_queue.length) + { + _queue.shift()(); + } + else + { + _queueRunning = false; + } + }, + attach: function(callback) + { + listeners.push(callback); + } + } + + _queue.push(function() + { + callback.apply(self, args); + }); + + + if(!_queueRunning) + { + self.next(); + } + + return exports; + } + + return exports; +} + +/** + * spacing between arguments + */ + +exports.delimiter = function(value) +{ + if(!arguments.length) return _delimiter; + + _delimiterRepl = new RegExp(value + '+','ig'); + + return _delimiter = value; +}; + + +/** + * Converts CLI arguments to beanpole routes. Nifty huh? + */ + +function _toRoute(type) +{ + return type.replace(_delimiterRepl, '\/'); +} + + + +/** + * size of the terminal window + */ + +exports.size = function() +{ + return tty.getWindowSize(); +} + +/** + * number of columns in the terminal window (characters / width) + */ + +exports.columns = function() +{ + return exports.size()[1] || exports.size(); +} + +/** + * number of rows in the terminal window + */ + +exports.rows = function() +{ + return exports.size()[0]; +} + +var _inputPrefix = '> '; + +exports.inputPrefix = function(prefix) +{ + if(!arguments.length) return _inputPrefix; + + + return _inputPrefix = prefix || ''; +} + + +exports.on = function(type, callback) +{ + + if(typeof type == 'object') + { + var disposables = []; + + if(type instanceof Array) + { + for(var i = type.length; i--;) + { + disposables.push(exports.on(type[i], callback)); + } + } + else + { + for(var t in type) + { + + disposables.push(exports.on(t, type[t])); + } + } + + + + return { + dispose: function() + { + disposables.forEach(function(disposable) + { + disposable.dispose(); + }); + } + }; + } + + return router.on('push /'+_toRoute(type), callback); + +} + +exports.emit = function(type, data) +{ + + //catch parse errors + try + { + return router.push(_toRoute(type), data, { meta: { passive: 1 } }); + } + catch(e) + { + //console.log(e.stack); + } + + return false; + +} + + +exports.buffer = function(value, ignoreReplace) +{ + if(!arguments.length) return _buffer; + + _buffer = value; + + return !ignoreReplace ? exports.replaceLine(value) : value; +} + +/** + * Replaces the current line in the terminal window + */ + +exports.replaceLine = function(buffer, cursorTo) +{ + + //need to clear the line before replacing it + process.stdout.clearLine(); + + //set the cursor to zero, otherwise we'll have padding we don't want + exports.cursor(0); + + //write the buffer + process.stdout.write(buffer); + + //set the cursor to the new position! + exports.cursor(cursorTo != undefined ? cursorTo : buffer.length); + + return _buffer = buffer; +} + + +/** + * inserts text into the current line + */ + +exports.insertText = function(str, position) +{ + var buffer = exports.buffer(); + exports.replaceLine(buffer.substr(0, position) + str + buffer.substr(position), position + str.length); +} + + +/** + * Takes a chunk of text out of the current line + */ + +exports.spliceLine = function(position, length, newCursor) +{ + + var buffer = exports.buffer(); + exports.replaceLine(buffer.substr(0, position) + buffer.substr(position + length), newCursor); +} + +var _cursorPosition = 0; + + +/** + */ + +exports.cursor = function(position) +{ + if(!arguments.length) return _cursorPosition; + + + process.stdout.cursorTo(position); + + return _cursorPosition = position; +} + + + +function stringRep(key) +{ + var chain = ''; + + for(var prop in key) + { + if(!key[prop]) continue; + + if(key[prop] == true) + { + chain = prop+'-'+chain; + } + else + { + chain += key.name; + } + } + + return chain; +} + +exports.write = function(string) +{ + process.stdout.write(string); +} + +exports.newLine = function(buffer) +{ + if(buffer) exports.write(buffer); + exports.write('\n'); + exports.buffer(''); +} + +exports.open = function(ops) +{ + if(ops) + { + if(ops.prefix) exports.inputPrefix(ops.prefix); + if(ops.delimiter) exports.delimiter(ops.delimiter); + } + + if(exports.opened) return; + exports.opened = true; + + + stdin = process.openStdin(); + stdin.setEncoding('utf8'); + tty.setRawMode(true); + + + + stdin.on('keypress', function(c, key) + { + + //integer? + if(!key) key = { name: c.toString() } + + + + + var chain = stringRep(key), + emitSuccess = exports.emit(chain); + + + //not a handled item to boot? Probably enter, delete, left, right, up, etc. Append it. + if(!emitSuccess && c) + { + if(!_buffer.length) + { + exports.insertText(exports.inputPrefix(), _cursorPosition); + } + exports.insertText(c, _cursorPosition); + //exports.insertText(c, Math.max(_cursorPosition, exports.inputPrefix().length)); + } + + + //new line? reset + if(key && key.name == 'enter') + { + //exports.replaceLine(exports.buffer().magenta); + process.stdout.write('\n'); + _buffer = ''; + _cursorPosition = 0; + //exports.insertText(exports.inputPrefix(), _cursorPosition); + //exports.cursor(0); + } + + + //for custom handlers: password, confirm, etc. + exports.emit('keypress', { char: c, key: key }); + + //character code? + if(key.name.length == 1) + { + exports.emit('charpress', c); + } + + + }); +} + + +exports.parse = function(args) +{ + var self = this; + + args.forEach(function(arg) + { + var argParts = arg.split(':'); + + for(var i = argParts.length; i--;) + { + argParts[i] = encodeURIComponent(argParts[i]); + } + self.emit(argParts.join('/')); + }); +} + + + + + +fs.readdirSync( __dirname + '/modules').forEach(function(module) +{ + + require( __dirname + '/modules/'+module).plugin(exports); +}); \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/auth.js b/node_modules/celeri/lib/modules/auth.js new file mode 100755 index 0000000..4d2e590 --- /dev/null +++ b/node_modules/celeri/lib/modules/auth.js @@ -0,0 +1,18 @@ +exports.plugin = function(cli) +{ + cli.auth = cli.queue(function(callback) + { + var self = this; + + self.attach(callback); + + cli.prompt('Username: ', function(user) + { + cli.password('Password: ','*', function(pass) + { + self.next(user, pass); + }); + }); + + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/backspace.js b/node_modules/celeri/lib/modules/backspace.js new file mode 100755 index 0000000..bf0897e --- /dev/null +++ b/node_modules/celeri/lib/modules/backspace.js @@ -0,0 +1,22 @@ +exports.plugin = function(cli) +{ + + + cli.on('backspace', function() + { + var pos = cli.cursor(); + + if(pos == cli.inputPrefix().length) return; + + cli.spliceLine(pos-1, 1, pos-1); + //cli.replaceLine(buffer.substr(0, pos-1) + buffer.substr(pos, buffer.length-pos), pos-1); + + }); + + cli.on('delete', function() + { + var pos = cli.cursor(); + + cli.spliceLine(pos, 1, pos); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/confirm.js b/node_modules/celeri/lib/modules/confirm.js new file mode 100755 index 0000000..a0d30bd --- /dev/null +++ b/node_modules/celeri/lib/modules/confirm.js @@ -0,0 +1,38 @@ +exports.plugin = function(cli) +{ + + + cli.confirm = cli.queue(function(label, callback) + { + label += ' [y/n]: '; + + cli.write(label); + + var input = '', yes = 'y', no = 'n', + self = this; + + self.attach(callback); + + var disposable = cli.on({ + 'keypress': function(data) + { + input = data.char; + + cli.buffer(label + input); + }, + 'enter': function() + { + if(input != yes && input != no) + { + return cli.write('\nPlease enter "'+yes+'" or "'+no+'"'); + } + + + disposable.dispose(); + + + setTimeout(self.next, 1, input == 'y'); + } + }); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/enter.js b/node_modules/celeri/lib/modules/enter.js new file mode 100755 index 0000000..846da4a --- /dev/null +++ b/node_modules/celeri/lib/modules/enter.js @@ -0,0 +1,38 @@ +exports.plugin = function(cli) +{ + + cli.on('enter', function() + { + var buffer = cli.buffer(), + commands = buffer.split('&&'); + + commands.forEach(function(command) + { + command = command.replace(cli.inputPrefix(),''); + + var args = command.match(/((["'])([^\\](?!\2)|\\.|\w)+\2|[^\s"']+)/ig); + + + if(!args) return; + + for(var i = args.length; i--;) + { + args[i] = encodeURIComponent(args[i]); + } + + + function emit(operation) + { + if(!cli.emit(args.join(cli.delimiter()))) + { + //console.log('illegal operation: "%s"'.red, operation); + //cli.emit('help'); + } + } + + setTimeout(emit, 1, args.join(cli.delimiter())); + }); + + + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/exec.js b/node_modules/celeri/lib/modules/exec.js new file mode 100755 index 0000000..5667363 --- /dev/null +++ b/node_modules/celeri/lib/modules/exec.js @@ -0,0 +1,87 @@ +var spawn = require('child_process').spawn; + +exports.plugin = function(cli) +{ + + /** + * goal = dead simple and painless. + */ + + cli.exec = function(command, args, ops, callback) + { + if(typeof args == 'function') + { + callback = args; + args = []; + ops = {}; + } + else + if(!(args instanceof Array)) + { + callback = ops; + ops = args; + args = []; + } + + + + if(typeof ops == 'function') + { + callback = ops; + ops = {}; + } + + //no callbacks? THEY MUST EXIST!!!! + if(!callback) callback = ops.callback || ops; + + var callbacks = {}; + + if(typeof callback != 'function') + { + callbacks = callback; + } + + if(!callbacks.error) callbacks.error = function(){}; + if(!callbacks.exit) callbacks.exit = function(){}; + if(!callbacks.data) callbacks.data = function(){}; + + + var procOps = { + cwd: ops.cwd, + env: ops.env, + customFds: ops.customFds + }; + + + var proc = spawn(command, ops.args || args, procOps), errors = [], buffer = []; + + proc.stdout.on('data', function(data) + { + buffer.push(data); + + callbacks.data(data); + }); + + proc.stderr.on('data', function(data) + { + errors.push(data); + + callbacks.error(data); + }); + + proc.on('exit', function(code) + { + + if(typeof callback == 'function') + { + callback(errors.length ? errors.join(' ') : false, buffer.length ? buffer.join(' ') : false); + } + else + if(callbacks.exit) + { + callbacks.exit(code); + } + }); + + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/help.js b/node_modules/celeri/lib/modules/help.js new file mode 100755 index 0000000..f068c7b --- /dev/null +++ b/node_modules/celeri/lib/modules/help.js @@ -0,0 +1,42 @@ +var fs = require('fs'); + +exports.plugin = function(cli) +{ + //cli.help = function(){}; + + + cli.openHelp = function(filePath, prefix) + { + if(!prefix) prefix = ''; + + var helpTxt = fs.readFileSync(filePath,'utf8'), coloredText; + + + //colored text + while(coloredText = helpTxt.match(/<(.*?)>([\w\W]*?)<\/\1>/)) + { + var colorAttrs = coloredText[1].split(' '), + text = coloredText[2]; + + colorAttrs.forEach(function (attr) + { + text = text[attr]; + }); + + helpTxt = helpTxt.replace(coloredText[0],text); + } + + /*helpTxt.split('\n').forEach(function(line) + { + console.log(prefix+line); + });*/ + + console.log(helpTxt); + } + + + /*cli.on('help', function() + { + cli.help(); + });*/ +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/history.js b/node_modules/celeri/lib/modules/history.js new file mode 100755 index 0000000..127c5e1 --- /dev/null +++ b/node_modules/celeri/lib/modules/history.js @@ -0,0 +1,33 @@ +exports.plugin = function(cli) +{ + var history = [], cursor = 0, max = 20; + + cli.on('enter', function() + { + history.push(cli.buffer()); + + if(history.length > max) + { + history.shift(); + } + + + cursor = history.length-1; + + }); + + + cli.on('up', function() + { + if(cursor == -1) return; + + cli.replaceLine(history[cursor--]); + }); + + cli.on('down', function() + { + if(cursor == history.length-1) return; + + cli.replaceLine(history[++cursor]); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/loading.js b/node_modules/celeri/lib/modules/loading.js new file mode 100755 index 0000000..8475752 --- /dev/null +++ b/node_modules/celeri/lib/modules/loading.js @@ -0,0 +1,43 @@ +exports.plugin = function(cli) +{ + cli.loading = function(label, callback) + { + + if(typeof label == 'function') + { + callback = label; + label = ''; + } + + if(!label) label = ''; + + + function done(message, success) + { + if(!message) message = success == undefined ? 'done' : (success ? 'success' : 'fail') ; + + var color = success == undefined ? 'grey' : (success ? 'green' : 'red'); + + + clearInterval(interval); + cli.replaceLine(label + message[color]['bold']); + cli.newLine(); + } + + if(callback) callback(done); + + var seq = '–\|/'; + pos = 0, + interval = setInterval(function() + { + cli.replaceLine(label+'['+seq[pos++%seq.length].blue+'] '); + }, 200); + + + return { + done: done + }; + + + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/nav.js b/node_modules/celeri/lib/modules/nav.js new file mode 100755 index 0000000..277d114 --- /dev/null +++ b/node_modules/celeri/lib/modules/nav.js @@ -0,0 +1,13 @@ +exports.plugin = function(cli) +{ + + cli.on('left', function() + { + cli.cursor(cli.cursor()-1); + }); + + cli.on('right', function() + { + cli.cursor(cli.cursor()+1); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/password.js b/node_modules/celeri/lib/modules/password.js new file mode 100755 index 0000000..667fd20 --- /dev/null +++ b/node_modules/celeri/lib/modules/password.js @@ -0,0 +1,58 @@ +exports.plugin = function(cli) +{ + + function getMask(mask, length) + { + if(!mask) return ''; + + var buffer = ''; + + for(var i = length; i--;) + { + buffer += mask; + } + + return buffer; + } + + + cli.password = cli.queue(function(label, mask, callback) + { + if(typeof mask == 'function') + { + callback = mask; + mask = undefined; + } + + + + cli.write(label); + + var input = '', + self = this; + + self.attach(callback); + + + var disposable = cli.on({ + 'backspace': function() + { + if(!input.length) return; + + input = input.substr(0, input.length-1); + }, + 'keypress': function(data) + { + if(data.key.name != 'backspace') + input += data.char; + + cli.buffer(label+getMask(mask, input.length)); + }, + 'enter': function() + { + setTimeout(self.next,1,input); + disposable.dispose(); + } + }); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/progress.js b/node_modules/celeri/lib/modules/progress.js new file mode 100755 index 0000000..25751b0 --- /dev/null +++ b/node_modules/celeri/lib/modules/progress.js @@ -0,0 +1,33 @@ +exports.plugin = function(cli) +{ + var spaces = 20, + perc = 0; + + function percentBuffer(label, color) + { + var diff = Math.round((spaces/100) * perc); + + + return label + ' ['+ cli.utils.fill('#'[color],diff,' ', spaces-diff) + '] '+ perc +'% '; + } + + cli.progress = function(label, percent) + { + //fail + if(percent === false) + { + cli.replaceLine(percentBuffer(label, perc, 'red')); + return cli.newLine(); + } + + perc = Math.min(percent, 100); + + cli.replaceLine(percentBuffer(label, perc == 100 ? 'green' : 'blue')); + + if(perc == 100) + { + return cli.newLine(); + } + + }; +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/prompt.js b/node_modules/celeri/lib/modules/prompt.js new file mode 100755 index 0000000..f248b02 --- /dev/null +++ b/node_modules/celeri/lib/modules/prompt.js @@ -0,0 +1,41 @@ +exports.plugin = function(cli) +{ + cli.prompt = cli.queue(function(label, callback) + { + var input = '', + self = this; + + self.attach(callback); + + + function write() + { + cli.replaceLine(label+input); + } + + + var disp = cli.on({ + 'backspace': function() + { + if(!input.length) return; + + input = input.substr(0, input.length-1); + }, + 'keypress': function(data) + { + if(data.key.name != 'backspace') + input += data.char; + + write(); + }, + 'enter': function() + { + setTimeout(self.next, 1, input); + disp.dispose(); + } + }); + + write(); + }); + +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/quit.js b/node_modules/celeri/lib/modules/quit.js new file mode 100755 index 0000000..b5b5de8 --- /dev/null +++ b/node_modules/celeri/lib/modules/quit.js @@ -0,0 +1,7 @@ +exports.plugin = function(cli) +{ + cli.on('ctrl-c', function() + { + process.exit(); + }); +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/section.js b/node_modules/celeri/lib/modules/section.js new file mode 100755 index 0000000..31c468a --- /dev/null +++ b/node_modules/celeri/lib/modules/section.js @@ -0,0 +1,6 @@ +exports.plugin = function(cli) +{ + cli.section = function(message) + { + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/table.js b/node_modules/celeri/lib/modules/table.js new file mode 100644 index 0000000..a0cbf97 --- /dev/null +++ b/node_modules/celeri/lib/modules/table.js @@ -0,0 +1,292 @@ +var Structr = require('structr'); + +exports.plugin = function(cli) +{ + function normalizeOptions(ops) + { + var cliWidth = cli.columns(); + + var columns = ops.columns, + normCols = [], + vert = ops.vertical || ops.vert || ' ', + horz = ops.horizontal || ops.horz || '', + pad = Structr.copy(ops.pad, { left: 0, right: 0, top: 0, bottom: 0 }); + + if(ops.padRight) pad.right = ops.padRight; + if(ops.padLeft) pad.left = ops.padLeft; + if(ops.padTop) pad.top = ops.padTop; + if(ops.padBottom) pad.bottom = ops.padBottom; + if(!ops.width) ops.width = cliWidth; + + ops.width = Math.min(ops.width, cliWidth - pad.left - pad.right); + + + if(ops.border) + { + if(vert == ' ') vert = ' | '; + if(horz == '') horz = '–'; + } + + + //sum width of all columns combined + var sumWidth = 0; + + for(var prop in columns) + { + var columnValue = columns[prop], + normCol = { minWidth: 6, align: 'left' }, + tocv = typeof columnValue; + + normCols.push(normCol) + + //['columnName'] + if(tocv == 'string') + { + normCol.name = columnValue; + } + else + { + //{columnName:value} + if(typeof prop == 'string') + { + normCol.name = prop; + } + + + if(tocv == 'number') + { + normCol.width = columnValue; + } + else + if(tocv == 'object') + { + Structr.copy(columnValue, normCol); + } + } + + if(!normCol.width) normCol.width = 100/columns.length; + + + + sumWidth += normCol.width; + } + + + //subtract vert padding + + + var sumActualWidth = 0, + colsTaken = 0, + numCols = normCols.length; + var tableWidth = ops.width - vert.length * numCols; + + + for(var i = 0; i < numCols; i++) + { + + var column = normCols[i]/*, + isLast = i == numCols-1, + align = column.align; + + if(!align) + { + column.align = isLast ? 'right' : 'left'; + }*/ + + var percWidth = Math.round(column.width/sumWidth * tableWidth); + actualWidth = Math.max(column.minWidth, percWidth), + + //diff between calculated perc width, and min width. used for penalization + difference = actualWidth - percWidth; + + sumActualWidth += actualWidth; + + + //this may happen if there are too many minWidths specified. In which case, not all columns + //will be shown. Actual width will be set to zero + if(sumActualWidth > ops.width) actualWidth -= Math.min(actualWidth, sumActualWidth - tableWidth); + + //actual width CANNOT be less than min width. e.g: single char column couold be huge. + if(actualWidth < column.minWidth) actualWidth = 0; + + column.actualWidth = actualWidth; + + //penalize the rest of the columns. Width must *not* cli width + sumWidth -= difference; + } + + return { + columns: normCols, + ellipsis: ops.ellipsis, + vert: vert, + horz: horz, + pad: pad, + width: ops.width, + numColumns: numCols, + showLabels: !!ops.showLabels + } + } + + function addLines(colLines, value, column) + { + var newLines = (value ? value.toString() : '').split(/[\r\n]/g); + + for(var i = 0, n = newLines.length; i < n; i++) + { + //trim whitespace off the ends. line breaks = whitespace + var buffer = newLines[i].replace(/^\s+|\s+$/g,''); + + var colors = buffer.match(/\u001b\[\d+m/g) || []; + + var padding = column.actualWidth - buffer.length + colors.join('').length; + + switch(column.align) + { + case 'right': + buffer = cli.utils.padLeft(buffer, padding, ' '); + break; + + case 'center': + buffer = cli.utils.pad(buffer, Math.floor(padding/2), ' ', Math.ceil(padding/2)); + break; + + default: + buffer = cli.utils.padRight(buffer, padding, ' '); + break; + } + + colLines.push(buffer); + } + } + + function getRowLineTable(item, ops) + { + var lineTable = [], + numLines = 0, + cols = ops.numColumns; + + + //get the lines. + for(var j = 0, jn = cols; j < jn; j++) + { + var column = ops.columns[j], + value = item[ops.columns[j].name] || '', + colLines = [], + actualWidth = column.actualWidth; + + //width not present? skip the column + if(!actualWidth) continue; + + + if(value.length > actualWidth) + { + if(ops.ellipsis) + { + var newBuffer = value.substr(0, actualWidth-3) + cli.utils.repeat('.', Math.min(actualWidth, 3)); + + addLines(colLines, newBuffer, column); + } + else + { + var start = 0; + + //splice apart the single line, treating each chunk as a new line + for(var k = actualWidth; k < value.length + actualWidth; k += actualWidth) + { + addLines(colLines, value.substr(start, actualWidth), column); + start = k; + } + } + } + else + { + addLines(colLines, value, column); + } + + //if this column lines + numLines = Math.max(numLines, colLines.length); + + + //next add the line - need to check against all lines now + lineTable.push(colLines); + + + //need to go through all the column lines again, and + //make sure all the lines match up properly + for(var k = 0, kn = lineTable.length; k < kn; k++) + { + var line = lineTable[k]; + + //must have same number of lineTable + if(line.length < numLines) + { + addLines(lineTable[k], cli.utils.repeat('\n', numLines - line.length -1), ops.columns[k]); + } + } + } + + var rows = []; + //inversed + for(var i = 0, n = lineTable.length; i < n; i++) + { + var col = lineTable[i]; + + //each row + for(var j = 0, jn = col.length; j < jn; j++) + { + if(!rows[j]) rows[j] = []; + + rows[j].push(col[j]); + } + } + + return rows; + } + + function logRow(ops, buffer) + { + console.log(cli.utils.repeat(' ', ops.pad.left) + buffer); + } + + function drawBreak(ops) + { + if(ops.horz) logRow(ops, cli.utils.repeat(ops.horz, ops.width)); + } + + function drawRow(lineTable, ops) + { + for(var i = 0, n = lineTable.length; i < n; i++) + { + logRow(ops, lineTable[i].join(ops.vert)) + } + + drawBreak(ops); + } + + function drawTable(source, ops) + { + if(ops.pad.top) console.log(cli.utils.repeat('\n', ops.pad.top-1)); + + drawBreak(ops); + + for(var i = source.length; i--;) + { + var lineTable = getRowLineTable(source[i], ops) + + drawRow(lineTable, ops); + } + + if(ops.pad.bottom) console.log(cli.utils.repeat('\n', ops.pad.bottom-1)); + + } + + + cli.drawTable = function(source, ops) + { + ops = normalizeOptions(ops); + drawTable(source, ops); + + // console.log(ops) + + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/table2.js b/node_modules/celeri/lib/modules/table2.js new file mode 100755 index 0000000..6062344 --- /dev/null +++ b/node_modules/celeri/lib/modules/table2.js @@ -0,0 +1,275 @@ +//oh my god what have I written. Quick, look away!!! + +exports.plugin = function(cli) +{ + + //draw table params & columns + //cli.drawTable(..., {name: 20, age: 20} + //TODO + + function addLines(ops) + { + var columnWidth = ops.columnWidth, + lines = ops.lines, + buffer = ops.buffer, + currentWidth = ops.currentWidth, + align = ops.align, + ellipsis = ops.ellipsis, + windowWidth = ops.windowWidth, + columnIndex = ops.columnIndex, + columns = ops.columns, + vert; + + + //last element? fill in the rest + if(columnIndex == columns.length-1) + { + columnWidth = windowWidth - currentWidth; + vert = ''; + } + else + { + vert = ops.vert; + } + + + var maxWidth = columnWidth - vert.length; + + + buffer.split('\n').forEach(function(line, index) + { + + if(line.length > maxWidth) + { + + //text too long? option to still keep it a one-liner + if(ellipsis) + { + line = line.substr(0, maxWidth-3) + '...'; + } + else + { + var start = 0; + var newLines = []; + + + for(var i = maxWidth; i < line.length + maxWidth; i += maxWidth) + { + newLines.push(line.substr(start, maxWidth)); + start = i; + } + + + return addLines({ + buffer: newLines.join('\n'), + columnWidth: columnWidth, + currentWidth: currentWidth, + align: ops.align, + windowWidth: windowWidth, + vert: vert, + lines: lines, + columnIndex: columnIndex, + columns: columns + }); + } + } + + padding = Math.max(columnWidth - line.length, 0); + + var colStr = ''; + + + + switch(align) + { + case 'right': + colStr = cli.utils.padLeft(line, padding, ' '); + break; + + case 'center': + colStr = cli.utils.pad(str, Math.floor(padding/2), ' ', Math.ceil(padding/2)); + break; + + default: + colStr = cli.utils.padRight(line, padding, ' '); + break; + + } + + + + if(!lines[index] ) + { + var buffer = ''; + + + for(var i = 0, n = columnIndex; i < n; i++) + { + buffer += cli.utils.padLeft(vert, columns[i].width-vert.length, ' '); + } + + lines[index] = buffer; + } +else +{ + console.log('GGG'+colStr); + console.log(index) +} + + + + + //console.log(maxWidth + " " + currentWidth+" "+lines[index].length); + + + + lines[index] += colStr + vert; + }); + } + + cli.drawTable2 = cli.table = function(objects, ops) + { + if(!(objects instanceof Array)) objects = [objects]; + + var windowWidth = ops.width || cli.columns(), + columns = ops.columns, + colArray = [], + vert = ops.vertical || ops.vert || ' ', + horz = ops.horizontal || ops.horz || '', + ellipsis = ops.ellipsis; + + + if(ops.padRight) windowWidth -= ops.padRight; + + + if(ops.border) + { + if(vert == ' ') vert = ' | '; + if(horz == '') horz = '–'; + } + + + + var tableWidth = 0, + title = {}, + medianColWidth; + + //convert the object into an array + if(columns instanceof Array) + { + colArray = columns; + + var numColumns = colArray.length, medianColWidth = Math.round(numColumns/windowWidth) + + for(var i = numColumns; i--;) + { + var col = colArray[i]; + + if(typeof col == 'string') + { + colArray[i] = col = { + name: col, + width: medianColWidth + }; + } + + title[col.name] = col.name; + tableWidth += col.width; + } + } + else + { + for(var property in columns) + { + var param = columns[property]; + + if(typeof param == 'number') + { + param = { + width: param, + }; + } + + param.name = property; + tableWidth += param.width || 0; + + title[param.name] = param.name; + colArray.push(param); + } + } + + //objects.unshift(title); + + + objects.forEach(function(object) + { + + var lines = []; + + var buffer = '', currentWidth = 0; + + for(var i = 0, n = colArray.length; i < n; i++) + { + var columnInfo = colArray[i]; + + if(typeof columnInfo == 'string') + { + columnInfo = { + name: columnInfo + }; + } + + if(!columnInfo.width) columnInfo.width = Math.round(100/n) + '%'; + + columnName = columnInfo.name; + + //percent + if(true || typeof columnInfo.width == 'string') + { + + //var cw = columnInfo.width.substr(0, columnInfo.width.length-1); + + columnWidth = Math.min(columnInfo.width, Math.floor((columnInfo.width/tableWidth) * windowWidth)); + + } + else + { + columnWidth = columnInfo.width; + } + + + //the string element. could be from a method, prop, or it's undefined + var str = (columnInfo.get ? columnInfo.get(object) : object[columnName] || 'Undefined').toString(); + + + + addLines({ + buffer: str, + lines: lines, + columnWidth: columnWidth, + currentWidth: currentWidth, + align: columnInfo.align, + windowWidth: windowWidth, + vert: vert, + ellipsis: ellipsis, + columnIndex: i, + columns: colArray + }); + + + currentWidth += columnWidth + vert.length; + + } + + if(horz.length) console.log(cli.utils.repeat(horz, windowWidth)); + + lines.forEach(function(line) + { + console.log(line); + }); + }); + + + if(horz) console.log(cli.utils.repeat(horz,windowWidth)); + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/modules/tree.js b/node_modules/celeri/lib/modules/tree.js new file mode 100755 index 0000000..00ef79e --- /dev/null +++ b/node_modules/celeri/lib/modules/tree.js @@ -0,0 +1,95 @@ +utils = require('../utils'), +Structr = require('structr'); + +//see http://en.wikipedia.org/wiki/Box-drawing_characters +exports.plugin = function(cli) +{ + + //┌── + //├── + //└── + + cli.drawTree = cli.tree = function(tree, ops, tab) + { + if(!ops) ops = {}; + + + var parts = { }; + + if(ops.pretty) + { + parts = { + pipe: '|', + tee: '┬', + dash: '─', + leftCorner: '└', + left: '├', + branch: utils.repeat('─', 1) + } + } + + //plays a little more nicely with fonts such as terminus + else + { + parts = { + pipe: '|', + tee: '+', + dash: '-', + leftCorner: '+', + left: '|', + branch: utils.repeat('-', 1) + } + } + + Structr.copy(ops.parts || {}, parts); + + + parts.tabs = utils.repeat(' ',parts.branch.length+1); + + + if(!tab) tab = ''; + + var n = utils.objectSize(tree), + i = 0, + printedBreak = false; + + + for(var index in tree) + { + + var childrenOrValue = tree[index], + toc = typeof childrenOrValue, + toi = typeof index, + edge = i < n-1 ? parts.left : parts.leftCorner; + + + var value = !isNaN(Number(index)) ? childrenOrValue : index + ': ' + childrenOrValue; + + + console.log('%s%s%s %s', tab, edge, parts.branch + ((toc == 'object') ? parts.tee : parts.dash), toc != 'object' ? value: index); + + + if(toc == 'object') + { + printedBreak = cli.drawTree(childrenOrValue, ops, n > 1 && i < n-1 ? tab + parts.pipe + parts.tabs.substr(1) : tab + parts.tabs); + } + /*else + if(toc == 'string' || toc == 'number') + { + + }*/ + + i++; + } + + + //add extra breaks for folders - a little more readable + if(!printedBreak) + { + console.log('%s',tab); + printedBreak = true; + } + + return printedBreak; + } +} \ No newline at end of file diff --git a/node_modules/celeri/lib/utils.js b/node_modules/celeri/lib/utils.js new file mode 100755 index 0000000..f208e47 --- /dev/null +++ b/node_modules/celeri/lib/utils.js @@ -0,0 +1,44 @@ +exports.padLeft = function(buffer, n, char) +{ + return exports.repeat(char, n) + buffer; +} + +exports.padRight = function(buffer, n, char) +{ + return buffer + exports.repeat(char, n); +} + + +//pad on left & right +exports.pad = function(buffer, ln, char, rn) +{ + return exports.repeat(char, ln) + buffer + exports.repeat(char, rn || ln); +} + + +exports.fill = function(leftChar, ln, rightChar, rn) +{ + return exports.repeat(leftChar, ln) + exports.repeat(rightChar, rn); +} + + +exports.repeat = function(char, n) +{ + var buffer = ''; + + for(var i = Math.abs(n); i--;) + { + buffer += char; + } + + return buffer; +} + +exports.objectSize = function(target) +{ + var n = 0; + + for(var i in target) n++; + + return n; +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/.cupboard b/node_modules/celeri/node_modules/beanpole/.cupboard new file mode 100644 index 0000000..46d2b19 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/.cupboard @@ -0,0 +1,2 @@ +[commands] +proj = subl --project project.sublime-project diff --git a/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22 (1)) b/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22 (1)) new file mode 100644 index 0000000..f2d80a5 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22 (1)) @@ -0,0 +1,2 @@ +[commands] +proj = open project.tmproj diff --git a/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22) b/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22) new file mode 100644 index 0000000..46d2b19 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/.cupboard (minimacblack's conflicted copy 2011-11-22) @@ -0,0 +1,2 @@ +[commands] +proj = subl --project project.sublime-project diff --git a/node_modules/celeri/node_modules/beanpole/.gitignore b/node_modules/celeri/node_modules/beanpole/.gitignore new file mode 100644 index 0000000..a051526 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/.gitignore @@ -0,0 +1,2 @@ +node_modules +n diff --git a/node_modules/celeri/node_modules/beanpole/MIT-LICENSE.txt b/node_modules/celeri/node_modules/beanpole/MIT-LICENSE.txt new file mode 100644 index 0000000..31d6550 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Craig Condon + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/celeri/node_modules/beanpole/README.md b/node_modules/celeri/node_modules/beanpole/README.md new file mode 100644 index 0000000..78665d0 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/README.md @@ -0,0 +1,392 @@ +## Beanpole - Routing framework + + +### What are some features? + +- Syntactic sugar (see below). +- Works with many protocols: amqp, http, websockets, etc. +- Hooking with other applications is a breeze with [daisy](https://github.com/spiceapps/daisy). +- Works well with coffeescript + + +### Projects using Beanpole + +- [celeri](https://github.com/spiceapps/celeri) - CLI library +- [bonsai](https://github.com/spiceapps/bonsai) - application server +- [leche](https://github.com/spiceapps/leche) - Framework to build frontend / backend applications with the same code. +- [daisy](https://github.com/spiceapps/daisy) - Expose beanpole to: http, websockets, amqp (rabbitmq), etc. +- [beandocs](https://github.com/spiceapps/beandocs) - Generate documentation from your beanpole route comments. +- [beanprep](https://github.com/spiceapps/beanprep) - Scans beans in a given directory, and installs their dependencies. +- [cupboard](https://github.com/spiceapps/beanprep) - Reverse package manager. + +### Beanpole ports + +- [Actionscript](https://github.com/spiceapps/beanpole.as) +- [C++](https://github.com/spiceapps/beanpoll) + +### Overview + + +![Alt ebnf diagram](http://i.imgur.com/v1wdO.png) + + +The basic route consists of a few parts: the `type` of route, and the `channel`. Here are some examples: + + router.on('pull hello/:name', ...); + +and + + router.on('push hello/:name', ...); + + +#### Push Routes: + +- Used to broadcast a message, or change (1 to many). +- Doesn't expect a response. +- Multiple listeners per route. + +#### Pull Routes: + +- Used to request data from a particular route (1 to 1). +- Expects a response. +- One listener per route. +- examples: + - request to http-exposed route + + + +Using both `push`, and `pull` allows you to **bind** to a particular route. For example: + + +````javascript + +var _numUsers = 0; + + +//numUser getter / setter function +function numUsers(value) +{ + if(!arguments.length) return _numUsers; + + _numUsers = value; + + router.push('users/online', value); +} + + +//the request handler. This could be called in-app. It's also just as easily exposable as an API to http, websockets, etc. +router.on('pull users/online', function(request) +{ + request.end(numUsers()); +}); + +//pull num users initially, then listen for when num users changes. +router.on('push -pull users/online', function(response) +{ + //handle change here.. + console.log(response); //0, 3, 10... +}); + + + +//triggers above listener +numUsers(3); +numUsers(10); + +```` + +Okay, so you might have noticed I added something funky here: `-pull` - that's a tag. Tags are structured like so: + + router.on('pull -tagName hello/:route', ...); + +or, you can add a value to it: + + router.on('pull -method=GET hello/:route', ...); + +As mentioned above, you can only have *one* listener per `pull` route. HOWEVER, you can have multiple listeners per `pull` route *if* you provide different tag values. For example: + +````javascript + +router.on({ + + /** + * returns the given user + */ + + 'pull -method=GET users/:userId': function(request) + { + //get the specific user + }, + + /** + * updates a user + */ + + 'pull -method=UPDATE users/:userId': function(request) + { + //update user here + }, + + /** + * deletes a user + */ + + 'pull -method=DELETE users/:userId': function(request) + { + //delete user + } + +}); +```` + +The above chunk of code is well suited for a REST-ful api without explicilty writing it *for* an http server. It can be used for any protocol. For example - say I wanted to *delete* a user using the code above: + +````javascript + +router.pull('users/' + someUserId, { tag: { method: 'DELETE'} }, function() +{ + //delete user response +}); + +```` + +You might have guessed - tags can be used to filter routes. Okay, onto something a little more advanced: **middleware**. Here's an example: + +````javascript + + +router.on({ + + /** + */ + + 'pull authorize': function(request) + { + if(request.data.secret != 'superSecret') + { + request.end('You shall not pass!'); + } + else + { + + //onto the next route + request.next(); + } + }, + + /** + */ + + 'pull -method=GET authorize -> my/profile': function(request) + { + request.end('Super secret stuff!'); + } + +}); + + +```` + +The token `->` denotes `my/profile` must go *through* the `authorize` route. Here are a few more use-cases: + +````javascript + +router.on({ + + /** + */ + + 'pull post/body': function(request) + { + //post http request body here. This is implemented in daisy + }, + + /** + */ + + 'pull session': function(request) + { + //initialize cookies for the user. Again, implemented in daisy + }, + + /** + */ + + 'pull -method=POST post/body -> session -> upload/video': function() + { + //passed through 2 routes before getting here. + }, + + /** + */ + + 'pull cache/:ttl': function(request) + { + //used to check if the *next* route is cached. If it is, then return the value vs continuing + }, + + /** + */ + + 'pull cache/10000 -> some/heavy/request': function(request) + { + //do some heavy stuff here, but go through the cache route so it's not called on each request + } + + +}) + +```` + +Middleware is especially useful for a REST-ful interface: + +````javascript + +router.on({ + + /** + * returns the given user + * @example /users/665468459 + */ + + 'pull users/:userId': function(request) + { + getUser(request.data.postId, funciton(user) + { + request.user = user; + + //route being used as middleware? + if(request.hasNext()) return request.next(); + + //return the user + request.end(user); + }) + }, + + /** + * Returns a post made by a particular user + * @example /users/665468459/posts/54353499534 + */ + + 'pull users/:userId -> users/:userId/posts/:postId': function(request) + { + getPosts(request.user, request.data.postId, function(posts) + { + request.end(posts); + }) + } +}); + +```` + +Middleware can also be specified without using the token: `->`.An example: + + +````javascript + +router.on({ + + /** + */ + + 'pull my/*': function() + { + //authorize user + }, + + /** + */ + + 'pull my/profile': function() + { + //goes through authorization first + } +}); + +```` + +Providing a wildcard `*` tells the router that **anything** after the route must go through it. + + +### Methods + +#### router.on(type[,listener]) + +Listens to the given routes + +- `type` - string or object. String would contain the route. Object would contain multiple routes / listeners +- `listener` - function listening to the route given. + + +#### router.push(route[, data][, options]) + +- `type` - the channel broadcast a message to. +- `data` - the data to push to the given route +- `options` - options for the given route + - `meta` - tags to use to filter out listeners + +#### router.pull(route[, data][, options][, callback]) + +same as push, but expects a response + +#### router.channels() + +returns all registered channels + +#### router.getRoute(route) + +returns route expression + +#### request.write(chunk) + +Initializes a streamed response. Great for sending files + +#### request.end([chunk]) + +Ends a response + +#### request.hasNext() + +Returns TRUE if there's a listener after the current one. + +#### request.next() + +Moves onto the next route. + +#### request.forward(channel, callback) + +Forwards the current request to the given channel + +#### request.thru(channel[ ,options]) + +Treats the given channel as middleware + +#### request.data + +Data is added here + + +### One last goodie + +Beanpole works well with coffeescript: + + +````coffeescript + +router.on + + # + 'pull -method=GET say/hello': -> + "hello world!" + +```` + + + + + + + + + + diff --git a/node_modules/celeri/node_modules/beanpole/beanpole.tmproj b/node_modules/celeri/node_modules/beanpole/beanpole.tmproj new file mode 100644 index 0000000..115e82d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/beanpole.tmproj @@ -0,0 +1,185 @@ + + + + + currentDocument + lib/core/middleware/route/pushPull/pull/request.js + documents + + + expanded + + name + beanpole + regexFolderFilter + !.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$ + sourceDirectory + + + + fileHierarchyDrawerWidth + 200 + metaData + + examples/bean.hello/beans/hello.core/index.js + + caret + + column + 14 + line + 9 + + columnSelection + + firstVisibleColumn + 0 + firstVisibleLine + 0 + selectFrom + + column + 3 + line + 9 + + selectTo + + column + 14 + line + 9 + + + examples/bean.hook.hello/beans/test/index.js + + caret + + column + 0 + line + 0 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + examples/ws/server.js + + caret + + column + 14 + line + 34 + + columnSelection + + firstVisibleColumn + 0 + firstVisibleLine + 0 + selectFrom + + column + 3 + line + 34 + + selectTo + + column + 14 + line + 34 + + + lib/core/concrete/collection.js + + caret + + column + 0 + line + 13 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/concrete/router.js + + caret + + column + 37 + line + 162 + + firstVisibleColumn + 0 + firstVisibleLine + 142 + + lib/core/controller.js + + caret + + column + 1 + line + 8 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/middleware/meta/rotate.js + + caret + + column + 60 + line + 22 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/middleware/route/pushPull/pull/request.js + + caret + + column + 0 + line + 14 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + + openDocuments + + lib/core/controller.js + examples/bean.hello/beans/hello.core/index.js + examples/bean.hook.hello/beans/test/index.js + lib/core/concrete/collection.js + lib/core/concrete/router.js + lib/core/middleware/meta/rotate.js + lib/core/middleware/route/pushPull/pull/request.js + examples/ws/server.js + + showFileHierarchyDrawer + + windowFrame + {{0, 4}, {1470, 1024}} + + diff --git a/node_modules/celeri/node_modules/beanpole/docs/beans/README.md b/node_modules/celeri/node_modules/beanpole/docs/beans/README.md new file mode 100644 index 0000000..6f7a6f6 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/beans/README.md @@ -0,0 +1,76 @@ +### Beans + +Beans are a fancy name for **plugin**. + +### Organization + +This is still very much a work in progress, but personally, I try to stick to a few conventions which help organize my "beans". Here are some general rules I follow: + +- All beans are placed in a single directory. The directory name depends on what the application does. + - If the app serves one platform, then place the beans in `app/beans`; + - If the app serves multiple platforms, then place the beans in: + - `app/node/beans` for node.js specific beans. + - `app/web/beans` for web-specific beans. + - `app/shared/beans` for beans usable across all platforms. + +- Bean names should reflect any RESTful API used in the bean. +- Beans in NPM have `bean` prepended to the name e.g: `bean.database.mongo`. + + + +### Naming Conventions + + +Start off with the category of the bean first, and then the subject. A few examples: + +- database.mongo +- database.redis +- database.mysql + +Using `database` as the category tells that all beans share the same API. I can easily add / remove any `database` bean I want without breaking the application. + + +If you have a plugin that uses many plugins, then try this naming convention: + +- `category`.core + +And for beans that make up `category.core`: + +- `category`.part.`subject` + +For example: + + +- stream.core +- stream.part.facebook +- stream.part.twitter +- stream.part.google + + +Where all the **parts** make up `stream.core`. Remember that parts shouldn't do **anything**. They make-up core plugins. If you have a plugin that serves several plugins, split it up like so: + +- posting.part.facebook +- friends.part.facebook + +You could also do something like: + +- stream.core +- group.core +- group.part.stream.core `part of stream.core` + + +Try and follow a RESTful naming convention. For example: + + +- stream.core +- stream.part.subscription.core `listening for streamed content, and sending off to registered subscribers` +- stream.part.subscription.email `subscription listening to stream, and sending a newsletter` +- stream.part.subscription.facebook `subscription listening to a stream, and posting out to facebook` + +Note that `part` was dropped after `subscription`. I find it reduntant to use it after the first instance. We already know that `stream.part.subscription.core` is nothing without `stream.core`, so anything *after* that is also useless without the root plugin. + + + + + + diff --git a/node_modules/celeri/node_modules/beanpole/docs/brainstorming/README.txt b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/README.txt new file mode 100644 index 0000000..1da1f1d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/README.txt @@ -0,0 +1 @@ +These notes are just so I can straighten out ideas about the architecture. \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/docs/brainstorming/analogy.txt b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/analogy.txt new file mode 100644 index 0000000..b2804d4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/analogy.txt @@ -0,0 +1 @@ +- modularized skyscraper \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/docs/brainstorming/ideas.txt b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/ideas.txt new file mode 100644 index 0000000..fe71bbc --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/brainstorming/ideas.txt @@ -0,0 +1,155 @@ +--------------------------------- +Abstracting beanpole: +--------------------------------- + +Plugins *MUST NOT* know if whether a computer is networked. That job is delegated for *one* particular module: glue.core. If a client connects to a server, and contains a hook which acts like a plugin, the backend should treat it exactly as it would with a another networked server, or even internally. Glue.core would handle the handshake / authentication. + +Likewise, connected servers using brazen must not handle communication with other servers differently than internally. + + +For security sake, each channel must provide metadata identifying whether it's private, protected, or public. Channels default to private if it's absent. + + - Public channels are available to call without authentication + - Protected channels are available to call only by other crusted servers / clients + - Private channels can only be handled within the application. + +All metadata is handled by the parser / router. + + +--------------------------------- +Routing: +--------------------------------- + +The routing mechanism should parse syntactic sugar to identify how a particular channel is handled. Each channel must be separated by backslashes to allow for parameters. This is primarily for future implementation where beanpole might support HTTP requests. + +'[type] [meta]* [channel_name]* [channel/:param] [additional]*' + +- type: the type of channel - push, pull, ??? +- meta: information attached to channel help glue.core, and other handlers. +- channel_name: the name of the channel. Private use from channel. Useful if channel needs to change, like a variable name. +- channel: the physical channel separated/by/backslashes +- additional: additional parameters specific to the channel type. + +on push application/ready: function(data){} + +'push private -pull application/ready' + +on private pull of application ready passing through application exists: + +'pull private application/exists -> application/ready': function(pull){ } + + +Calling back: + +There needs to be a way for modules handling a particular request to identify where it's coming from. + +--------------------------------- +Types of channels: +--------------------------------- + +- pull - (getting) channels which respond to a particular request which maybe pushed out at a later time. This is from the source that makes the "push" with the same name. +- push - (setting) channels which are pushed out are used after a particular change has occurred. This is one to many. + +Why I chose for push/pull to be different handlers with the same name: + +Inspiration was actually taken back in the day when I was developing in Actionscript (I know, stfu). Bindable metadata was a slick way of getting a particular property from an object, and then sticking to it for any changes. For beanpole, "pull" would be the action of getting the current value of a particular "pod" (object), and "push" is the method of sticking to it. + +Problems: + +How do we distinguish single pulls from multiple pulls? For instance, for multiple pulls, I may want to "pull" stats from all the servers, but for a single pull, I may want to register a particular queue, and *only* send it to one instance. + +Possible solutions: + +on('pull multi…') + +proxy.pull('multi…') + +is a different channel handing than + +on('pull…') +proxy.pull('…') + +So technically, if I register + +proxy.on('pull get.name', …') +proxy.on('pull multi get.name') + +there wouldn't be any complaining, since I can call only one, or the other. Where the first one can be the *only* one, and the second one can have multiple. SO + +proxy.pull('get.name') + +would be the first one, and + +proxy.pull('multi get.name') + +would be the second one. + + +Multiple pulls also need to return to the requestor how many items are handling the request. This probably needs to take on a response, ondata, and end approach similar to node.js's streaming api + +Streaming: + +Without adding too much shit to the architecture, there may come a time where content is streamed to the particular requestor. This could be highly beneficial for programs which send files back and forth. Something which beanpole isn't necessarily equipped for at the moment. So, without changing the architecture, perhaps providing a method for supporting such a feature. For example: + +This could be used: + +proxy.pull('get.file','text.txt', { + data: function(buffer) + { + }, + end: function() + { + } +}); + +or this could be used: + +proxy.pull('get.file','text.txt',function(body) +{ +}); + + +But what about pulling from multiple sources? + +proxy.pull('multi get.file', 'text.txt', function(source) //callback multiple times +{ + source.on('data… +}); + + +Hmmmm… + + +-------------------------------- +Network Topology +-------------------------------- + +The architecture, mainly glue.core must have the ability to manage connected servers. Many of which should only communicate to particular applications. For instance: Currently there are two applications on spice.io which register queue's to the queue app . Each application has a slave which handles the cue, but the queue must know which slaves to send to. So: + +- Each app must have an identifier shared amongst other apps it needs to communicate with (_appId) +- Since queues are protected, the handshake to between the queue app and the requester must be authenticated. +- The queue must receive the app id, and know what apps to send to via registered channels. + +What if there are dozens of slaves running across a cluster of servers? + +there *must* be a way for glue.core to use a load-balancing mechanism to send individual pulls to servers: round robin, least connected, etc. Stats from servers to see which is less busy? + +What if there are multiple singleton pulls registered to glue.core? + +Duh, fucking round-robin that shit when a pull-request is made. + + + + + + + + + + + + + + + + diff --git a/node_modules/celeri/node_modules/beanpole/docs/build-ebnf b/node_modules/celeri/node_modules/beanpole/docs/build-ebnf new file mode 100755 index 0000000..a4a085d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/build-ebnf @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +var ebnf = require('ebnf-diagram'); + +ebnf.fromFile(__dirname + '/syntax.ebnf', __dirname + '/diagram.png',3000, 1654); diff --git a/node_modules/celeri/node_modules/beanpole/docs/diagram.png b/node_modules/celeri/node_modules/beanpole/docs/diagram.png new file mode 100644 index 0000000..a2489a6 Binary files /dev/null and b/node_modules/celeri/node_modules/beanpole/docs/diagram.png differ diff --git a/node_modules/celeri/node_modules/beanpole/docs/syntax.ebnf b/node_modules/celeri/node_modules/beanpole/docs/syntax.ebnf new file mode 100644 index 0000000..83db97a --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/docs/syntax.ebnf @@ -0,0 +1,5 @@ +"" { +syntax = ('push' | 'pull') { tag } channel { '->' channel }. +tag = '-' name [ '=' value ]. +channel = '/' { [':'] name '/' } ['*']. +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.core/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.core/index.js new file mode 100644 index 0000000..b65b64b --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.core/index.js @@ -0,0 +1,18 @@ +exports.plugin = function(mediator) +{ + + function init() + { + console.log('calling plugins to say hello...'); + + mediator.pull(' -multi say/hello', function(response) + { + console.log(response); + }); + } + + mediator.on({ + 'push init': init + }); + +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.friend/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.friend/index.js new file mode 100644 index 0000000..ccc4b5a --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.friend/index.js @@ -0,0 +1,13 @@ +exports.plugin = function(mediator) +{ + + function sayHello(pull) + { + pull.end('Hello Friend!'); + } + + + mediator.on({ + 'pull -multi -public say/hello': sayHello + }); +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.neighbor/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.neighbor/index.js new file mode 100644 index 0000000..22c6918 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/beans/hello.neighbor/index.js @@ -0,0 +1,13 @@ +exports.plugin = function(mediator) +{ + + function sayHello(pull) + { + pull.end('Hello Neighbor!'); + } + + + mediator.on({ + 'pull -multi -public say/hello': sayHello + }) +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hello/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/index.js new file mode 100644 index 0000000..5682f02 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hello/index.js @@ -0,0 +1,3 @@ +var beanpole = require('../../lib/node'); + +beanpole.require(__dirname + '/beans').push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/beans/test/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/beans/test/index.js new file mode 100644 index 0000000..b5b1122 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/beans/test/index.js @@ -0,0 +1,72 @@ +var lazy = require('sk/core/lazy').callback; + + +exports.plugin = function(mediator) +{ + var ops, sent = 0, received = 0, pulls = 0, capp = 0, interval; + + function testSend(pull) + { + // console.log('received: %d', ++received); + + /*if(received != sent) + { + console.log(recieved-sent) + }*/ + + + pull.end(++received); + } + + function pushHook(data, err, request) + { + console.success('starting test.'); + + timeout(data, ++capp, request); + } + + function timeout(data, index, request) + { + var margin = 0; + + setTimeout(function() + { + for(var i = ops.concurrent; i--;) + { + // console.log('sent %d', ++sent); + + margin++; + + + request.from.pull('test/send', function(rcv) + { + // console.log('received: %d', rcv); + + //wait till everything's done. Stop if anything's missed. + if(!(--margin)) + { + console.log('#%d: done pulling %d requests from app #%d', ++pulls, ops.concurrent, index); + timeout(request, index); + } + + }); + } + + }, ops.speed); + } + + function init(op) + { + ops = op; + console.success('ready: speed=%d, concurrent=%d', ops.speed, ops.concurrent); + + console.success('Now open another terminal window with the same script'.underline); + } + + mediator.on({ + 'push init': init, + 'pull -public test/send': testSend, + 'push hook/connection': pushHook + }); + +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/index.js new file mode 100644 index 0000000..d4c0b1d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.call.receive/index.js @@ -0,0 +1,28 @@ +var beanpole = require('../../lib/node'), +cli = require('sk/node/cli'); + +var ops = {}; + +process.stdout.write('num concurrent calls: '); + +cli.next(function(arg) +{ + ops.concurrent = Number(arg) || 10; + + process.stdout.write('speed (ms): '); + + cli.next(function(arg) + { + ops.speed = Number(arg) || 200; + + + beanpole.require(['hook.core','hook.http.mesh']). + require(__dirname + '/beans').push('init', ops); + }) +}) + + + + +// + \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/beans/test/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/beans/test/index.js new file mode 100644 index 0000000..764cc88 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/beans/test/index.js @@ -0,0 +1,41 @@ +var lazy = require('sk/core/lazy').callback; + + +exports.plugin = function(mediator) +{ + var myName; + + function pushSayHello(guestName) + { + console.log('hello %s!', guestName); + + if(this.from) + { + this.from.push('say/hello/back', myName); + } + } + + function pushSayHelloBack(guestName, err, push) + { + console.log('%s said hello back!', guestName); + } + + function pushHook(data, err, push) + { + console.success('A person decided to join the partayyy.'); + push.from.push('say/hello', myName) + } + + function init(n) + { + myName = n; + pushSayHello(n); + } + + mediator.on({ + 'push init': init, + 'push hook/connection': pushHook, + 'push -public say/hello': pushSayHello, + 'push -public say/hello/back': pushSayHelloBack, + }) +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/index.js new file mode 100644 index 0000000..2d17c36 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.hello/index.js @@ -0,0 +1,26 @@ +var beanpole = require('../../lib/node'), + argv = process.argv.concat(); + +argv.splice(0,2); + +var name = argv[0]; + +function onName(name) +{ + beanpole.require(['hook.core','hook.http.mesh']). + require(__dirname + '/beans').push('init', name.toString().replace('\n','')); + + process.stdin.removeListener('data', onName); +}; + +if(name) +{ + onName(name) +} +else +{ + process.stdout.write('Name: '); + process.stdin.on('data', onName); + + process.openStdin(); +} diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/beans/test/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/beans/test/index.js new file mode 100644 index 0000000..577f98f --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/beans/test/index.js @@ -0,0 +1,41 @@ +var lazy = require('sk/core/lazy').callback; + + +exports.plugin = function(mediator) +{ + var myName; + + function pushSayHello(guestName) + { + console.log('hello %s!', guestName); + + if(this.from) + { + this.from.push('say/hello/back', myName); + } + } + + function pushSayHelloBack(guestName, push) + { + console.log('%s said hello back!', guestName); + } + + function pushHook(data, push) + { + console.success('A person decided to join the partayyy.'); + push.from.push('say/hello', myName) + } + + function init(n) + { + myName = n; + pushSayHello(n); + } + + mediator.on({ + 'push init': init, + 'push hook/connection': pushHook, + 'push -public say/hello': pushSayHello, + 'push -public say/hello/back': pushSayHelloBack, + }) +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook1.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook1.js new file mode 100644 index 0000000..8d0796c --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook1.js @@ -0,0 +1,32 @@ +var beanpole = require('../../lib/node'), + argv = process.argv.concat(); + +beanpole.require(['hook.http.mesh','hook.core']); + +beanpole.on({ + 'pull -public hook2': function() + { + this.next(); + }, + 'pull -public hook2 -> thru/hook2 -> test/hook': function() + { + console.log("fetching account..."); + + return "Successfuly passed through remote middleware"; + }, + 'push -public hook2/ready': function() + { + console.log("Connected to hook 2"); + + beanpole.pull('test/hook', function(message) + { + console.success(message); + }) + } +}); + +beanpole.push('init'); +beanpole.push('ready','hook1'); + + +console.log('hook1 is ready'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook2.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook2.js new file mode 100644 index 0000000..0d4a81b --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook2.js @@ -0,0 +1,32 @@ +var beanpole = require('../../lib/node'), + argv = process.argv.concat(); + +beanpole.require(['hook.http.mesh','hook.core']); + +beanpole.on({ + + 'pull -public thru/hook2': function() + { + console.log("Through hook 2"); + + + setTimeout(function(self) + { + console.success("done!") + self.next(); + }, 500, this) + }, + + 'push -public hook1/ready': function() + { + console.log("Connected to hook 1"); + } +}); + + +beanpole.push('init'); +beanpole.push('ready','hook2'); + + +console.log('hook2 is ready'); + diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook3.js b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook3.js new file mode 100644 index 0000000..ee113e4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.hook.middleware/hook3.js @@ -0,0 +1,26 @@ +var beanpole = require('../../lib/node'), + argv = process.argv.concat(); + +beanpole.require(['hook.http.mesh','hook.core']); + +beanpole.on({ + + 'pull -public thru/hook3': function() + { + console.log('thru hook 3'); + + if(!this.next()) return "authenticated" + }, + 'push -public hook1/ready': function() + { + console.log("connected to hook 1"); + } +}); + + +beanpole.push('init'); +beanpole.push('ready','hook2'); + + +console.log('hook2 is ready'); + diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.http.middleware/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.http.middleware/index.js new file mode 100644 index 0000000..c043b11 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.http.middleware/index.js @@ -0,0 +1,101 @@ +var beanpole = require('../../lib/node').router(), +express = require('express'), +Url = require('url'); + +beanpole.require('middleware.core'); + +beanpole.on({ + + + /** + */ + + 'pull -public basic/auth/root/pass -> basic/auth': function() + { + if(!this.next()) return 'authorized!'; + }, + + /** + */ + + 'pull -public basic/auth -> auth/text': function() + { + return "authorized: " + this.user.name; + }, + + + /** + */ + + 'pull -public session -> test/session': function() + { + var sess = this.session.data; + + if(!sess.numVisits) sess.numVisits = 0; + + sess.numVisits++; + + return 'Num Visits: '+sess.numVisits; + }, + + /** + */ + + 'push init': function(init) + { + var srv = express.createServer(), + channels = beanpole.channels(); + + + function initPath(path, expr) + { + srv.get('/' + path, function(req, res) + { + beanpole.pull(Url.parse(req.url).pathname, null, { meta: { stream: 1 }, req: req }, function(writer) + { + writer.on({ + response: function(headers) + { + if(headers.session) + { + res.setHeader('Set-Cookie', headers.session.http) + } + + if(headers.authorization) + { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', headers.authorization.http); + } + }, + write: function(data) + { + res.write(typeof data == 'object' ? JSON.stringify(data) : data); + }, + end: function() + { + res.end(); + } + }); + + }) + }); + } + + for(var channel in channels) + { + var expr = channels[channel]; + + if(expr.type == 'pull' && expr.meta.public) + { + initPath(channel, expr); + } + } + + srv.listen(8032); + } + + +}); + + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/hello.core/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/hello.core/index.js new file mode 100644 index 0000000..17a9ff1 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/hello.core/index.js @@ -0,0 +1,34 @@ +exports.plugin = function(mediator) +{ + + function meta1(pull) + { + pull.end('metadata 1'); + } + + function meta2(pull) + { + pull.end('metadata 2'); + } + + function meta3(pull) + { + pull.end('metadata 3'); + } + + function filterMeta(pull) + { + mediator.pull('meta', null, { meta: { group: pull.data.group } }, function(data) + { + pull.end(data || ''); + }); + } + + mediator.on({ + 'pull -public -rotate -group=1 meta': meta1, + 'pull -public -rotate -group=2 meta': meta2, + 'pull -public -rotate -group=3 meta': meta3, + 'pull -public meta/:group': filterMeta + }); + +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/http.server/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/http.server/index.js new file mode 100644 index 0000000..059848d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/beans/http.server/index.js @@ -0,0 +1,41 @@ +var express = require('express'); + +exports.plugin = function(mediator) +{ + + function init(pull) + { + var srv = express.createServer(); + + mediator.pull('hook', function(data) + { + data.channels.forEach(function(channel) + { + srv.get('/'+channel.name, function(req, res) + { + var name = channel.name; + + for(var param in req.params) + { + name = name.replace(':'+param,req.params[param]) + } + + mediator.pull('-stream ' + name, function(writer) + { + writer.pipe(res); + }) + }); + }); + + srv.listen(8032); + }); + + } + + console.log('Server running on port ' + 8032+'. try http://localhost:8032/meta/[1,2,3], or omit the number and watch them rotate.'); + + + mediator.on({ + 'push init': init + }); +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/index.js new file mode 100644 index 0000000..ca57080 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.http.server/index.js @@ -0,0 +1,3 @@ +var beanpole = require('../../lib/node'); + +beanpole.require(['hook.core','hook.http.mesh']).require(__dirname + '/beans').push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/beans/hello.core/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/beans/hello.core/index.js new file mode 100644 index 0000000..21c8ea4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/beans/hello.core/index.js @@ -0,0 +1,46 @@ +exports.plugin = function(mediator) +{ + + function init() + { + var i = 0; + + //default + mediator.pull('load/site', { site: 'http://www.google.com/' }, function(chunk) + { + console.log('http://www.google.com chunk #%d', i++); + }); + + //letting brazilnut handle the combining of buffers + mediator.pull('-batch load/site', { site: 'http://www.engadget.com/' }, function(buffer) + { + console.log('done reading http://engadget.com with %d chunks.', buffer.length); + }); + + + //streaming data + mediator.pull('-stream load/site', { site: 'http://www.google.com/' }, function(reader) + { + var buffer = []; + + reader.on({ + write: function(chunk) + { + buffer.push(chunk) + }, + end: function() + { + console.log('done reading http://google.com with %d chunks.', buffer.length); + } + }) + }); + + + + } + + mediator.on({ + 'push init': init + }); + +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/index.js b/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/index.js new file mode 100644 index 0000000..a1e015a --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/bean.website.load/index.js @@ -0,0 +1,3 @@ +var brazilnut = require('../../lib/node'); + +brazilnut.require(__dirname + '/beans').push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/benchmark.silly/index.js b/node_modules/celeri/node_modules/beanpole/examples/benchmark.silly/index.js new file mode 100644 index 0000000..27cb531 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/benchmark.silly/index.js @@ -0,0 +1,32 @@ +var beanpole = require('../../lib/node').router(), +Structr = require('structr'); + + + +function hello() +{ + return "hello!."; +} + + + + + +beanpole.on({ + 'pull hello/silly/world': hello +}) + +var start = new Date(); + +for(var i = 10000; i--;) +{ + beanpole.pull('hello/silly/world', function (res) + { + // console.log(res) + }); + +} + +console.log(new Date().getTime() - start.getTime()); + + \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/default/index.js b/node_modules/celeri/node_modules/beanpole/examples/default/index.js new file mode 100644 index 0000000..eb8ccbc --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/default/index.js @@ -0,0 +1,49 @@ +var beanpole = require('../../lib/node').router(); + +function all() +{ + console.log('all'); + + if(!this.next()) + { + console.log("DONE!") + } +} + +function all2() +{ + console.log("ROTATE") +} + +function thru() +{ + console.log('thru'); + + if(!this.next()) + { + console.log("CANNOT CONTINUE!") + } +} + +function thru2() +{ + console.log("THRU 2"); + this.next(); +} + +function sayHi(message) +{ + console.log(message); +} + +beanpole.on({ + 'dispatch /*': all, + // 'dispatch -d /*': all2, + 'dispatch thru2': thru2, + 'dispatch thru2 -> thru': thru, + 'dispatch thru2 -> thru -> thru -> hello': sayHi +}); + +// beanpole.dispatch('hello','world!'); +// beanpole.dispatch('hello','world!'); +beanpole.dispatch('hello','world!'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/beans/test/index.js b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/beans/test/index.js new file mode 100644 index 0000000..1599c1d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/beans/test/index.js @@ -0,0 +1,6 @@ +exports.plugin = function(mediator) +{ + + +} + diff --git a/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/index.js b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/index.js new file mode 100644 index 0000000..2e57072 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata.rotate/index.js @@ -0,0 +1,75 @@ +var beanpole = require('../../lib/node').router(); + + +function hello1(pull) +{ + return "hello 1!"; +} + +function hello2(pull) +{ + return "hello 2!"; +} + +function hello3(pull) +{ + return "hello 3!"; +} + + +function init() +{ + //hello 3! + beanpole.pull('say/hello', function(msg) + { + console.log(msg) + }); + + //hello 1! + beanpole.pull('say/hello', function(msg) + { + console.log(msg) + }); + + //hello 2! + beanpole.pull('say/hello', function(msg) + { + console.log(msg) + }); + + //hello 2! + beanpole.pull('-name=group1 say/hello', function(msg) + { + console.log(msg) + }); + + //hello 3! + beanpole.pull('-name=group1 say/hello', function(msg) + { + console.log(msg) + }); + + //hello 1! + beanpole.pull('-name=group2 say/hello', function(msg) + { + console.log(msg) + }); + + //hello 1! + beanpole.pull('-name=group2 say/hello', function(msg) + { + console.log(msg) + }); +} + +beanpole.on({ + 'push init': init, + + //NOTE: rotate=N is provided just so the properties aren't overridden + 'pull -name=group2 -rotate=3 say/hello': hello1, + 'pull -name=group1 -rotate=2 say/hello': hello2, + 'pull -name=group1 -rotate=1 say/hello': hello3 +}); + + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/filter.metadata/index.js b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata/index.js new file mode 100644 index 0000000..cba0c8e --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/filter.metadata/index.js @@ -0,0 +1,53 @@ +var beanpole = require('../../lib/node').router(); + + +function groupHello1(pull) +{ + return "hello!"; +} + +function groupHello2(pull) +{ + return "hello again!"; +} + +function groupHello3(pull) +{ + return "hello for a third time!"; +} + + +function init() +{ + //hello! + //hello again! + //hello for a third time! + beanpole.pull('-multi say/hello', function(msg) + { + console.log(msg) + }); + + //hello! + //hello again! + beanpole.pull('-multi -name=group1 say/hello', function(msg) + { + console.log(msg) + }); + + //hello for a third time! + beanpole.pull('-multi -name=group2 say/hello', function(msg) + { + console.log(msg) + }); +} + +beanpole.on({ + 'push init': init, + + //-multi=N is set so props aren't overridden + 'pull -name=group2 -multi=3 say/hello': groupHello3, + 'pull -name=group1 -multi=2 say/hello': groupHello2, + 'pull -name=group1 -multi=1 say/hello': groupHello1 +}); + +beanpole.push('init') \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/direct.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/direct.js new file mode 100644 index 0000000..5cbe6b4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/direct.js @@ -0,0 +1,33 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8080 + } + } +}); + + + +router.on({ + + 'push -public spice.io/theurld/ready': function() + { + console.log("READY"); + } +}); + +router.require(['http.server', 'http.gateway','hook.http','hook.core']); + + +router.push('init'); + +router.push('hook/add','http://theurld.spice.io'); + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook.js new file mode 100644 index 0000000..396267f --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook.js @@ -0,0 +1,43 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8081 + } + } +}); + + +router.on({ + + 'pull -http hello': function() + { + return "Hello world!"; + }, + + 'push -public head/ready': function() + { + console.log("READ READY"); + }, + + 'push -public hook/ready': function() + { + console.log("LOL HOOKKS"); + } +}); + +router.require(['http.server', 'http.gateway','hook.http.mesh2','hook.core']); + + +router.push('init'); +router.push('ready','hook'); + +router.pull('hooks/add', 'http://localhost:8080', function(){}); + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook2.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook2.js new file mode 100644 index 0000000..6e0dc26 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook2.js @@ -0,0 +1,38 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8082 + } + } +}); + + +router.on({ + + 'pull -http hello': function() + { + return "Hello world!"; + }, + + 'push -public head/ready': function() + { + console.log("READ READY"); + } +}); + +router.require(['http.server', 'http.gateway','hook.http.mesh2','hook.core']); + + +router.push('init'); +router.push('ready','hook'); + +router.pull('hooks/add', 'http://localhost:8080', function(){}); + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook3.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook3.js new file mode 100644 index 0000000..0d1a6f4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook3.js @@ -0,0 +1,43 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8083 + } + } +}); + + +router.on({ + + 'pull -http hello': function() + { + return "Hello world!"; + }, + + 'push -public head/ready': function() + { + console.log("READ READY"); + }, + + 'push -public hook/ready': function() + { + console.log("LOL HOOKKS"); + } +}); + +router.require(['hook.http.mesh','hook.core']); + + +router.push('init'); +router.push('ready','hook'); + +router.pull('hooks/add', 'http://localhost:8080', function(){}); + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook4.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook4.js new file mode 100644 index 0000000..c9c401b --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/hook4.js @@ -0,0 +1,48 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8083 + } + } +}); + +var id = Date.now(); + +console.log(id); + + +router.on({ + + 'pull -http hello': function() + { + return "Hello world!"; + }, + + 'push -public sibling/ready': function(id) + { + console.log("SIBLING READY: " + id); + }, + + 'push -public hook/ready': function() + { + if(this.from == router) return; + + this.from.push('sibling/ready', id); + } +}); + +router.require(['hook.http.mesh','hook.core']); + + +router.push('init'); +router.push('ready','hook'); + + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/http.gateway/index.js b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/index.js new file mode 100644 index 0000000..a642d9d --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/http.gateway/index.js @@ -0,0 +1,41 @@ +var beanpole = require('../../lib/node'); + + +var router = beanpole.router(); + + +router.params({ + 'http.gateway': { + http:{ + port: 8080 + } + } +}); + + +router.on({ + + 'pull -http hello': function() + { + return "Hello world!"; + }, + + 'push -public hook/ready': function() + { + console.log("READY"); + }, + + 'push -public duck': function() + { + console.log("DUCK!"); + } +}); + +router.require(['http.server', 'http.gateway','hook.http.mesh2','hook.core']); + + +router.push('init'); +router.push('ready','head'); + + + diff --git a/node_modules/celeri/node_modules/beanpole/examples/interception-old/index.js b/node_modules/celeri/node_modules/beanpole/examples/interception-old/index.js new file mode 100644 index 0000000..9b86aea --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/interception-old/index.js @@ -0,0 +1,31 @@ +var beanpole = require('../../lib/node').router(); + +function intercept(pull) +{ + //change the data + pull.data.sport = 'soccer'; + + pull.next(); +} + +function test(pull) +{ + pull.end(pull.data.sport) +} + +function init() +{ + beanpole.pull('test', { sport: 'football' }, function(result) + { + console.log(result) + }); +} + +beanpole.on({ + 'push init': init, + 'pull -intercept=sport te`st/interception': intercept, + 'pull test': test +}) + + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/multi.routes/index.js b/node_modules/celeri/node_modules/beanpole/examples/multi.routes/index.js new file mode 100644 index 0000000..b5d53ee --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/multi.routes/index.js @@ -0,0 +1,20 @@ +var beanpole = require('../../lib/node'), + argv = process.argv.concat(); + +var router = beanpole.router(), +router2 = beanpole.router(); + + + +var listen = { + 'push hello': function() + { + console.log('hello!') + } +} + + +router.on(listen).dispose(); +router2.on(listen); + +router.push('hello') \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/or.hello/index.js b/node_modules/celeri/node_modules/beanpole/examples/or.hello/index.js new file mode 100644 index 0000000..1d10fcc --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/or.hello/index.js @@ -0,0 +1,32 @@ +var beanpole = require('../../lib/node').router(); + +function delay() +{ + setTimeout(function (self){ self.next(); }, this.data.seconds * 1000, this); +} + + + +beanpole.on({ + 'push -filter=BOMB (say/hello or say/hello/world) or blah': function() + { + console.log("hello world!") + }, + 'push -filter=GOLD blah': function() + { + console.log("GO") + }, + + 'pull /*': function() + { + console.log("G") + } +}) + + + +beanpole.push('say/hello'); +beanpole.push('say/hello/world'); +beanpole.push('-filter=GOLD blah'); +beanpole.push('-filter=BOMB blah'); +beanpole.push('/'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/override.pull/index.js b/node_modules/celeri/node_modules/beanpole/examples/override.pull/index.js new file mode 100644 index 0000000..a8f1d4e --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/override.pull/index.js @@ -0,0 +1,21 @@ +var beanpole = require('../../lib/node').router(); + + + +beanpole.on({ + + /** + */ + + 'pull -overridable say/hello': function() + { + return "hello"; + }, + + + 'pull say/hello': function() + { + return "hello world!" + } +}); + diff --git a/node_modules/celeri/node_modules/beanpole/examples/pull.thru/index.js b/node_modules/celeri/node_modules/beanpole/examples/pull.thru/index.js new file mode 100644 index 0000000..1182fc1 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/pull.thru/index.js @@ -0,0 +1,61 @@ +var beanpole = require('../../lib/node').router(); + + + +function sayHi() +{ + console.log(this.data) + console.log('hi') + // this.next(); + if(!this.next()) return "don't pass " + this.data.name+ " "+this.data.last; +} + +function sayHi2() +{ + console.log('pass!'); + + if(!this.next()) + { + this.end("GO") + } +} + +function sayHiCraig() +{ + if(!this.next()) return "GO" +} + +function sayHi3() +{ + if(!this.next()) return "hello"; +} + + +function init() +{ + beanpole.pull('hello2/craig', function(result) + { + console.log(result) + }); + +} + +function test2() +{ + +} + +beanpole.on({ + 'push init': init, + 'pull /*': function() + { + console.log("PSSS") ; + this.next(); + }, + 'pull hellotest': sayHi2, + 'pull hellotest -> hellotest -> hello2/:name': sayHi3 +}); + +// console.log(beanpole.routeMiddleware._routers.pull._collection._routes) + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/push.pull/index.js b/node_modules/celeri/node_modules/beanpole/examples/push.pull/index.js new file mode 100644 index 0000000..b76590b --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/push.pull/index.js @@ -0,0 +1,46 @@ +var beanpole = require('../../lib/node').router(); + + + +beanpole.on({ + 'pull name': function() + { + setTimeout(function() + { + beanpole.push('name', function() + { + return "SLAYERS!"; + }); + + beanpole.push('name', 'PUSH'); + // beanpole.push('name', 'PUSH'); + // beanpole.push('name', 'PUSH'); + // beanpole.push('name', 'PUSH'); + // beanpole.push('name', 'PUSH'); + }, 100); + + return 'PULL'; + }, + 'push /*': function() + { + console.log("PUSH INITIALIZED!"); + this.next(); + }, + 'push through': function(data) + { + console.log("delay!") + setTimeout(function(self){ self.next(); }, 500, this) + }, + 'push -pull name': function(name) + { + console.log(name) + }, + 'push -pull name': function(name) + { + console.log(name) + }, + /*'push name': function(name) + { + console.log(name +' PUSH') + }*/ +}); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/push.thru/index.js b/node_modules/celeri/node_modules/beanpole/examples/push.thru/index.js new file mode 100644 index 0000000..8e04edc --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/push.thru/index.js @@ -0,0 +1,35 @@ +var beanpole = require('../../lib/node').router(); + + + +function sayHi2() +{ + console.log('pass!'); + + // return 'ga' + if(!this.next()) + { + console.log("FAIL") + } +} + +function sayHi3() +{ + console.log(this.data) +} + + +function init() +{ + beanpole.push('hello3', 'craig!'); +} + +beanpole.on({ + 'push init': init, + 'push hello2 -> hello2 -> hello2 -> hello2 -> hello2 -> hello2 -> hello': sayHi2, + 'push hello2': sayHi2, + 'push hello -> hello2 -> hello3': sayHi3 +}) + + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/rotate.hello/index.js b/node_modules/celeri/node_modules/beanpole/examples/rotate.hello/index.js new file mode 100644 index 0000000..cbe55a9 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/rotate.hello/index.js @@ -0,0 +1,43 @@ +var beanpole = require('../../lib/node').router(); + +function delay() +{ + setTimeout(function (self){ self.next(); }, this.data.seconds * 1000, this); +} + +function sayHi() +{ + return "I."; +} + +function sayHi2() +{ + return "Love."; +} + +function sayHi3() +{ + return "Coffee."; +} + +function init() +{ + for(var i = 3; i--;) + { + beanpole.pull('say/hi', function (res) + { + console.log(res) + }); + } +} + +beanpole.on({ + 'push init': init, + 'pull delay/:seconds': delay, + 'pull -rotate delay/1 -> say/hi': sayHi, + 'pull -rotate delay/2 -> say/hi': sayHi2, + 'pull -rotate delay/3 -> say/hi': sayHi3 +}) + + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/thru/index.js b/node_modules/celeri/node_modules/beanpole/examples/thru/index.js new file mode 100644 index 0000000..acc04d5 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/thru/index.js @@ -0,0 +1,87 @@ +var beanpole = require('../../lib/node'); + +var router = beanpole.router(); + + + +router.on({ + /** + */ + + 'pull /*': function() + { + console.log("THRU"); + + this.next(); + }, + + /** + */ + + 'pull -two /*': function() + { + console.log("THRU MOO"); + + this.next(); + }, + + /** + */ + + 'pull -two /hello/*': function() + { + console.log("THRU hoo"); + + this.next(); + }, + + /** + */ + + 'pull /hello/param/*': function() + { + console.log("THRU AGAIN"); + this.next(); + }, + + /** + */ + + 'pull -t /hello/param/*': function() + { + console.log("THRU AGAIN"); + this.next(); + }, + + /** + */ + + 'pull -t2 /hello/param/*': function() + { + console.log("THRU AGAIN"); + this.next(); + }, + + /** + */ + + 'pull -t3 /hello/param/*': function() + { + console.log("THRU AGAIN"); + this.next(); + }, + + + /** + */ + + 'pull hello/param': function() + { + console.log("HELLO!"); + } +}); + + +router.pull('hello/param', function() +{ +}); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.html b/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.html new file mode 100644 index 0000000..29bd56c --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.html @@ -0,0 +1,9 @@ + + + Socket Test + + + + + + \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.js b/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.js new file mode 100644 index 0000000..14d1056 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/ws/client/release/index.js @@ -0,0 +1,2139 @@ +var sardModule0 = {}; +var Structr = function(fhClass, parent) { + if (!parent) parent = Structr.fh({}); + var that = Structr.extend(parent, fhClass); + if (!that.__construct) { + that.__construct = function() {}; + } + that.__construct.prototype = that; + that.__construct.extend = function(child) { + return Structr(child, that); + }; + return that.__construct; +}; + +Structr.copy = function(from, to, lite) { + if (typeof to == "boolean") { + lite = to; + to = undefined; + } + if (!to) to = from instanceof Array ? [] : {}; + var i; + for (i in from) { + var fromValue = from[i], toValue = to[i], newValue; + if (!lite && typeof fromValue == "object" && (!fromValue || fromValue.__proto__ == Object.prototype || fromValue.__proto__ == Array.prototype)) { + if (toValue && fromValue instanceof toValue.constructor) { + newValue = toValue; + } else { + newValue = fromValue instanceof Array ? [] : {}; + } + Structr.copy(fromValue, newValue); + } else { + newValue = fromValue; + } + to[i] = newValue; + } + return to; +}; + +Structr.getMethod = function(that, property) { + return function() { + return that[property].apply(that, arguments); + }; +}; + +Structr.wrap = function(that) { + if (that._wrapped) return that; + that._wrapped = true; + function wrap(target) { + return function() { + return target.apply(that, arguments); + }; + } + for (var property in that) { + var target = that[property]; + if (typeof target == "function") { + that[property] = wrap(target); + } + } + return that; +}; + +Structr.findProperties = function(target, modifier) { + var props = [], property; + for (property in target) { + var v = target[property]; + if (v && v[modifier]) { + props.push(property); + } + } + return props; +}; + +Structr.nArgs = function(func) { + var inf = func.toString().replace(/\{[\W\S]+\}/g, "").match(/\w+(?=[,\)])/g); + return inf ? inf.length : 0; +}; + +Structr.getFuncsByNArgs = function(that, property) { + return that.__private["overload::" + property] || (that.__private["overload::" + property] = {}); +}; + +Structr.getOverloadedMethod = function(that, property, nArgs) { + var funcsByNArgs = Structr.getFuncsByNArgs(that, property); + return funcsByNArgs[nArgs]; +}; + +Structr.setOverloadedMethod = function(that, property, func, nArgs) { + var funcsByNArgs = Structr.getFuncsByNArgs(that, property); + if (func.overloaded) return funcsByNArgs; + funcsByNArgs[nArgs || Structr.nArgs(func)] = func; + return funcsByNArgs; +}; + +Structr.modifiers = { + m_override: function(that, property, newMethod) { + var oldMethod = that.__private && that.__private[property] || that[property] || function() {}, parentMethod = oldMethod; + if (oldMethod.overloaded) { + var overloadedMethod = oldMethod, nArgs = Structr.nArgs(newMethod); + parentMethod = Structr.getOverloadedMethod(that, property, nArgs); + } + var wrappedMethod = function() { + this._super = parentMethod; + var ret = newMethod.apply(this, arguments); + delete this._super; + return ret; + }; + if (oldMethod.overloaded) { + return Structr.modifiers.m_overload(that, property, wrappedMethod, nArgs); + } + return wrappedMethod; + }, + m_explicit: function(that, property, gs) { + var pprop = "__" + property; + if (typeof gs != "object") { + gs = {}; + } + if (!gs.get) gs.get = function() { + return this._value; + }; + if (!gs.set) gs.set = function(value) { + this._value = value; + }; + return function(value) { + if (!arguments.length) { + this._value = this[pprop]; + var ret = gs.get.apply(this); + delete this._value; + return ret; + } else { + if (this[pprop] == value) return; + this._value = this[pprop]; + gs.set.apply(this, [ value ]); + this[pprop] = this._value; + } + }; + }, + m_implicit: function(that, property, egs) { + that.__private[property] = egs; + that.__defineGetter__(property, egs); + that.__defineSetter__(property, egs); + }, + m_overload: function(that, property, value, nArgs) { + var funcsByNArgs = Structr.setOverloadedMethod(that, property, value, nArgs); + var multiFunc = function() { + var func = funcsByNArgs[arguments.length]; + if (func) { + return funcsByNArgs[arguments.length].apply(this, arguments); + } else { + var expected = []; + for (var sizes in funcsByNArgs) { + expected.push(sizes); + } + throw new Error("Expected " + expected.join(",") + " parameters, got " + arguments.length + "."); + } + }; + multiFunc.overloaded = true; + return multiFunc; + } +}; + +Structr.extend = function(from, to) { + if (!to) to = {}; + var that = { + __private: { + propertyModifiers: {} + } + }; + if (to instanceof Function) to = to(); + Structr.copy(from, that); + var usedProperties = {}, property; + for (property in to) { + var value = to[property]; + var propModifiersAr = property.split(" "), propertyName = propModifiersAr.pop(), modifierList = that.__private.propertyModifiers[propertyName] || (that.__private.propertyModifiers[propertyName] = []); + if (propModifiersAr.length) { + var propModifiers = {}; + for (var i = propModifiersAr.length; i--; ) { + var modifier = propModifiersAr[i]; + propModifiers["m_" + propModifiersAr[i]] = 1; + if (modifierList.indexOf(modifier) == -1) { + modifierList.push(modifier); + } + } + if (propModifiers.m_explicit || propModifiers.m_implicit) { + value = Structr.modifiers.m_explicit(that, propertyName, value); + } + if (propModifiers.m_override) { + value = Structr.modifiers.m_override(that, propertyName, value); + } + if (propModifiers.m_implicit) { + Structr.modifiers.m_implicit(that, propertyName, value); + continue; + } + } + for (var j = modifierList.length; j--; ) { + value[modifierList[j]] = true; + } + if (usedProperties[propertyName]) { + var oldValue = that[propertyName]; + if (!oldValue.overloaded) Structr.modifiers.m_overload(that, propertyName, oldValue, undefined); + value = Structr.modifiers.m_overload(that, propertyName, value, undefined); + } + usedProperties[propertyName] = 1; + that.__private[propertyName] = that[propertyName] = value; + } + if (that.__construct && from.__construct && that.__construct == from.__construct) { + that.__construct = Structr.modifiers.m_override(that, "__construct", function() { + this._super.apply(this, arguments); + }); + } + var propertyName; + for (propertyName in that) { + var value = that[propertyName]; + if (value && value["static"]) { + that.__construct[propertyName] = value; + delete that[propertyName]; + } + } + return that; +}; + +Structr.fh = function(that) { + that = Structr.extend({}, that); + that.getMethod = function(property) { + return Structr.getMethod(this, property); + }; + that.extend = function(target) { + return Structr.extend(this, target); + }; + that.copyTo = function(target, lite) { + Structr.copy(this, target, lite); + }; + that.wrap = function() { + return Structr.wrap(this); + }; + return that; +}; + +sardModule0 = Structr; +var sardModule6 = {}; +var sardVar5 = sardModule0; + +var Token = { + WORD: 1, + METADATA: 1 << 1, + NUMBER: 1 << 2, + PARAM: 1 << 3, + TO: 1 << 4, + BACKSLASH: 1 << 5, + DOT: 1 << 6, + STAR: 1 << 7, + OR: 1 << 8, + LP: 1 << 9, + RP: 1 << 10, + EQ: 1 << 11, + WHITESPACE: 1 << 12 +}; + +var Reversed = { + or: Token.OR +}; + +var Tokenizer = function() { + var source = "", pos = 0, currentToken, self = this; + this.source = function(value) { + if (value) { + source = value + " "; + pos = 0; + } + return source; + }; + this.next = function(keepWhite) { + return currentToken = nextToken(keepWhite); + }; + this.peekChars = function(n) { + return source.substr(pos, n); + }; + this.current = function(keepWhite) { + return currentToken || self.next(keepWhite); + }; + this.position = function() { + return pos; + }; + var nextToken = function(keepWhite) { + if (!keepWhite) skipWhite(); + if (eof()) return null; + var c = currentChar(), ccode = c.charCodeAt(0); + if (isWhite(ccode)) { + skipWhite(); + return token(" ", Token.WHITESPACE); + } + if (isAlpha(ccode)) { + var w = nextWord(); + return token(w, Reversed[w.toLowerCase()] || Token.WORD); + } + if (isNumber(ccode)) { + return token(nextNumber(), Token.NUMBER); + } + switch (c) { + case "-": + if (nextChar() == ">") return token("->", Token.TO, true); + if (isAlpha(currentCharCode())) return token(nextWord(), Token.METADATA); + error(); + case ":": + if (isAlpha(nextCharCode())) return token(nextWord(), Token.PARAM); + error(); + case "/": + return token("/", Token.BACKSLASH, true); + case ".": + return token(".", Token.DOT, true); + case "*": + return token("*", Token.STAR, true); + case "(": + return token("(", Token.LP, true); + case ")": + return token(")", Token.RP, true); + case "=": + return token("=", Token.EQ, true); + default: + error(); + } + return null; + }; + var error = function() { + throw new Error('Unexpected character "' + currentChar() + '" at position ' + pos + ' in "' + source + '"'); + }; + var token = function(value, type, skipOne) { + if (skipOne) nextChar(); + return { + value: value, + type: type + }; + }; + var nextChar = this.nextChar = function() { + return source[++pos]; + }; + var currentChar = this.currentChar = function() { + return source[pos]; + }; + var isAlpha = this.isAlpha = function(c) { + return c > 96 && c < 123 || c > 64 && c < 91 || isNumber(c); + }; + var isWhite = this.isWhite = function(c) { + return c == 32 || c == 9 || c == 10; + }; + var isNumber = this.isNumber = function(c) { + return c > 47 && c < 58; + }; + var nextCharCode = function() { + return nextChar().charCodeAt(0); + }; + var currentCharCode = function() { + return currentChar().charCodeAt(0); + }; + var rewind = function(steps) { + pos -= steps || 1; + }; + var skipWhite = function() { + var end = false; + while (!(end = eof())) { + if (!isWhite(currentCharCode())) break; + nextChar(); + } + return !end; + }; + var nextNumber = function() { + var buffer = currentChar(); + while (!eof()) { + if (isNumber(nextCharCode())) { + buffer += currentChar(); + } else { + break; + } + } + return buffer; + }; + var nextWord = function() { + var buffer = currentChar(); + while (!eof()) { + if (!isWhite(nextCharCode()) && !currentChar().match(/[\/=()]/g)) { + buffer += currentChar(); + } else { + break; + } + } + return buffer; + }; + var eof = function() { + return pos > source.length - 2; + }; +}; + +var ChannelParser = function() { + var tokenizer = new Tokenizer, cache = {}; + this.parse = function(source) { + if (!source) throw new Error("Source is not defined"); + if (cache[source]) return sardVar5.copy(cache[source]); + tokenizer.source(source); + return sardVar5.copy(cache[source] = rootExpr()); + }; + var rootExpr = function() { + var expr = tokenizer.current(), type, meta = {}; + if (expr.type == Token.WORD && tokenizer.isWhite(tokenizer.peekChars(1).charCodeAt(0)) && tokenizer.position() < tokenizer.source().length - 1) { + type = expr.value; + tokenizer.next(); + } + var token, channels = []; + while (token = tokenizer.current()) { + switch (token.type) { + case Token.METADATA: + meta[token.value] = metadataValue(); + break; + case Token.BACKSLASH: + case Token.WORD: + case Token.STAR: + channels = channels.concat(channelsExpr()); + break; + case Token.OR: + tokenizer.next(); + break; + default: + tokenizer.next(); + break; + } + } + return { + type: type, + meta: meta, + channels: channels + }; + }; + var metadataValue = function() { + if (tokenizer.currentChar() == "=") { + tokenizer.next(); + var v = tokenizer.next().value; + tokenizer.next(); + return v; + } + tokenizer.next(); + return 1; + }; + var channelsExpr = function() { + var channels = [], to; + while (hasNext()) { + if (currentTypeIs(Token.LP)) { + tokenizer.next(); + } + if (currentTypeIs(Token.WORD | Token.PARAM | Token.STAR | Token.BACKSLASH)) { + channels.push([ channelPathsExpr() ]); + while (currentTypeIs(Token.OR)) { + tokenizer.next(); + channels[channels.length - 1].push(channelPathsExpr()); + } + } else { + break; + } + if (currentTypeIs(Token.RP)) { + tokenizer.next(); + } + if (currentTypeIs(Token.TO)) { + tokenizer.next(); + } + } + var _orChannels = splitChannelExpr(channels.concat(), []), channelsThru = []; + for (var i = _orChannels.length; i--; ) { + var chain = sardVar5.copy(_orChannels[i]), current = channel = chain[chain.length - 1]; + for (var j = chain.length - 1; j--; ) { + current = current.thru = chain[j]; + } + channelsThru.push(channel); + } + return channelsThru; + }; + var splitChannelExpr = function(orChannels, stack) { + if (!orChannels.length) return [ stack ]; + var current = orChannels.shift(); + if (current.length == 1) { + stack.push(current[0]); + return splitChannelExpr(orChannels, stack); + } else { + var split = []; + for (var i = current.length; i--; ) { + var stack2 = stack.concat(); + stack2.push(current[i]); + split = split.concat(splitChannelExpr(orChannels.concat(), stack2)); + } + return split; + } + }; + var channelPathsExpr = function(type) { + var paths = [], token, isMiddleware = false, cont = true; + while (cont && (token = tokenizer.current())) { + switch (token.type) { + case Token.WORD: + case Token.PARAM: + case Token.NUMBER: + paths.push({ + name: token.value, + param: token.type == Token.PARAM + }); + break; + case Token.BACKSLASH: + break; + default: + cont = false; + break; + } + if (cont) tokenizer.next(); + } + if (currentTypeIs(Token.STAR)) { + isMiddleware = true; + tokenizer.next(); + } + return { + paths: paths, + isMiddleware: isMiddleware + }; + }; + var currentToken = function(type, igError) { + return checkToken(tokenizer.current(), type, igError); + }; + var nextToken = function(type, igError, keepWhite) { + return checkToken(tokenizer.next(keepWhite), type, igError); + }; + var checkToken = function(token, type, igError) { + if (!token || !(type & token.type)) { + if (!igError) throw new Error('Unexpected token "' + (token || {}).value + '" at position ' + tokenizer.position() + " in " + tokenizer.source()); + return null; + } + return token; + }; + var currentTypeIs = function(type) { + var current = tokenizer.current(); + return current && !!(type & current.type); + }; + var hasNext = function() { + return !!tokenizer.current(); + }; +}; + +sardModule6.parse = (new ChannelParser).parse; +var sardModule8 = {}; +sardModule8.replaceParams = function(expr, params) { + var path; + for (var i = expr.channel.paths.length; i--; ) { + path = expr.channel.paths[i]; + if (path.param) { + path.param = false; + path.name = params[path.name]; + if (!path.name) expr.channel.paths.splice(i, 1); + } + } + return expr; +}; + +sardModule8.channel = function(expr, index) { + return { + type: expr.type, + channel: expr.channels[index], + meta: expr.meta || {} + }; +}; + +sardModule8.pathToString = function(path) { + var paths = []; + for (var i = 0, n = path.length; i < n; i++) { + var pt = path[i]; + paths.push(pt.param ? ":" + pt.name : pt.name); + } + return paths.join("/"); +}; + +sardModule8.passThrusToArray = function(channel) { + var cpt = channel.thru, thru = []; + while (cpt) { + thru.push(this._pathToString(cpt.paths)); + cpt = cpt.thru; + } + return thru; +}; +var sardModule11 = {}; +sardModule11.rotator = function(target, meta) { + if (!target) target = {}; + target.meta = [ meta ]; + target.allowMultiple = true; + target.getRoute = function(ops) { + var route = ops.route, listeners = ops.listeners; + if (!ops.router._allowMultiple && route && route.meta && route.meta[meta] != undefined && listeners.length) { + route.meta[meta] = ++route.meta[meta] % listeners.length; + ops.listeners = [ listeners[route.meta[meta]] ]; + } + }; + target.setRoute = function(ops) {}; +}; + +sardModule11.rotator(sardModule11, "rotate"); +var sardModule13 = {}; +var sardVar10 = sardModule0; + +sardModule13 = function() { + var mw = new sardModule13.Middleware; + mw.add(sardModule11); + return mw; +}; + +sardModule13.Middleware = sardVar10({ + __construct: function() { + this._toMetadata = {}; + this._universal = {}; + }, + add: function(module) { + var self = this; + if (module.all) { + module.all.forEach(function(type) { + if (!self._universal[type]) self._universal[type] = []; + self._universal[type].push(module); + }); + } + module.meta.forEach(function(name) { + self._toMetadata[name] = module; + }); + }, + getRoute: function(ops) { + var mw = this._getMW(ops.route ? ops.route.meta : {}, "getRoute").concat(this._getMW(ops.expr.meta)); + return this._eachMW(ops, mw, function(cur, ops) { + return cur.getRoute(ops); + }); + }, + setRoute: function(ops) { + var mw = this._getMW(ops.meta, "setRoute"); + return this._eachMW(ops, mw, function(cur, ops) { + return cur.setRoute(ops); + }); + }, + allowMultiple: function(expr) { + var mw = this._getMW(expr.meta); + for (var i = mw.length; i--; ) { + if (mw[i].allowMultiple) return true; + } + return false; + }, + _getMW: function(meta, uni) { + var mw = (this._universal[uni] || []).concat(); + for (var name in meta) { + if (!meta[name]) continue; + var handler = this._toMetadata[name]; + if (handler && mw.indexOf(handler) == -1) mw.push(handler); + } + return mw; + }, + _eachMW: function(ops, mw, each) { + var cops = ops, newOps; + for (var i = mw.length; i--; ) { + if (newOps = each(mw[i], cops)) { + cops = newOps; + } + } + return cops; + } +}); +var sardModule17 = {}; +var sardVar15 = sardModule0, sardVar16 = sardModule6; + +var Request = sardVar15({ + __construct: function(listener, batch) { + this.data = batch.data; + this.inner = batch.inner; + this.callback = batch.callback; + this._used = {}; + this._queue = []; + this._add(listener, this.data, batch.paths); + if (batch._next) { + this.add(batch._next); + } + }, + init: function() { + return this; + }, + hasNext: function() { + return !!this._queue.length; + }, + next: function() { + if (this._queue.length) { + var thru = this._queue.pop(), target = thru.target; + this.current = target; + if (target.paths) { + var route = this.origin.getRoute({ + channel: target + }); + this._addListeners(route.listeners, route.data, target.paths); + return this.next(); + } + if (this._used[target.id]) return this.next(); + this._used[target.id] = thru; + this._prepare(target, thru.data, thru.paths); + return true; + } + return false; + }, + _addListeners: function(listeners, data, paths) { + if (listeners instanceof Array) { + for (var i = listeners.length; i--; ) { + this._add(listeners[i], data, paths); + } + return; + } + }, + add: function(callback) { + this._queue.unshift(this._func(callback)); + }, + unshift: function(callback) { + this._queue.push(this._func(callback)); + }, + _func: function(callback) { + return { + target: { + callback: callback + }, + data: {} + }; + }, + _add: function(route, data, paths) { + var current = route, _queue = this._queue; + if (!data) data = {}; + while (current) { + for (var i = paths.length; i--; ) { + var opath = paths[i], cpath = route.path[i], param, value; + if (cpath.param && !opath.param) { + param = cpath.name; + value = opath.name; + } else if (cpath.param && opath.param) { + param = cpath.name; + value = this.data[opath.name]; + } + this.data[param] = data[param] = value; + } + _queue.push({ + target: current, + data: data || {}, + paths: paths + }); + current = current.thru; + } + }, + _prepare: function(target, data, paths) { + if (target.meta.one) { + target.dispose(); + } + this._callback(target, data); + }, + _callback: function(target, data) { + return target.callback.call(this, this); + } +}); + +sardModule17 = Request; +var sardModule23 = {}; +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(obj) { + for (var i = 0; i < this.length; i++) { + if (this[i] == obj) { + return i; + } + } + return -1; + }; +} + +if (this.window && !window.console) { + var console = { + log: function() {} + }; +} + +var sk = {}; +var sardModule26 = {}; +sardModule23; + +sardModule26 = sardModule0; +var sardModule28 = {}; +var sardVar27 = sardModule26; + +sardModule28.Janitor = sardVar27({ + __construct: function() { + this.dispose(); + }, + addDisposable: function() { + var args = arguments[0] instanceof Array ? arguments[0] : arguments; + for (var i = args.length; i--; ) { + var target = args[i]; + if (target && target["dispose"]) { + if (this.disposables.indexOf(target) == -1) this.disposables.push(target); + } + } + }, + dispose: function() { + if (this.disposables) for (var i = this.disposables.length; i--; ) { + this.disposables[i].dispose(); + } + this.disposables = []; + } +}); +var sardModule30 = {}; +var sardVar19 = sardModule0, sardVar20 = sardModule6, sardVar21 = sardModule8, sardVar22 = sardModule17, Janitor = sardModule28.Janitor; + +var Collection = sardVar19({ + __construct: function(ops) { + this._ops = ops || {}; + this._routes = this._newRoute(); + this._middleware = this._newRoute(); + this._routeIndex = 0; + }, + has: function(expr) { + var routes = this.routes(expr); + for (var i = routes.length; i--; ) { + if (routes[i].target) return true; + } + return false; + }, + route: function(channel) { + return this._route(channel.paths); + }, + routes: function(expr) { + var channels = expr.channels, routes = []; + for (var i = channels.length; i--; ) { + routes.push(this.route(channels[i])); + } + return routes; + }, + add: function(expr, callback) { + var janitor = new Janitor; + for (var i = expr.channels.length; i--; ) { + janitor.addDisposable(this._add(expr.channels[i], expr.meta, callback)); + } + return janitor; + }, + _add: function(channel, meta, callback) { + var paths = channel.paths, isMiddleware = channel.isMiddleware, middleware = channel.thru, currentRoute = this._start(paths, isMiddleware ? this._middleware : this._routes); + var before = this._before(paths, currentRoute); + if (middleware) this._endMiddleware(middleware).thru = before; + var listener = { + callback: callback, + meta: meta, + id: "r" + this._routeIndex++, + thru: middleware || before, + path: paths, + dispose: function() { + var i = currentRoute.listeners.indexOf(listener); + if (i > -1) currentRoute.listeners.splice(i, 1); + } + }; + currentRoute.meta = sardVar19.copy(meta, currentRoute.meta); + if (isMiddleware) this._injectMiddleware(listener, paths); + if (!currentRoute.listeners) currentRoute.listeners = []; + currentRoute.listeners.push(listener); + return listener; + }, + _endMiddleware: function(target) { + var current = target || {}; + while (current.thru) { + current = current.thru; + } + return current; + }, + _injectMiddleware: function(listener, paths) { + listener.level = paths.length; + var afterListeners = this._after(paths, this._routes).concat(this._after(paths, this._middleware)); + for (var i = afterListeners.length; i--; ) { + var currentListener = afterListeners[i]; + var currentMiddleware = currentListener.thru, previousMiddleware = currentListener; + while (currentMiddleware) { + if (currentMiddleware.level != undefined) { + if (currentMiddleware.level < listener.level) { + previousMiddleware.thru = listener; + } + break; + } + previousMiddleware = currentMiddleware; + currentMiddleware = currentMiddleware.thru; + } + if (!currentMiddleware) previousMiddleware.thru = listener; + } + }, + _before: function(paths, after) { + var current = this._middleware._route, listeners = []; + for (var i = 0, n = paths.length; i < n; i++) { + if (current.listeners) listeners = current.listeners; + var path = paths[i], newCurrent = path.param ? current._param : current[path.name]; + if (!newCurrent || !newCurrent._route || !newCurrent._route.listeners) break; + current = newCurrent._route; + if (current != after) listeners = current.listeners; + } + return listeners[0]; + }, + _after: function(paths, routes) { + return this._flatten(this._start(paths, routes)); + }, + _route: function(paths, routes, create) { + var current = (routes || this._routes)._route; + for (var i = 0, n = paths.length; i < n; i++) { + var path = paths[i], name = path.param ? "_param" : path.name; + if (!current[name] && create) { + current[name] = this._newRoute(i); + } + if (current[name]) { + current = current[name]; + } else { + current = current._param; + } + if (!current) return {}; + current = current._route; + } + return current; + }, + _start: function(paths, routes) { + return this._route(paths, routes, true); + }, + _newRoute: function(level) { + return { + _route: {}, + _level: level || 0 + }; + }, + _flatten: function(route) { + var listeners = route.listeners ? route.listeners.concat() : []; + for (var path in route) { + listeners = listeners.concat(this._flatten(route[path]._route || {})); + } + return listeners; + } +}); + +sardModule30 = Collection; +var sardModule32 = {}; +var sardVar4 = sardModule0, sardVar7 = sardModule6, sardVar9 = sardModule8, sardVar14 = sardModule13, sardVar18 = sardModule17, sardVar31 = sardModule30; + +var Router = sardVar4({ + __construct: function(ops) { + if (!ops) ops = {}; + this.RequestClass = ops.RequestClass || sardVar18; + this._collection = new sardVar31(ops); + this._allowMultiple = !!ops.multi; + }, + on: function(expr, ops, callback) { + if (!callback) { + callback = ops; + ops = null; + } + for (var i = expr.channels.length; i--; ) { + var single = sardVar9.channel(expr, i), existingRoute = this.getRoute(single); + if (existingRoute.listeners.length && !this._allowMultiple && !this._middleware().allowMultiple(single)) { + if (existingRoute.listeners[0].meta.overridable) { + existingRoute.listeners[0].dispose(); + } else { + throw new Error('Path "' + sardVar9.pathToString(single.channel.paths) + '" already exists'); + } + } + this._middleware().setRoute(channel); + } + return this._collection.add(expr, callback); + }, + _middleware: function() { + return this.controller.metaMiddleware; + }, + hasRoute: function(channel, data) { + return !!this.getRoute(channel, data).listeners.length; + }, + hasRoutes: function(expr, data) { + for (var i = expr.channels.length; i--; ) { + if (this.hasRoute(sardVar9.channel(expr, i), data)) return true; + } + return false; + }, + getRoute: function(single, data) { + var route = this._collection.route(single.channel); + return this._middleware().getRoute({ + expr: single, + router: this, + route: route, + data: data, + listeners: this._filterRoute(single, route) + }); + }, + dispatch: function(expr, data, ops, callback) { + for (var i = expr.channels.length; i--; ) { + if (this._dispatch(sardVar9.channel(expr, i), data, ops, callback)) return true; + } + return false; + }, + _dispatch: function(expr, data, ops, callback) { + if (data instanceof Function) { + callback = data; + data = undefined; + ops = undefined; + } + if (ops instanceof Function) { + callback = ops; + ops = undefined; + } + if (!ops) ops = {}; + if (!data) data = {}; + var inf = this.getRoute(expr, data); + if (!inf.listeners.length) { + if (!ops.ignoreWarning && !expr.meta.passive) console.warn('The %s route "%s" does not exist', expr.type, sardVar9.pathToString(expr.channel.paths)); + if (expr.meta.passive && callback) { + callback(null, "Route Exists"); + } + return false; + } + var newOps = { + router: this.controller, + origin: this, + data: inf.data, + inner: ops.inner || {}, + paths: inf.expr.channel.paths, + meta: expr.meta, + from: ops.from || this.controller, + listeners: inf.listeners, + callback: callback + }; + sardVar4.copy(newOps, ops, true); + this._callListeners(ops); + return true; + }, + _callListeners: function(newOps) { + for (var i = newOps.listeners.length; i--; ) { + sardVar4.copy(newOps, new this.RequestClass(newOps.listeners[i], newOps), true).init().next(); + } + }, + _filterRoute: function(expr, route) { + if (!route) return []; + var listeners = (route.listeners || []).concat(); + for (var name in expr.meta) { + var value = expr.meta[name]; + if (value === 1) continue; + for (var i = listeners.length; i--; ) { + var listener = listeners[i]; + if (listener.meta[name] != value) { + listeners.splice(i, 1); + } + } + } + if (!this._allowMultiple && listeners.length) { + return [ listeners[0] ]; + } + return listeners; + } +}); + +sardModule32 = Router; +var sardModule36 = {}; +var sardVar35 = sardModule26; + +sardModule36.EventEmitter = { + __construct: function() { + this._listeners = {}; + }, + addListener: function(type, callback) { + (this._listeners[type] || (this._listeners[type] = [])).push(callback); + var self = this; + return { + dispose: function() { + self.removeListener(type, callback); + } + }; + }, + hasEventListener: function(type, callback) { + return !!this._listeners[type]; + }, + getNumListeners: function(type, callback) { + return this.getEventListeners(type).length; + }, + removeListener: function(type, callback) { + var lists = this._listeners[type], i, self = this; + if (!lists) return; + if ((i = lists.indexOf(callback)) > -1) { + lists.splice(i, 1); + if (!lists.length) { + delete self._listeners[type]; + } + } + }, + getEventListeners: function(type) { + return this._listeners[type] || []; + }, + removeListeners: function(type) { + delete this._listeners[type]; + }, + removeAllListeners: function() { + this._listeners = {}; + }, + dispose: function() { + this._listeners = {}; + }, + emit: function() { + var args = [], type = arguments[0], lists; + for (var i = 1, n = arguments.length; i < n; i++) { + args[i - 1] = arguments[i]; + } + if (lists = this._listeners[type]) for (var i = lists.length; i--; ) { + lists[i].apply(this, args); + } + } +}; + +sardModule36.EventEmitter = sardVar35(sardModule36.EventEmitter); +var sardModule38 = {}; +var sardVar34 = sardModule0, EventEmitter = sardModule36.EventEmitter; + +var proto = { + _init: function(ttl) { + this._em = new EventEmitter; + this.response = {}; + if (ttl) { + this.cache(ttl); + } + }, + cache: function(ttl) { + if (this._caching) return; + this._caching = true; + var buffer = this._buffer = [], self = this; + this.on({ + write: function(chunk) { + buffer.push(chunk); + } + }); + }, + on: function(listeners) { + for (var type in listeners) { + this._em.addListener(type, listeners[type]); + } + }, + "second on": function(type, callback) { + this._em.addListener(type, callback); + }, + respond: function(data) { + sardVar34.copy(data, this.response, true); + return this; + }, + error: function(data) { + if (!data) return this._error; + this._error = data; + this._em.emit("error", data); + return this; + }, + _sendResponse: function() { + if (!this._sentResponse) { + this.response = JSON.parse(JSON.stringify(this.response)); + this._em.emit("response", this.response); + } + }, + write: function(data) { + this._sendResponse(); + this._em.emit("write", data); + return this; + }, + end: function(data) { + if (data) this.write(data); + this._sendResponse(); + this.finished = true; + this._em.emit("end", data); + this._em.dispose(); + return this; + }, + pipe: function(stream) { + if (stream.response) stream.response = this.response; + if (this._buffer && this._buffer.length) { + for (var i = 0, n = this._buffer.length; i < n; i++) { + stream.write(this._buffer[i]); + } + } + if (this.finished) { + return stream.end(); + } + this.on({ + write: function(data) { + stream.write(data); + }, + end: function() { + stream.end(); + }, + error: function(e) { + if (stream.error) stream.error(e); + }, + response: function(data) { + if (stream.respond) stream.respond(data); + } + }); + } +}; + +var Stream = sardVar34(sardVar34.copy(proto, { + __construct: function(ttl) { + this._init(ttl); + } +})); + +Stream.proto = proto; + +sardModule38 = Stream; +var sardModule40 = {}; +var sardVar33 = sardModule32, sardVar39 = sardModule38; + +var PushRouter = sardVar33.extend({ + "override on": function(expr, ops, callback) { + if (!callback) { + callback = ops; + ops = {}; + } + var ret = this._super(expr, ops, callback); + if (expr.meta.pull) { + this.controller.pull(expr, ops.data, { + ignoreWarning: true + }, callback); + } + return ret; + }, + "override _callListeners": function(ops) { + var stream = new sardVar39(true), callback = ops.callback || function(stream) { + return ops.data; + }; + var ret = callback(stream); + if (ret != undefined) { + stream.end(ret); + } + ops.stream = stream; + this._super.apply(this, arguments); + } +}); + +sardModule40 = PushRouter; +var sardModule46 = {}; +var sardVar43 = sardModule17, sardVar44 = sardModule38, sardVar45 = sardModule0; + +var PushPullRequest = sardVar43.extend(sardVar45.copy(sardVar44.proto, { + init: function() { + this._init(); + return this; + }, + _listen: function(listener, meta) { + if (!meta.stream) { + var buffer = [], self = this; + function end(err) { + if (err) return; + if (meta.batch) { + listener.call(self, buffer, err, self); + } else { + if (!buffer.length) { + listener(); + } else for (var i = 0, n = buffer.length; i < n; i++) { + listener.call(self, buffer[i], err, self); + } + } + } + this.pipe({ + write: function(data) { + buffer.push(data); + }, + error: end, + end: end + }); + } else { + listener.call(this, this); + } + } +})); + +sardModule46 = PushPullRequest; +var sardModule48 = {}; +var sardVar42 = sardModule38, sardVar47 = sardModule46; + +var PushRequest = sardVar47.extend({ + "override init": function() { + this._super(); + this.cache(); + this.stream.pipe(this); + return this; + }, + "override _callback": function(route, data) { + this._listen(route.callback, route.meta); + } +}); + +sardModule48 = PushRequest; +var sardModule50 = {}; +var sardVar41 = sardModule40, sardVar49 = sardModule48; + +sardModule50.types = [ "push" ]; + +sardModule50.test = function(expr) { + return expr.type == "push" ? "push" : null; +}; + +sardModule50.newRouter = function() { + return new sardVar41({ + multi: true, + RequestClass: sardVar49 + }); +}; +var sardModule55 = {}; +var sardVar53 = sardModule46, sardVar54 = sardModule0; + +var PullRequest = sardVar53.extend({ + "override init": function() { + this._super(); + this._listen(this.callback, this.meta); + return this; + }, + "override _callback": function() { + var ret = this._super.apply(this, arguments); + if (ret != undefined) { + this.end(ret); + } + } +}); + +sardModule55 = PullRequest; +var sardModule57 = {}; +var sardVar52 = sardModule32, sardVar56 = sardModule55; + +sardModule57.types = [ "pull", "pullMulti" ]; + +sardModule57.test = function(expr) { + if (expr.type == "pullMulti") return "pullMulti"; + return expr.type == "pull" ? expr.meta.multi ? "pullMulti" : "pull" : null; +}; + +sardModule57.newRouter = function(type) { + var ops = { + RequestClass: sardVar56 + }; + if (type == "pullMulti") ops.multi = true; + return new sardVar52(ops); +}; +var sardModule60 = {}; +var sardVar59 = sardModule32; + +sardModule60.types = [ "dispatch" ]; + +sardModule60.test = function(expr) { + return !expr.type || expr.type == "dispatch" ? "dispatch" : null; +}; + +sardModule60.newRouter = function() { + return new sardVar59({ + multi: true + }); +}; +var sardModule62 = {}; +var sardVar3 = sardModule0; + +sardModule62 = function(controller) { + var mw = new sardModule62.Middleware(controller); + mw.add(sardModule50); + mw.add(sardModule57); + mw.add(sardModule60); + return mw; +}; + +sardModule62.Middleware = sardVar3({ + __construct: function(controller) { + this._middleware = []; + this._controller = controller; + this._routers = {}; + this.types = []; + }, + add: function(module) { + this._middleware.push(module); + this.types = module.types.concat(this.types); + for (var i = module.types.length; i--; ) { + this._controller._createTypeMethod(module.types[i]); + } + }, + router: function(expr) { + for (var i = this._middleware.length; i--; ) { + var mw = this._middleware[i], name = mw.test(expr); + if (name) return this._router(mw, name); + } + return null; + }, + _router: function(tester, name) { + return this._routers[name] || this._newRouter(tester, name); + }, + _newRouter: function(tester, name) { + var router = tester.newRouter(name); + router.type = name; + router.controller = this._controller; + this._routers[name] = router; + return router; + } +}); +var sardModule68 = {}; +var sardVar2 = sardModule0, sardVar63 = sardModule62, sardVar64 = sardModule13, sardVar65 = sardModule6, Janitor = sardModule28.Janitor, sardVar67 = sardModule8; + +var AbstractController = sardVar2({ + __construct: function(target) { + this.metaMiddleware = sardVar64(this); + this.routeMiddleware = sardVar63(this); + this._channels = {}; + }, + has: function(type, ops) { + var expr = this._parse(type, ops); + return this._router(expr).hasRoutes(expr); + }, + getRoute: function(type, ops) { + var expr = this._parse(type, ops); + return this._router(expr).getRoute(sardVar67.channel(expr, 0)); + }, + on: function(target) { + var ja = new Janitor; + for (var type in target) { + ja.addDisposable(this.on(type, {}, target[type])); + } + return ja; + }, + "second on": function(type, callback) { + return this.on(type, {}, callback); + }, + "third on": function(type, ops, callback) { + var expr = this._parse(type, ops), router = this.routeMiddleware.router(expr); + for (var i = expr.channels.length; i--; ) { + var pathStr = sardVar67.pathToString(expr.channels[i].paths); + if (!this._channels[pathStr]) { + this.addChannel(pathStr, sardVar67.channel(expr, i)); + } + } + return router.on(expr, ops, callback); + }, + channels: function() { + return this._channels; + }, + addChannel: function(path, singleChannel) { + this._channels[path] = singleChannel; + }, + _parse: function(type, ops) { + var expr = typeof type != "object" ? sardVar65.parse(type) : type; + if (ops) { + if (ops.meta) sardVar2.copy(ops.meta, expr.meta); + if (ops.type) expr.type = ops.type; + } + return expr; + }, + _router: function(expr) { + return this.routeMiddleware.router(expr); + }, + _createTypeMethod: function(method) { + var self = this; + this[method] = function(type, data, ops, callback) { + if (!ops) ops = {}; + ops.type = method; + var expr = this._parse(type, ops); + return self._router(expr).dispatch(expr, data, ops, callback); + }; + } +}); + +var ConcreteController = AbstractController.extend({ + "override __construct": function() { + this._super(); + var self = this; + this.on({ + "pull channels": function() { + return self.channels(); + } + }); + }, + "override addChannel": function(path, singleChannel) { + this._super(path, singleChannel); + var toPush = {}; + toPush[path] = singleChannel; + this.push("channels", toPush, { + ignoreWarning: true + }); + } +}); + +sardModule68 = ConcreteController; +var sardModule70 = {}; +var sardVar1 = sardModule0, sardVar69 = sardModule68; + +try { + require.paths.unshift(__dirname + "/beans"); +} catch (e) {} + +var Loader = sardVar69.extend({ + "override __construct": function() { + this._super(); + this._params = {}; + }, + params: function(params) { + sardVar1.copy(params || {}, this._params); + return this; + }, + require: function(source) { + if (source instanceof Array) { + for (var i = source.length; i--; ) { + this.require(source[i]); + } + } else if (typeof src == "object" && typeof src.bean == "function") { + source.plugin(this._controller, source.params || this._params[source.name] || {}); + } else { + return false; + } + return this; + } +}); + +sardModule70 = Loader; +var sardModule72 = {}; +var sardVar71 = sardModule70; + +sardModule72.router = function() { + return new sardVar71; +}; + +sardModule72.router().copyTo(sardModule72, true); +var sardModule78 = {}; +var sardVar74 = sardModule0, EventEmitter = sardModule36.EventEmitter, sardVar76 = sardModule68, Janitor = sardModule28.Janitor; + +var Message = sardVar74({ + __construct: function(name, manager) { + this._name = name; + this._manager = manager; + this._data = {}; + }, + action: function(value) { + this._action = value; + return this; + }, + data: function(value) { + this._data = value; + return this; + }, + send: function(action, value) { + if (action) { + this.action(action); + this.data(value); + } + var self = this; + this._manager._connection._target.send(sardVar74.copy(this._buildMessage()), function(err, result) { + if (err) { + self.onError(err); + } + }); + return this; + }, + onError: function(e) {}, + _buildMessage: function() { + return { + name: this._name, + action: this._action, + data: this._data + }; + } +}); + +var Transaction = Message.extend({ + "override __construct": function(name, uid, manager) { + this._super(name, manager); + this._uid = uid; + this._manager = manager; + var em = this._em = new EventEmitter, oldDispose = this._em.dispose, self = this; + this._em.dispose = function() { + this.disposed = true; + oldDispose.call(em); + self.dispose(); + }; + }, + "override _buildMessage": function() { + var message = this._super(); + message.uid = this._uid; + return message; + }, + response: function(message) { + this._em.emit(message.action, message.data); + return this; + }, + on: function(listen) { + for (var type in listen) { + this.on(type, listen[type]); + } + return this; + }, + "second on": function(type, listener) { + this._em.addListener(type, listener); + return this; + }, + register: function() { + this._manager._addTransaction(this); + return this; + }, + onError: function(e) { + this._em.emit("error", e); + }, + disposeOn: function(type) { + var self = this; + return this.on(type, function() { + self.dispose(); + }); + }, + dispose: function() { + if (!this._em.disposed) this._em.dispose(); + this._manager.remove(this._uid); + } +}); + +var CommunicationManager = sardVar74({ + __construct: function(connection) { + this._connection = connection; + this._liveTransactions = {}; + this._connection._target.onMessage = this.getMethod("onMessage"); + this._em = new EventEmitter; + }, + message: function(name) { + return new Message(name, this); + }, + on: function(listen) { + for (var type in listen) { + this._em.addListener(type, listen[type]); + } + }, + onMessage: function(message) { + var trans = this._liveTransactions[message.uid]; + this._connection._hook.ignore(message.name, true); + if (trans) { + trans.response(message); + } else { + var msg; + if (message.uid) { + msg = this.request(message).action(message.action).data(message.data); + } else { + msg = this.message(message.name).action(message.action).data(message.data); + } + this._em.emit(msg._action, msg); + } + this._connection._hook.ignore(message.name, false); + return false; + }, + onDisconnect: function(err) { + for (var uid in this._liveTransactions) { + var transaction = this._liveTransactions[uid]; + transaction.response({ + action: "error", + data: "unable to fullfill request" + }).dispose(); + } + }, + transaction: function(name) { + return (new Transaction(name, this._uid(), this)).register(); + }, + request: function(message) { + return new Transaction(message.name, message.uid, this); + }, + remove: function(uid) { + var trans = this._liveTransactions[uid]; + delete this._liveTransactions[uid]; + return trans; + }, + _addTransaction: function(trans) { + this._liveTransactions[trans._uid] = trans; + }, + _uid: function() { + var uid = (new Date).getTime() + "." + Math.round(Math.random() * 99999); + while (this._liveTransactions[uid]) uid = this._uid(); + return uid; + } +}); + +var RemoteInvoker = sardVar74({ + __construct: function(hook) { + this._janitor = new Janitor; + this._hook = hook; + this.remote = Math.random(); + var self = this; + this._hook._router.on("push -pull hook", { + data: { + all: hook._target.bussed + } + }, function(hook) { + self._hook._transaction().send("hook", hook).dispose(); + }); + this.reset(); + }, + reset: function() { + this.dispose(); + this._janitor.addDisposable(this._virtualRouter = new sardVar76); + this.push = this._virtualRouter.getMethod("push"); + this.pull = this._virtualRouter.getMethod("pull"); + var self = this; + }, + dispose: function() { + this._janitor.dispose(); + }, + hook: function(type, channel) { + switch (type) { + case "push": + return this._hookPush(channel); + case "pull": + return this._hookPull(channel); + default: + return null; + } + }, + _hookPull: function(channel) { + var self = this; + this._janitor.addDisposable(this._virtualRouter.on("pull -stream " + channel, function(request) { + this.wrap(); + if (!this.inner.key) this.inner.key = self.id; + self._hook._transaction(channel).send("pull", { + hasNext: this.hasNext(), + data: this.data, + inner: this.inner + }).on(this).on({ + next: this.next + }).disposeOn("end"); + })); + }, + _hookPush: function(channel) { + var self = this; + this._janitor.addDisposable(this._virtualRouter.on("push -stream " + channel, function() { + if (!this.inner.key) this.inner.key = self.id; + var trans = self._hook._transaction(channel).send("push", { + hasNext: this.hasNext(), + inner: this.inner + }).on({ + next: this.next + }); + this.pipe({ + write: function(chunk) { + trans.send("write", chunk); + }, + end: function() { + trans.send("end").dispose(); + } + }); + })); + } +}); + +var LocalInvoker = sardVar74({ + __construct: function(connection) { + this._con = connection; + this._router = connection._router; + this._janitor = new Janitor; + }, + hook: function(type, channel, ops) { + var self = this, remoteMethod = this._con._remote.getMethod(type); + if (!ops) ops = {}; + if (!ops.meta) ops.meta = {}; + ops.meta.stream = true; + this._janitor.addDisposable(this._router.on(type + " " + channel, ops, function(localRequest) { + if (self._con._hook.ignore(channel) && (!self._con._target.bussed || !this.inner.key || !self._con._remote.id || self._con._remote.id == this.inner.key)) return; + var _next = this.hasNext() ? function() { + localRequest.next(); + } : null; + remoteMethod(channel, localRequest.data, { + meta: { + stream: true + }, + _next: _next, + inner: this.inner + }, function(remoteRequest) { + if (type == "pull") { + remoteRequest.pipe(localRequest); + } else { + localRequest.pipe(remoteRequest); + } + }); + })); + }, + reset: function() { + this._janitor.dispose(); + }, + dispose: function() { + this._janitor.dispose(); + }, + push: function(trans) { + this._router.push(" -stream " + trans._name, {}, { + from: this._con._remote, + meta: this._meta(trans, "push"), + _next: this._next(trans), + inner: this._inner(trans) + }, function(stream) { + trans.register().on(stream.wrap()).disposeOn("end"); + }); + }, + pull: function(trans) { + var id = this._con._remote.id; + this._router.pull(" -stream " + trans._name, trans._data.data, { + from: this._con._remote, + meta: this._meta(trans, "pull"), + _next: this._next(trans), + inner: this._inner(trans) + }, function() { + this.pipe({ + respond: function(response) { + trans.send("respond", response); + }, + write: function(chunk) { + trans.send("write", chunk); + }, + end: function(err) { + trans.send("end"); + trans.dispose(); + } + }); + }); + }, + _next: function(trans) { + return trans._data.hasNext ? function() { + trans.send("next"); + } : null; + }, + _inner: function(trans) { + if (!trans._data.inner.key) trans._data.inner.key = this._con._remote.id; + return trans._data.inner; + }, + _meta: function(trans, type) { + var inner = this._inner(trans); + if (inner.key != this._con._remote.id && this._router.has(trans._name, { + type: type, + meta: { + target: inner.key + } + })) { + return { + target: inner.key + }; + } + return null; + } +}); + +var Connection = sardVar74({ + __construct: function(target, hook) { + this._target = target; + this._hook = hook; + this._router = hook._router; + this._comm = new CommunicationManager(this); + this._janitor = new Janitor; + this._local = (new LocalInvoker(this)).wrap(); + this._remote = new RemoteInvoker(this); + this.janitor = new Janitor; + this._comm.on({ + push: this._local.push, + pull: this._local.pull, + hook: this.getMethod("onHook") + }); + this._onClose(); + }, + _onClose: function() { + var self = this; + this._target.onExit = function(err) { + self._comm.onDisconnect(); + self.dispose(); + }; + }, + onHook: function(trans) { + this._reset(); + var self = this, hook = trans._data; + for (var i = hook.channels.length; i--; ) { + try { + self._listen(hook.channels[i], hook); + } catch (e) {} + } + this._connected(); + return this; + }, + hook: function(type, path, ops) { + this._remote.hook(type, path, ops); + this._local.hook(type, path, ops); + }, + _connected: function() { + if (this._dispatchedConnected) return; + this._dispatchedConnected = true; + this._router.push("hook/connection", null, { + from: this._remote + }); + }, + _listen: function(channel, hook) { + var ops = { + meta: sardVar74.copy(channel.meta || {}) + }, meta = ops.meta; + ops.meta.pull = ops.meta.rotate = ops.meta.bussed = undefined; + ops.meta.stream = ops.meta.hooked = ops.meta.overridable = ops.meta["public"] = 1; + if (this._target.bussed) { + ops.meta.bussed = 1; + } + meta.target = this._remote.id = hook.id; + this.hook("push", channel.path, ops); + var route = this._router.getRoute("pull " + channel.path, ops); + if (route && route.route && route.route.meta) { + if (route.route.meta.hooked == undefined && !route.router._allowMultiple) { + return console.warn("local channel %s exists. Cannot hook remote channel.", channel.path); + } + } + this.hook("pull", channel.path, ops); + }, + _reset: function() { + this._remote.reset(); + this._local.reset(); + }, + dispose: function() { + this._remote.dispose(); + this._local.dispose(); + this.janitor.dispose(); + }, + _response: function(message) { + return this._comm.response(message); + }, + _transaction: function(name) { + return this._comm.transaction(name); + }, + _message: function(name) { + return this._comm.message(name); + } +}); + +var Hook = sardVar74({ + __construct: function(transport, router) { + this._router = router; + var connections = this._connections = [], self = this; + transport.connect(function(connection) { + var con = new Connection(connection, self); + connections.push(con); + con.janitor.addDisposable({ + dispose: function() { + var i = connections.indexOf(con); + if (i > -1) connections.splice(i, 1); + } + }); + }); + }, + ignore: function(name, value) { + if (!this._ignoring) this._ignoring = []; + var i = this._ignoring.indexOf(name); + if (value == undefined) return i > -1; + if (!value && i > -1) { + this._ignoring.splice(i, 1); + } else if (value && i == -1) { + this._ignoring.push(name); + } + } +}); + +sardModule78 = Hook; +var sardModule80 = {}; +sardModule80.callback = function(callback, timeout) { + var interval; + return function() { + clearTimeout(interval); + var args = arguments; + interval = setTimeout(function() { + callback.apply(callback, args); + }, timeout); + }; +}; + +sardModule80.lazy = { + callback: sardModule80.callback +}; +var sardModule82 = {}; +var sardVar79 = sardModule78, sardVar81 = sardModule80; + +sardModule82.plugin = function(mediator, host) { + var oldAddChannel = mediator.addChannel, readyBeans = {}, identifier; + mediator.addChannel = function(path, expr) { + oldAddChannel.apply(mediator, arguments); + lazyPush(); + }; + function init() { + mediator.pullMulti("hook/transport", function(transport) { + new sardVar79(transport, mediator); + }); + } + function onBeanReady(name) { + readyBeans[name] = 1; + mediator.on("pull " + name + "/ready", { + meta: { + "public": 1, + rotate: 1 + } + }, function() { + return true; + }); + } + function getHook(data) { + var d = data || {}; + var channels = [], ch = mediator.channels(); + for (var channel in ch) { + var expr = ch[channel]; + if (!d.all && !expr.meta.bussed && expr.meta.hooked || !expr.meta["public"]) continue; + channels.push({ + meta: expr.meta, + path: channel + }); + } + var info = { + id: identifier, + channels: channels + }; + return info; + } + function pullHook(request) { + return getHook(request.data); + } + function pushHook() { + mediator.push("hook", getHook()); + } + var lazyPush = sardVar81.callback(pushHook, 1); + function onAppId(data) { + console.log(data); + } + function setId(value) { + identifier = value; + pushHook(); + } + function onConnection(data) { + for (var bean in readyBeans) { + this.from.push(bean + "/ready", true, { + ignoreWarning: true + }); + } + } + mediator.on({ + "push init": init, + "push ready": onBeanReady, + "pull hook": pullHook, + "push set/id": setId, + "push hook/connection": onConnection + }); +}; +var sardModule85 = {}; +var sardVar84 = sardModule0; + +sardModule85 = sardVar84({ + __construct: function(socket) { + this._socket = socket; + this._id = socket.id; + var self = this; + socket.on("message", function(batch) { + batch.forEach(function(msg) { + self.onMessage(msg); + }); + }); + socket.on("disconnect", function() { + console.log("socket disconnect :%d", self._id); + self.onExit(); + }); + }, + send: function(message, callback) { + if (!this._batch) { + this._batch = []; + setTimeout(this.getMethod("_sendBatch"), 1); + } + this._batch.push(message); + }, + _sendBatch: function() { + this._socket.json.send(this._batch); + this._batch = null; + }, + onExit: function() {}, + onMessage: function() {} +}); +var sardModule87 = {}; +var sardVar86 = sardModule85; + +sardModule87.plugin = function(router) { + return { + connect: function(onConnection) { + var socket = io.connect("http://localhost:6032"), socket; + socket.on("connect", function() { + router.push("set/id", socket.socket.sessionid); + onConnection(new sardVar86(socket)); + }); + } + }; +}; +var sardModule89 = {}; +var sardVar88 = sardModule87; + +sardModule89.plugin = function(router) { + var con = sardVar88.plugin(router); + router.on({ + "pull -multi hook/transport": function() { + return con; + } + }); +}; +var sardModule91 = {}; +var beanpole = sardModule72.router(); + +function pluginExample(router) { + var name = prompt("What's your name?", "craig"); + var time = Number(prompt("When do you want an alert? (in seconds)", 1)); + function appendBody(message) { + var div = document.createElement("div"); + div.innerHTML = message; + document.body.appendChild(div); + } + router.on({ + "pull -public some/random/callback": function(request) { + appendBody(request.data.message); + this.from.push("notify/clients", request.data); + request.end(); + }, + "push send/message": function(data) { + beanpole.push("call/later", { + channel: "some/random/callback", + data: { + _id: (new Date).getTime(), + message: data.message + }, + sendAt: (new Date).getTime() + data.delay + }); + }, + "push -public notify/clients": function(data) { + appendBody("notified from another client: " + data.message); + } + }); + beanpole.on({ + "push -public -one spice.io/ready": function() { + beanpole.push("send/message", { + message: "hello " + name + "!", + name: name, + delay: time * 1e3 + }); + } + }); +} + +sardModule82.plugin(beanpole); + +sardModule89.plugin(beanpole); + +pluginExample(beanpole); + +beanpole.push("ready", "client"); + +beanpole.push("init"); diff --git a/node_modules/celeri/node_modules/beanpole/examples/ws/hook.js b/node_modules/celeri/node_modules/beanpole/examples/ws/hook.js new file mode 100644 index 0000000..a3d4500 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/ws/hook.js @@ -0,0 +1,37 @@ +var beanpole = require('../../lib/node').router(); + + +beanpole.require(['hook.core','hook.http.mesh']); + +beanpole.on({ + + /** + */ + + 'push init': function() + { + beanpole.push('ready', 'spice.io'); + }, + + /** + */ + + + 'push -public call/later': function(data) + { + console.log('calling later'); + + var self = this; + + setTimeout(function() + { + self.from.pull(data.channel, data.data, { inner: self.inner }, function(result) + { + console.log(result) + }) + },Math.max(0, data.sendAt - new Date().getTime())); + // setTimeout() + } +}); + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/examples/ws/server.js b/node_modules/celeri/node_modules/beanpole/examples/ws/server.js new file mode 100644 index 0000000..4ce2c61 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/examples/ws/server.js @@ -0,0 +1,40 @@ +var beanpole = require('../../lib/node').router(); + + +beanpole.require(['hook.core','hook.socket.io.server','hook.http.mesh']); + +beanpole.on({ + + /** + */ + + 'push init': function() + { + beanpole.push('ready', 'spice.io'); + }, + + /** + */ + + + 'pull -public say/hello': function() + { + return "hello MADRE!"; + }, + + + /** + */ + + + 'push -public client/ready': function() + { + console.log("CLIENT READY"); + this.from.pull('get/name', function(name) + { + console.log(name) + }) + } +}); + +beanpole.push('init'); \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/concrete/collection.js b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/collection.js new file mode 100644 index 0000000..3a59784 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/collection.js @@ -0,0 +1,338 @@ +var Structr = require('structr'), +Parser = require('./parser'), +utils = require('./utils'), +Request = require('./request'), +Janitor = require('sk/core/garbage').Janitor; + + + + + +/** + * collection for routes + */ + +/** + * IMPORTANT notes regarding this class + * 1. you can have multiple explicit middleware (/path/*) +*/ + + +var Collection = Structr({ + + /** + * Constructor. What else do you think it is? + */ + + '__construct': function(ops) + { + + //the options for the router + this._ops = ops || {}; + + //these are the channels parsed into a traversable route + this._routes = this._newRoute(); + + //these get executed whenever there's a new "on" + this._middleware = this._newRoute(); + + //the current route index. increments on every route! + this._routeIndex = 0; + }, + + /** + */ + + 'has': function(expr) + { + var routes = this.routes(expr); + + for(var i = routes.length; i--;) + { + if(routes[i].target) return true; + } + + return false; + }, + + /** + */ + + 'route': function(channel) + { + return this._route(channel.paths); + }, + + /** + */ + + 'routes': function(expr) + { + var channels = expr.channels, + routes = []; + + for(var i = channels.length; i--;) + { + routes.push(this.route(channels[i])); + } + + return routes; + }, + + /** + * listens to the given expression for any chandage + */ + + 'add': function(expr, callback) + { + var janitor = new Janitor(); + + for(var i = expr.channels.length; i--;) + { + janitor.addDisposable(this._add(expr.channels[i], expr.meta, callback)); + } + + + + return janitor; + }, + + /** + */ + + '_add': function(channel, meta, callback) + { + var paths = channel.paths, + isMiddleware = channel.isMiddleware, + middleware = channel.thru, + + //middleware isn't used explicitly. Rather, it's *injected* into the routes which ARE used. Remember that. + //explicit middleware looks like some/path/* + currentRoute = this._start(paths, isMiddleware ? this._middleware : this._routes, true); + + //some explicit middleware might already be defined, so we need to get the *one* to pass through. + var before = this._before(paths, currentRoute); + + + if(middleware) this._endMiddleware(middleware).thru = before; + + + //the final callback for the route + var listener = { + callback: callback, + + //metadata for the expression + meta: meta, + + //keeps tabs for later use (in request) + id: 'r'+(this._routeIndex++), + + //this is a queue where the first item is executed first, then on until we reach the last item + thru: middleware || before, + + isMiddleware: channel.isMiddleware, + + path: paths, + + dispose: function() + { + var i = currentRoute.listeners.indexOf(listener); + if(i > -1) currentRoute.listeners.splice(i, 1); + } + }; + + currentRoute.meta = Structr.copy(meta, currentRoute.meta); + + //at this point we can inject the listener into the current route IF it's middleware. + if(isMiddleware) this._injectMiddleware(listener, paths); + + + //now that we're in the clear, need to add the listener! + if(!currentRoute.listeners) currentRoute.listeners = []; + + + //now to add it. Please take remember, for MOST CASES, "_listeners" will only have one, especially for http / requests + currentRoute.listeners.push(listener); + + + + //the return statement allows for the item to be disposed of + return listener; + }, + + /** + */ + + '_endMiddleware': function(target) + { + var current = target || {}; + + while(current.thru) + { + current = current.thru; + } + + return current; + }, + + /** + * injects explicit middleware (/path/*) in all the routes which go through its path + */ + + '_injectMiddleware': function(listener, paths) + { + //level is only important for + listener.level = paths.length; + + //need to go through *all* routes ~ even middleware, because middleware also have + //routes to pass through ~ Inception. + var afterListeners = this._after(paths, this._routes).concat(this._after(paths, this._middleware)); + + //go through ALL items to put before this route, but make sure the item we're replacing isn't higher + //in the middleware chain, because higher methods will already *have* reference to this pass-thru + for(var i = afterListeners.length; i--;) + { + var currentListener = afterListeners[i]; + + var currentMiddleware = currentListener.thru, + previousMiddleware = currentListener; + + while(currentMiddleware) + { + if(currentMiddleware.level != undefined) + { + if(currentMiddleware.level < listener.level) + { + previousMiddleware.thru = listener; + } + break; + } + + previousMiddleware = currentMiddleware; + currentMiddleware = currentMiddleware.thru; + } + + if(!currentMiddleware) previousMiddleware.thru = listener; + } + }, + + /** + * reveals routes which must come *before* a middleware + * after beats circular references + * TODO: following code is __ugly as fuck__. + */ + + '_before': function(paths, after) + { + var current = this._middleware, + listeners = []; + + for(var i = 0, n = paths.length; i < n; i++) + { + + //this makes sure we don't get to the end for pass thrus + if(current.listeners) listeners = current.listeners; + + + var path = paths[i], + + newCurrent = path.param ? current._route._param : current._route[path.name]; + + + if(current == after || !newCurrent) break; + + current = newCurrent; + } + + + // if(current != after) + //this is a check against pass thrus to beat circular references. It *also* allows this: hello/* -> hello + if(current != after && current.listeners) listeners = current.listeners; + + return listeners[0]; + }, + + /** + * reveals everyhing that comes *after* a route (for pass-thru's) + */ + + '_after': function(paths, routes) + { + return this._flatten(this._start(paths, routes)); + }, + + /** + * returns the starting point of a route + */ + + '_route': function(paths, routes, create, retControl) + { + var control = (routes || this._routes), + current = control._route; + + for(var i = 0, n = paths.length; i < n; i++) + { + var path = paths[i], + name = path.param ? '_param' : path.name; + + if(!current[name] && create) + { + current[name] = this._newRoute(i); + } + + if(current[name]) + { + current = current[name]; + } + else + { + current = current._param; + } + + + if(!current) return {}; + + control = current; + current = current._route; + } + + + return control; + }, + + /** + */ + + '_start': function(paths, routes) + { + return this._route(paths, routes, true); + }, + + /** + */ + + '_newRoute': function(level) + { + return { _route: { }, _level: level || 0 }; + }, + + /** + * flattens all routes into a single array + */ + + '_flatten': function(route) + { + var listeners = route.listeners ? route.listeners.concat() : []; + + + for(var path in route._route) + { + listeners = listeners.concat(this._flatten(route[path] || {})); + } + + return listeners; + } +}); + + +module.exports = Collection; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/concrete/parser.js b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/parser.js new file mode 100644 index 0000000..1570fc8 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/parser.js @@ -0,0 +1,595 @@ + +var Structr = require('structr'); + +/** + * parses syntactic sugar. + + Why the hell are you using a parser for something so simple? Because I wanted to. Yeah, I could have done it in Regexp, but fuck that >.>... This + Is much more fun. + */ + + + +//follow the pattern below when adding tokens plz. + +var Token = { + + // A-Z + WORD: 1, + + // -metadata + METADATA: 1 << 1, + + + // = + PATH: 1 << 2, + + + // :param + PARAM: 1 << 3, + + // -> + TO: 1 << 4, + + // for routing + BACKSLASH: 1 << 5, + + // . + DOT: 1 << 6, + + // * - this is an auto-middleware + STAR: 1 << 7, + + // "or" + OR: 1 << 8, + + // ( + LP: 1 << 9, + + // ) + RP: 1 << 10, + + // = + EQ: 1 << 11, + + + //whitespace + WHITESPACE: 1 << 12 +}; + + +//reserved keywords +var Reversed = { + or: Token.OR +} + + +var Tokenizer = function() +{ + + //source of the string to tokenize + var source = '', + + //the position of the parser + pos = 0, + + //the current token + currentToken, + + self = this; + + + /** + * getter / setter for the source + */ + + this.source = function(value) + { + if(value) + { + source = value+' '; //padding + pos = 0; + } + + return source; + } + + /** + * next token + */ + + this.next = function(keepWhite) + { + return currentToken = nextToken(keepWhite); + } + + /** + */ + + this.peekChars = function(n) + { + return source.substr(pos, n); + } + + + + /** + */ + + this.current = function(keepWhite) + { + return currentToken || self.next(keepWhite); + } + + + /** + */ + + this.position = function() + { + return pos; + } + + /** + */ + + var nextToken = function(keepWhite, ignoreError) + { + if(!keepWhite) skipWhite(); + + if(eof()) return null; + + var c = currentChar(), ccode = c.charCodeAt(0); + + if(isWhite(ccode)) + { + + skipWhite(); + return token(' ',Token.WHITESPACE); + } + + //a-z0-9 + if(isAlpha(ccode)) + { + var w = nextPath(); + + return token(w, Reversed[w.toLowerCase()] || Token.WORD); + } + + + + switch(c) + { + + //for middleware + case '-': + if(nextChar() == '>') return token('->', Token.TO, true); + if(isAlpha(currentCharCode())) return token(nextPath(), Token.METADATA); + + error(); + + //parameters for routes + case ':': + if(isAlpha(nextCharCode())) return token(nextPath(), Token.PARAM); + + error(); + + case '/': return token('/', Token.BACKSLASH, true); + case '.': return token('.', Token.DOT, true); + case '*': return token('*', Token.STAR, true); + case '(': return token('(', Token.LP, true); + case ')': return token(')', Token.RP, true); + case '=': return token('=', Token.EQ, true); + + //path part + default: return token(nextPath(), Token.PATH); + } + + //eof + return null; + } + + var error = function() + { + throw new Error('Unexpected character "'+currentChar()+'" at position '+pos+' in "'+source+'"'); + } + + /** + */ + + var token = function(value, type, skipOne) + { + if(skipOne) nextChar(); + + + return { value: value, type: type }; + } + + + /** + */ + + var nextChar = this.nextChar = function() + { + return source[++pos]; + } + + /** + */ + + var currentChar = this.currentChar = function() + { + return source[pos]; + } + + /** + */ + + var isAlpha = this.isAlpha = function(c) + { + return (c > 96 && c < 123) || (c > 64 && c < 91) || isNumber(c) || c == 95; + } + + /** + */ + + var isWhite = this.isWhite = function(c) + { + return c == 32 || c == 9 || c == 10; + } + + /** + */ + + var isNumber = this.isNumber = function(c) + { + return c > 47 && c < 58; + } + + /** + */ + + var nextCharCode = function() + { + return nextChar().charCodeAt(0); + } + /** + */ + + var currentCharCode = function() + { + return currentChar().charCodeAt(0); + } + + /** + */ + + var rewind = function(steps) + { + pos -= (steps || 1); + } + + + /** + */ + + var skipWhite = function() + { + var end = false; + + while(!(end = eof())) + { + if(!isWhite(currentCharCode())) break; + + nextChar(); + } + return !end; + } + + + /** + */ + + var nextNumber = function() + { + var buffer = currentChar(); + + while(!eof()) + { + if(isNumber(nextCharCode())) + { + buffer += currentChar(); + } + else + { + break; + } + } + + return buffer; + } + + + /** + */ + + var nextPath = function() + { + var buffer = currentChar(); + + while(!eof()) + { + if(!isWhite(nextCharCode()) && !currentChar().match(/[\/=()]/g)) + // if(isAlpha(nextCharCode()) || isNumber(currentCharCode())) + { + buffer += currentChar(); + } + else + { + break; + } + } + + return buffer; + } + + + /** + * end of file + */ + + var eof = function() + { + return pos > source.length-2; + } +} + + +var ChannelParser = function() +{ + var tokenizer = new Tokenizer(), + cache = {}; + + /** + * parses a string into a handleable expression + */ + + this.parse = function(source) + { + if(!source) throw new Error('Source is not defined'); + + //stuff might have happened to the expression, so we need to clone it. it DEFINITELY changes + //when pull requests are made... + if(cache[source]) return Structr.copy(cache[source]); + + tokenizer.source(source); + + return Structr.copy(cache[source] = rootExpr()); + } + + + var rootExpr = function() + { + var expr = tokenizer.current(), + type, + meta = {}; + //type is not defined, but that's okay! + + if(expr.type == Token.WORD && tokenizer.isWhite(tokenizer.peekChars(1).charCodeAt(0)) && tokenizer.position() < tokenizer.source().length-1) + { + type = expr.value; + tokenizer.next(); + } + + var token, channels = []; + + while(token = tokenizer.current()) + { + switch(token.type) + { + + //-metadata=test + case Token.METADATA: + meta[token.value] = metadataValue(); + break; + + case Token.BACKSLASH: + case Token.WORD: + case Token.STAR: + channels = channels.concat(channelsExpr()); + break; + case Token.OR: + tokenizer.next(); + break; + default: + tokenizer.next(); + break; + } + } + + return { type: type, meta: meta, channels: channels }; + } + + var metadataValue = function() + { + if(tokenizer.currentChar() == '=') + { + tokenizer.next(); + var v = tokenizer.next().value; + tokenizer.next(); + return v; + } + + tokenizer.next(); + + return 1; + } + + var channelsExpr = function() + { + var channels = [], + to; + + + while(hasNext()) + { + + if(currentTypeIs(Token.LP)) + { + tokenizer.next(); + } + + + + if(currentTypeIs(Token.WORD | Token.PARAM | Token.STAR | Token.BACKSLASH)) + { + channels.push([channelPathsExpr()]); + + while(currentTypeIs(Token.OR)) + { + tokenizer.next(); + channels[channels.length-1].push(channelPathsExpr()); + } + } + else + { + break; + } + + + if(currentTypeIs(Token.RP)) + { + tokenizer.next(); + } + + if(currentTypeIs(Token.TO)) + { + tokenizer.next(); + } + } + + + var _orChannels = splitChannelExpr(channels.concat(), []), + channelsThru = []; + + for(var i = _orChannels.length; i--;) + { + var chain = Structr.copy(_orChannels[i]), + current = channel = chain[chain.length-1]; + + for(var j = chain.length-1; j--;) + { + current = current.thru = chain[j]; + } + + + channelsThru.push(channel); + } + + return channelsThru; + } + + var splitChannelExpr = function(orChannels, stack) + { + if(!orChannels.length) return [stack]; + + var current = orChannels.shift(); + + if(current.length == 1) + { + stack.push(current[0]); + + return splitChannelExpr(orChannels, stack); + } + else + { + var split = []; + + for(var i = current.length; i--;) + { + var stack2 = stack.concat(); + + stack2.push(current[i]); + + split = split.concat(splitChannelExpr(orChannels.concat(), stack2)); + } + + return split; + } + + } + + var channelPathsExpr = function(type) + { + var paths = [], + token, + isMiddleware = false, + cont = true; + + while(cont && (token = tokenizer.current())) + { + + switch(token.type) + { + case Token.WORD: + case Token.PARAM: + case Token.PATH: + paths.push({ name: token.value, param: token.type == Token.PARAM }); + break; + case Token.BACKSLASH: + break; + default: + cont = false; + break; + } + + if(cont) tokenizer.next(); + } + + if(currentTypeIs(Token.STAR)) + { + isMiddleware = true; + tokenizer.next(); + } + + + return { paths: paths, isMiddleware: isMiddleware }; + } + + + var currentToken = function(type, igError) + { + return checkToken(tokenizer.current(), type, igError); + } + + var nextToken = function(type, igError, keepWhite) + { + return checkToken(tokenizer.next(keepWhite), type, igError); + } + + var checkToken = function(token, type, igError) + { + if(!token || !(type & token.type)) + { + if(!igError) throw new Error('Unexpected token "'+(token || {}).value+'" at position '+tokenizer.position()+' in '+tokenizer.source()); + + return null; + } + + return token; + } + + var currentTypeIs = function(type) + { + var current = tokenizer.current(); + + return current && !!(type & current.type); + } + + var hasNext = function() + { + return !!tokenizer.current(); + } +} + +exports.parse = new ChannelParser().parse; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/concrete/request.js b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/request.js new file mode 100644 index 0000000..67606d8 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/request.js @@ -0,0 +1,310 @@ +var Structr = require('structr'), +Parser = require('./parser'), +utils = require('./utils'); + + +var Request = Structr({ + + /** + */ + + '__construct': function(listener, batch) + { + //data necessary for the request + this.data = batch.data; + + //inner data which is invisible to the request, but contains data which needs to get passed along + this.inner = batch.inner; + + //the end callback + this.callback = batch.callback; + + this._used = {}; + this._queue = []; + + //yes, and I know what you're thinking: why the hell are you copying data? + //Well, we work backwards, and we don't know if parameters might override data passed to the current URI - we need to be prepared for that. SO + //as we're working our way back up, data will be set, and the original data will be mapped the way it should be for the given URI + this._add(listener, Structr.copy(this.data, true), batch.paths); + + + if(batch._next) + { + this.add(batch._next); + } + + this.last = this._queue[0].target; + }, + + /** + */ + + 'init': function() + { + return this; + }, + + /** + */ + + 'hasNext': function() + { + return !!this._queue.length; + }, + + /** + */ + + 'next': function() + { + if(this._queue.length) + { + var thru = this._queue.pop(), + target = thru.target; + + this.current = target; + + if(target.paths) + { + var route = this.origin.getRoute({ channel: target }); + + this._addListeners(route.listeners, route.data, target.paths); + return this.next(); + } + + + //heavier... + /*var route = this.expandRoute(this._queue.length-1); + + if(!route) return this.next(); + + target = route.target, + thru = route.thru; + this._queue.pop();*/ + + + this.current = target; + + + if(target.isMiddleware && this._used[target.id]) return this.next(); + + //keep tabs of what's used so there's no overlap. this will happen when we get back to the router + //for middleware specified in path -> to -> route + this._used[target.id] = thru; + + this._prepare(target, thru.data, thru.hasParams, thru.paths); + + + return true; + } + + return false; + }, + + /** + * expands all the routes (middleware even). See leche for example + */ + + /*'expandThru': function() + { + + var i = 0; + + while(i < this._queue.length) + { + if(this.expandRoute(i)) + { + i++; + } + else + { + i = 0; + } + } + + },*/ + + /** + */ + + /*'expandRoute': function(index) + { + var thru = this._queue[index], + target = thru.target; + + if(target.paths) + { + this._queue.splice(index, 1); + var route = this.origin.getRoute({ channel: target }), n = this._queue.length; + + + this._addListeners(route.listeners, route.data, target.paths); + + return false; + } + + return { target: target, thru: thru }; + },*/ + + /** + */ + + 'forward': function(channel, callback) + { + return this.origin.dispatch(Parser.parse(channel), this.data, { inner: this.inner, req: this.req }, callback); + }, + + /** + */ + + 'thru': function(channel, ops) + { + var self = this; + + if(ops) Structr.copy(ops, this, true); + + + this._queue.push({ target: Parser.parse('-stream ' + channel).channels[0] }); + + this.next(); + + /*this.origin.dispatch(Parser.parse('-stream' + channel), this.data, Structr.copy({ inner: this.inner, req: this.req, _next: callback }, ops, true), function(request) + { + request.pipe(self); + })*/ + }, + + /** + */ + + '_addListeners': function(listeners, data, paths) + { + if(listeners instanceof Array) + { + for(var i = listeners.length; i--;) + { + this._add(listeners[i], data, paths); + } + return; + } + }, + + /** + * adds middleware to the END of the call stack + */ + + 'add': function(callback) + { + this._queue.unshift(this._func(callback)); + }, + + /** + * adds middleware to the beginning of the call stack + */ + + 'unshift': function(callback) + { + this._queue.push(this._func(callback)); + }, + + /** + */ + + '_func': function(callback) + { + return { target: { callback: callback }, data: {} }; + }, + + /** + */ + + '_add': function(route, data, paths) + { + var current = route, _queue = this._queue, + hasParams = false; + + if(!data) data = {}; + + while(current) + { + for(var i = paths.length; i--;) + { + var opath = paths[i], + cpath = route.path[i], + param, + value; + + + if(cpath.param && !opath.param) + { + param = cpath.name; + value = opath.name; + } + else + if(cpath.param && opath.param) + { + param = cpath.name; + value = this.data[opath.name]; + } + else + { + continue; + } + + hasParams = true; + + + this.data[param] = data[param] = value; + + + // if(!this.data[param]) this.data[param] = value; + } + + //make sure not to use the same route twice. this will happen especially with middleware specified as /middleware/* + _queue.push({ target: current, data: data, hasParams: hasParams, paths: paths }); + + current = current.thru; + } + }, + + + /** + */ + + '_prepare': function(target, data, hasParams, paths) + { + //call once, then dispose + if(target.meta && target.meta.one) + { + target.dispose(); + } + + if(hasParams) + { + Structr.copy(data, this.data,true); + } + + + if(target.path) this.currentChannel = utils.pathToString(target.path, this.data); + + this._callback(target, data); + }, + + /** + */ + + 'channelPath': function(index) + { + return utils.pathToString(this._queue[index].target.path || [], this.data); + }, + + /** + */ + + '_callback': function(target, data) + { + return target.callback.call(this, this); + } +}); + +module.exports = Request; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/concrete/router.js b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/router.js new file mode 100644 index 0000000..22333fe --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/router.js @@ -0,0 +1,282 @@ +var Structr = require('structr'), +Parser = require('./parser'), +utils = require('./utils'), +middleware = require('../middleware/meta'), +Request = require('./request'), +Collection = require('./collection'); + + + +/** + * Glorious. + */ + +var Router = Structr({ + + /** + * Constructor. What else do you think it is? + */ + + '__construct': function(ops) + { + if(!ops) ops = {}; + + this.RequestClass = ops.RequestClass || Request; + this._collection = new Collection(ops); + this._allowMultiple = !!ops.multi; + + }, + + /** + * listens to the given expression for any change + */ + + 'on': function(expr, ops, callback) + { + if(!callback) + { + callback = ops; + ops = null; + } + + for(var i = expr.channels.length; i--;) + { + var single = utils.channel(expr, i), + existingRoute = this.getRoute(single); + + if(existingRoute.listeners.length && !this._allowMultiple && !this._middleware().allowMultiple(single)) + { + var epath = existingRoute.listeners[0].path; + + //use-case: server crashes, and reboots. Needs to override current registered path (which is trash) + if(existingRoute.listeners[0].meta.overridable) + { + existingRoute.listeners[0].dispose(); + } + else + + //if both are params, then there's a collission. + if(single.channel.paths[single.channel.paths.length-1].param == epath[epath.length-1].param) + { + throw new Error('Path "'+utils.pathToString(single.channel.paths)+'" already exists'); + } + }; + + this._middleware().setRoute(channel); + } + + + return this._collection.add(expr, callback); + }, + + /** + */ + + '_middleware': function() + { + return this.controller.metaMiddleware; + }, + + /** + */ + + 'hasRoute': function(channel, data) + { + return !!this.getRoute(channel, data).listeners.length; + }, + + /** + */ + + 'hasRoutes': function(expr, data) + { + for(var i = expr.channels.length; i--;) + { + if(this.hasRoute(utils.channel(expr, i), data)) return true; + } + + return false; + }, + + /** + */ + + 'getRoute': function(single, data) + { + var route = this._collection.route(single.channel); + + var r = this._middleware().getRoute({ + expr: single, + router: this, + route: route, + data: data, + listeners: this._filterRoute(single, route) + }); + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + //this chunk is experimental. Moreso to test its usefulness over anything. The initial + //thought is enable the ability for routes with *different* metadata to share the same channel. This is great + //If say, you have web-workers which use the same channels, but different cluster IDs, so a master server knows + //what data to send to what web-worker. This COULD be specified in the URI structure, but that feels a bit messy. We'll see if this works first. It's nice and clean. + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + if(!this._middleware().allowMultiple(route) && !this._allowMultiple && r.listeners.length) + { + r.listeners = [r.listeners[0]]; + } + + return r; + }, + + /** + */ + + 'dispatch': function(expr, data, ops, callback) + { + //only one for now. may change later on. + for(var i = expr.channels.length; i--;) + { + if(this._dispatch(utils.channel(expr, i), data, ops, callback)) return true; + } + + return false; + }, + + /** + */ + + '_dispatch': function(expr, data, ops, callback) + { + if(data instanceof Function) + { + callback = data; + data = undefined; + ops = undefined; + } + + if(ops instanceof Function) + { + callback = ops; + ops = undefined; + } + + if(!ops) ops = {}; + if(!data) data = {}; + + channel = utils.pathToString(expr.channel.paths); + + var inf = this.getRoute(expr, data); + + //warnings are good incase this shouldn't happen + if(!inf.listeners.length) + { + if(!ops.ignoreWarning && !expr.meta.passive) + { + console.warn('The %s route "%s" does not exist', expr.type, channel); + } + + //some callbacks are passive, meaning the dispatched request is *optional* ~ like a plugin + if(expr.meta.passive && callback) + { + callback(null, 'Route Exists'); + } + return false; + } + + + var newOps = { + + //router is set to controller because router() is used in loader. keeps things consistent, and using "this.controller.pull" is vague + router: this.controller, + + //where the route lives + origin: this, + + //data attached, duh. + data: inf.data, + + //inner data + inner: ops.inner || {}, + + channel: channel, + + paths: inf.expr.channel.paths, + + //the metadata attached to the expression. Tells all about how it should be handled + meta: expr.meta, + + //where is the dispatch coming from? Useful for hooks + from: ops.from || this.controller, + + //the listeners to dispatch + listeners: inf.listeners, + + //the final callback after everything's done ;) + callback: callback + }; + + Structr.copy(newOps, ops, true); + + this._callListeners(ops); + + return true; + }, + + /** + */ + + '_callListeners': function(newOps) + { + for(var i = newOps.listeners.length; i--;) + { + Structr.copy(newOps, new this.RequestClass(newOps.listeners[i], newOps), true).init().next(); + } + }, + + /** + * filters routes based on metadata + */ + + '_filterRoute': function(expr, route) + { + if(!route) return [ ]; + + var listeners = (route.listeners || []).concat(); + + + //Useful if there are groups of listeners with the same channel, but should not communicate + //with each other. E.g: two apps with slaves, sending queues to thyme. Thyme would need to know exactly where the slaves are + for(var name in expr.meta) + { + //the value of the metadata to search + var value = expr.meta[name]; + + //make sure that it's not *just* defined. This is important + //for metadata such as streams + if(value === 1) continue; + + //loop through the listeners and start filtering + for(var i = listeners.length; i--;) + { + var listener = listeners[i]; + + if(listener.meta.unfilterable) break; + + var metaV = listener.meta[name]; + + //if value == 1, then the tag just needs to exist + if(metaV != value && metaV != '*') + { + listeners.splice(i, 1); + } + } + } + + + + return listeners; + } +}); + + + +module.exports = Router; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/concrete/utils.js b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/utils.js new file mode 100644 index 0000000..b82174c --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/concrete/utils.js @@ -0,0 +1,115 @@ + +/** + * replaces params of the given expression + */ + + +exports.replaceParams = function(expr, params) +{ + + var path; + + for(var i = expr.channel.paths.length; i--;) + { + path = expr.channel.paths[i]; + + if(path.param) + { + + path.param = false; + path.name = params[path.name]; + + //no name? IT MUST EXIST. DELETE! + if(!path.name) expr.channel.paths.splice(i, 1); + } + } + + return expr; +} + + +exports.channel = function(expr, index) +{ + return { type: expr.type, channel: expr.channels[index], meta: expr.meta || {} }; +} + + +exports.pathToString = function(path, data) +{ + var paths = []; + + if(!data) data = {}; + + for(var i = 0, n = path.length; i < n; i++) + { + var pt = path[i], + part; + + if(pt.param && data[pt.name]) + { + part = data[pt.name]; + } + else + { + part = pt.param ? ':' + pt.name : pt.name; + } + + paths.push(part); + } + + return paths.join('/'); +} + +//old +/*exports.channelToStr = function(channel, omit) +{ + var buffer = []; + + if(!omit) omit = []; + + if(expr.type && !omit.type) buffer.push(expr.type); + + if(!omit.meta) + for(var key in channel.meta) + { + buffer.push('-'+key+'='+expr.meta[key]); + } + + var current = expr.channel; + + var middleware = []; + + while(current) + { + var paths = []; + + for(var i = 0, n = current.paths.length; i < n; i++) + { + var path = current.paths[i]; + + paths.push((path.param ? ':' : '')+ path.name); + } + + middleware.unshift(paths.join('/')); + + current = current.thru; + } + + buffer.push(middleware.join(' -> ')); + + return buffer.join(' '); +}*/ + +exports.passThrusToArray = function(channel) +{ + var cpt = channel.thru, + thru = []; + + while(cpt) + { + thru.push(this._pathToString(cpt.paths)); + cpt = cpt.thru; + } + + return thru; +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/controller.js b/node_modules/celeri/node_modules/beanpole/lib/core/controller.js new file mode 100644 index 0000000..4180d6a --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/controller.js @@ -0,0 +1,200 @@ +var Structr = require('structr'), +routeMiddleware = require('./middleware/route'), +metaMiddleware = require('./middleware/meta'), +Parser = require('./concrete/parser'), +Janitor = require('sk/core/garbage').Janitor, +utils = require('./concrete/utils'); + +var AbstractController = Structr({ + + /** + */ + + + '__construct': function(target) + { + this.metaMiddleware = metaMiddleware(this); + this.routeMiddleware = routeMiddleware(this); + + this.metaMiddleware.init(); + this.routeMiddleware.init(); + + this._channels = {}; + }, + + /** + */ + + 'has': function(type, ops) + { + var expr = this._parse(type, ops); + return this._router(expr).hasRoutes(expr); + }, + + /** + */ + + 'getRoute': function(type, ops) + { + var expr = this._parse(type, ops); + return this._router(expr).getRoute(utils.channel(expr, 0)); + }, + + /** + */ + + 'on': function(target) + { + var ja = new Janitor(); + + for(var type in target) + { + ja.addDisposable(this.on(type, {}, target[type])); + } + + return ja; + }, + + /** + */ + + 'second on': function(type, callback) + { + return this.on(type, {}, callback); + }, + + /** + */ + + 'third on': function(type, ops, callback) + { + var expr = this._parse(type, ops), + router = this.routeMiddleware.router(expr); + + for(var i = expr.channels.length; i--;) + { + var pathStr = utils.pathToString(expr.channels[i].paths); + + if(!this._channels[pathStr]) + { + this.addChannel(pathStr, Structr.copy(utils.channel(expr, i))); + } + } + + return router.on(expr, ops, callback); + }, + + /** + */ + + 'channels': function() + { + return this._channels; + }, + + /** + */ + + 'addChannel': function(path, singleChannel) + { + for(var prop in singleChannel.meta) + { + singleChannel.meta[prop] = '*'; + } + + this._channels[path] = singleChannel; + }, + + /** + * flavor picker for operations. In the string, or in the ops ;) + */ + + '_parse': function(type, ops) + { + var expr = typeof type != 'object' ? Parser.parse(type) : Structr.copy(type); + + if(ops) + { + if(ops.meta) Structr.copy(ops.meta, expr.meta); + if(ops.type) expr.type = ops.type; + } + + return expr; + }, + + /** + */ + + '_router': function(expr) + { + return this.routeMiddleware.router(expr); + }, + + /** + */ + + '_createTypeMethod': function(method) + { + var self = this; + + var func = this[ method ] = function(channel, data, ops, callback) + { + if(!ops) ops = {}; + ops.type = method; + + var expr = this._parse(channel, ops); + + return self._router(expr).dispatch(expr, data, ops, callback); + } + + + var router = self._router( { type: method }); + + + Structr.copy(router, func, true); + + } +}); + + +var ConcreteController = AbstractController.extend({ + + /** + */ + + 'override __construct': function() + { + this._super(); + + var self = this; + + //make channels data-bindable + this.on({ + + /** + */ + + 'pull channels': function() + { + return self.channels(); + } + }); + }, + + /** + */ + + 'override addChannel': function(path, singleChannel) + { + this._super(path, singleChannel); + + //keep the same format as the channels so the end-point is handled exactly the same + var toPush = {}; + + toPush[path] = singleChannel; + + this.push('channels', toPush, { ignoreWarning: true }); + } +}) + +module.exports = ConcreteController; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/index.js new file mode 100644 index 0000000..3db2139 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/index.js @@ -0,0 +1,11 @@ +var Loader = require('./loader'); + + +//or a new, sandboxed router +exports.router = function() +{ + return new Loader(); +} + +//singleton to boot +exports.router().copyTo(module.exports, true); diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/loader.js b/node_modules/celeri/node_modules/beanpole/lib/core/loader.js new file mode 100644 index 0000000..83ecc76 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/loader.js @@ -0,0 +1,76 @@ +var Structr = require('structr'), +Controller = require('./controller'); + +try +{ + require.paths.unshift(__dirname + '/beans'); +}catch(e) +{ + //break the web. +} + +var Loader = Controller.extend({ + + /** + */ + + + 'override __construct': function() + { + this._super(); + + this._params = {}; + }, + + /** + */ + + 'params': function(params) + { + if(typeof params == 'string') return this._params[params]; + + Structr.copy(params || {}, this._params); + return this; + }, + + /** + */ + + 'require': function() + { + for(var i = arguments.length; i--;) + { + this._require(arguments[i]); + } + + return this; + }, + + /** + */ + + '_require': function(source) + { + if(source instanceof Array) + { + for(var i = source.length; i--;) + { + this._require(source[i]); + } + } + else + if(typeof src == 'object' && typeof src.bean == 'function') + { + source.plugin(this._controller, source.params || this._params[ source.name ] || {}); + } + else + { + return false; + } + + return true; + } + +}); + +module.exports = Loader; diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/index.js new file mode 100644 index 0000000..ecae203 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/index.js @@ -0,0 +1,138 @@ +var Structr = require('structr'); + +module.exports = function() +{ + var mw = new exports.Middleware(); + + mw.init = function() + { + //needs to be useable online = manual + mw.add(require('./rotate')); + } + + return mw; +} + +exports.Middleware = Structr({ + + /** + */ + + '__construct': function() + { + + //middleware specific to metadata + this._toMetadata = {}; + + //middleware which handles everything + this._universal = {}; + }, + + /** + */ + + 'add': function(module) + { + var self = this; + + if(module.all) + { + module.all.forEach(function(type) + { + if(!self._universal[type]) self._universal[type] = []; + + self._universal[type].push(module); + }); + } + + module.meta.forEach(function(name) + { + self._toMetadata[name] = module; + }); + }, + + /** + */ + + 'getRoute': function(ops) + { + //parse metadata TO, and FROM + var mw = this._getMW(ops.route ? ops.route.meta : {}, 'getRoute').concat(this._getMW(ops.expr.meta)); + + return this._eachMW(ops, mw, function(cur, ops) + { + return cur.getRoute(ops); + }); + }, + + /** + */ + + 'setRoute': function(ops) + { + var mw = this._getMW(ops.meta, 'setRoute'); + + return this._eachMW(ops, mw, function(cur, ops) + { + return cur.setRoute(ops); + }); + }, + + /** + */ + + 'allowMultiple': function(expr) + { + var mw = this._getMW(expr.meta); + + for(var i = mw.length; i--;) + { + if(mw[i].allowMultiple) return true; + } + + + return false; + }, + + /** + */ + + '_getMW': function(meta, uni) + { + var mw = (this._universal[uni] || []).concat(); + + for(var name in meta) + { + if(meta[name] == undefined) continue; + + var handler = this._toMetadata[name]; + + if(handler && mw.indexOf(handler) == -1) mw.push(handler); + } + + return mw; + }, + + /** + */ + + '_eachMW': function(ops, mw, each) + { + var cops = ops, + newOps; + + + for(var i = mw.length; i--;) + { + if(newOps = each(mw[i], cops)) + { + cops = newOps; + } + } + + return cops; + } + +}); + + diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/rotate.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/rotate.js new file mode 100644 index 0000000..77ac794 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/rotate.js @@ -0,0 +1,39 @@ + + + +exports.rotator = function(target, meta) +{ + + if(!target) target = {}; + + target.meta = [meta]; + target.allowMultiple = true; + + target.getRoute = function(ops) + { + var route = ops.route, + listeners = ops.listeners; + + + //if rotate is specified, then we need to rotate it (round-robin). There's a catch though... + //because the above *might* have filtered down to metadata values, we need to only rotate what's left, AND + //the rotate index must be stuck with the routes rotate metadata. + //Also, if the router can have multiple, then we cannot do round-robin. FUcKs ShiT Up. + if(!ops.router._allowMultiple && route && route.meta && route.meta[meta] != undefined && listeners.length) + { + route.meta[meta] = (++route.meta[meta]) % listeners.length; + + //only ONE listener now.. + ops.listeners = [listeners[route.meta[meta]]]; + } + + } + + + target.setRoute = function(ops) + { + + } +} + +exports.rotator(exports, 'rotate'); diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/store.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/store.js new file mode 100644 index 0000000..6f379ba --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/meta/store.js @@ -0,0 +1,8 @@ +exports.meta = ['store']; + + + +exports.getRoute = function(){}; +exports.setRoute = function(ops) +{ +}; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/default/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/default/index.js new file mode 100644 index 0000000..36bfc88 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/default/index.js @@ -0,0 +1,13 @@ +var Router = require('../../../concrete/router'); + +exports.types = ['dispatch']; + +exports.test = function(expr) +{ + return !expr.type || expr.type == 'dispatch' ? 'dispatch' : null; +} + +exports.newRouter = function() +{ + return new Router({multi:true}); +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/index.js new file mode 100644 index 0000000..4d6b3c7 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/index.js @@ -0,0 +1,91 @@ +var Structr = require('structr'); + + +module.exports = function(controller) +{ + var mw = new exports.Middleware(controller); + + mw.init = function() + { + //needs to be useable online = manual + mw.add(require('./pushPull/push')); + mw.add(require('./pushPull/pull')); + mw.add(require('./default')); + } + + return mw; +} + +exports.Middleware = Structr({ + + /** + */ + + '__construct': function(controller) + { + this._middleware = []; + + this._controller = controller; + + //instantiated routers + this._routers = {}; + + //types of routers + this.types = []; + }, + + /** + */ + + 'add': function(module) + { + this._middleware.push(module); + + this.types = module.types.concat(this.types); + + for(var i = module.types.length; i--;) + { + this._controller._createTypeMethod(module.types[i]); + } + }, + + /** + */ + + 'router': function(expr) + { + for(var i = this._middleware.length; i--;) + { + //get the factory name. some middleware may return different routers depending on the expression metadata, such as pull -multi + var mw = this._middleware[i], name = mw.test(expr); + + if(name) return this._router(mw, name); + } + + return null; + }, + + /** + */ + + '_router': function(tester, name) + { + return this._routers[ name ] || this._newRouter(tester, name); + }, + + /** + */ + + '_newRouter': function(tester, name) + { + var router = tester.newRouter(name); + + router.type = name; + router.controller = this._controller; + + this._routers[ name ] = router; + + return router; + } +}); + diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/index.js new file mode 100644 index 0000000..7554036 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/index.js @@ -0,0 +1,19 @@ +var Router = require('../../../../concrete/router'), +Request = require('./request'); + +exports.types = ['pull','pullMulti']; + +exports.test = function(expr) +{ + if(expr.type == 'pullMulti') return 'pullMulti'; + return expr.type == 'pull' ? (expr.meta && expr.meta.multi ? 'pullMulti' : 'pull') : null; +} + +exports.newRouter = function(type) +{ + var ops = { RequestClass: Request }; + + if(type == 'pullMulti') ops.multi = true; + + return new Router(ops); +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/request.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/request.js new file mode 100644 index 0000000..1b3ecf5 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/pull/request.js @@ -0,0 +1,45 @@ +var Request = require('../request'), + Structr = require('structr'); + + +var PullRequest = Request.extend({ + + /** + */ + + 'override init': function() + { + this._super(); + + this._listen(this.callback, this.meta); + + return this; + }, + + /** + */ + + 'override _callback': function() + { + var ret = this._super.apply(this, arguments); + + if(ret != undefined) + { + if(ret == true) + { + } + + if(ret.send) + { + ret.send(this); + } + else + { + this.end(ret); + } + } + } +}); + + +module.exports = PullRequest; diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/index.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/index.js new file mode 100644 index 0000000..4316c1f --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/index.js @@ -0,0 +1,14 @@ +var Router = require('./router'), +PushRequest = require('./request'); + +exports.types = ['push']; + +exports.test = function(expr) +{ + return expr.type == 'push' ? 'push' : null; +} + +exports.newRouter = function() +{ + return new Router({ multi: true, RequestClass: PushRequest }); +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/request.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/request.js new file mode 100644 index 0000000..363a562 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/request.js @@ -0,0 +1,30 @@ +var Stream = require('../stream'), + PushPullRequest = require('../request'); + + +var PushRequest = PushPullRequest.extend({ + + /** + */ + + 'override init': function() + { + this._super(); + + this.cache(); + this.stream.pipe(this); + + + return this; + }, + + /** + */ + + 'override _callback': function(route, data) + { + this._listen(route.callback, route.meta || {}); + } +}); + +module.exports = PushRequest; diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/router.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/router.js new file mode 100644 index 0000000..5f38709 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/push/router.js @@ -0,0 +1,63 @@ +var Router = require('../../../../concrete/router'), +Stream = require('../stream'), +utils = require('../../../../concrete/utils'), +Structr = require('structr'); + + +var PushRouter = Router.extend({ + + /** + */ + + 'override on': function(expr, ops, callback) + { + if(!callback) + { + callback = ops; + ops = {}; + } + + var ret = this._super(expr, ops, callback); + + + if(expr.meta.pull) + { + this.controller.pull(expr, Structr.copy(ops.data), { ignoreWarning: true }, callback); + } + + return ret; + }, + + /** + */ + + 'override _callListeners': function(ops) + { + + //the stream for pushing content. must be cached incase there's latency. + var stream = new Stream(true), + + //no callback? then data's just being pushed, which is okay + callback = ops.callback || function(stream) + { + return ops.data; + } + + //of there's a callback, it can return a value which is pushed to the stream + var ret = callback(stream); + + //IF there's a value, then we're done + if(ret != undefined) + { + stream.end(ret); + } + + //make the stream visible to all listeners + ops.stream = stream; + + //SHIBLAM. call the listeners ;) + this._super.apply(this, arguments); + } +}); + +module.exports = PushRouter; diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/request.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/request.js new file mode 100644 index 0000000..326cb9a --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/request.js @@ -0,0 +1,88 @@ +var Request = require('../../../concrete/request'), +Stream = require('./stream'), +Structr = require('structr'); + +/** + */ + +var PushPullRequest = Request.extend(Structr.copy(Stream.proto, { + + /** + */ + + 'init': function() + { + this._init(); + + return this; + }, + + /** + */ + + '_listen': function(listener, meta) + { + //because the framework needs to be easy to use, streams are turned off by default. This + //would be a huge pain in the pass if every time they're required, but they're SUPER important + //if we're trying to stream a large amount of data. What about HTTP? So if it's false, we need to + //add a stream handler. + if(!meta.stream) + { + //the buffer for the streams + var buffer = [], self = this; + + function end(err) + { + if(err) return; + + //again, it would be a pain in the ass if everytimg we have to do: var value = response[0]. So + //a "batch" must be specified if we're expecting an array, because 99% of the time for in-app route handling, + //only ONE value will be returned. + if(meta.batch) + { + listener.call(self, buffer, err, self); + } + else + { + if(!buffer.length) + { + listener(); + } + else + //so again, by default callback the listener as many times as there are batch values + for(var i = 0, n = buffer.length; i < n; i++) + { + listener.call(self, buffer[i], err, self); + } + } + } + + this.pipe({ + + + //on write, throw the data into the buffer + write: function(data) + { + buffer.push(data); + }, + + error: end, + + //on end, callback the listener + end: end + }); + } + + //is the listener expecting a stream? Okay, then pass on the writer to the listener. Only use this for files, http requests, and the + //likes plz, omg you're code would look like shit otherwise >.> + else + { + //more flavor picking. Use this, or the passed obj + listener.call(this, this); + } + } +})); + + + +module.exports = PushPullRequest; diff --git a/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/stream.js b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/stream.js new file mode 100644 index 0000000..d373ec5 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/core/middleware/route/pushPull/stream.js @@ -0,0 +1,209 @@ +var Structr = require('structr'), +EventEmitter = require('sk/core/events').EventEmitter; + +/** + the bridge between the listener, and responder. Yeah, Yeah. the listener +94 */ + +var proto = { + + /** + */ + + '_init': function(ttl) + { + this._em = new EventEmitter(); + + this.response = {}; + + if(ttl) + { + this.cache(ttl); + } + }, + + /** + */ + + 'cache': function(ttl) + { + if(this._caching) return; + this._caching = true; + + + //store the buffer incase data comes a little quicker than we can handle it. + var buffer = this._buffer = [], self = this; + + this.on({ + write: function(chunk) + { + buffer.push(chunk) + } + }); + }, + + /** + */ + + 'on': function(listeners) + { + for(var type in listeners) + { + this._em.addListener(type, listeners[type]); + } + }, + + + /** + */ + + 'second on': function(type, callback) + { + this._em.addListener(type, callback); + }, + + /** + */ + + 'respond': function(data) + { + this.responded = true; + + Structr.copy(data, this.response, true); + + return this; + }, + + /** + */ + + 'error': function(data) + { + if(!data) return this._error; + this._error = data; + this._em.emit('error', data); + return this; + }, + + /** + */ + + '_sendResponse': function() + { + if(!this._sentResponse) + { + this._sentResponse = true; + + //WHOOAAHH, what are you doing!? Okay, I know it looks stupid, it is. BUT, consider this scenario: + //via HTTP, the session object is *saved* to the database once toJSON is called, which is ONLY called when *this* happens. We do not want + //the session to save before we're done writing to it, or handling it. + this.response = JSON.parse(JSON.stringify(this.response)); + + this._em.emit('response', this.response); + + return true; + } + + return false; + }, + + /** + */ + + + 'write': function(data) + { + this._sendResponse(); + + this._em.emit('write', data); + + return this; + }, + + /** + */ + + 'end': function(data) + { + //SUPER NOTE: end can be called *once*. After that, all the listeners are disposed of + if(data) this.write(data); + + this._sendResponse(); + + this.finished = true; + + this._em.emit('end', data); + + //remove the event listeners to avoid mem leaks + this._em.dispose(); + + return this; + }, + + /** + */ + + 'pipe': function(stream) + { + + //IF there is a buffer, that means it came faster than we can handle it. This sort of thing + //occurrs when there are pass-thru routes which hold up the final callback. e.g: authenticating a user against + //a database + // if(stream.response) stream.response = this.response; + + if(stream.respond && this.responded) stream.respond(this.response); + + if(this._buffer && this._buffer.length) + { + for(var i = 0, n = this._buffer.length; i < n; i++) + { + stream.write(this._buffer[i]); + } + } + + //already finished? return + if(this.finished) + { + return stream.end(); + } + + //looks like the bridge is still handling data, so listen for the rest + this.on({ + write: function(data) + { + if(stream.write) stream.write(data); + }, + end: function() + { + if(stream.end) stream.end(); + }, + error: function(e) + { + if(stream.error) stream.error(e); + }, + response: function(data) + { + if(stream.respond) stream.respond(data); + } + }); + } +}; + +var Stream = Structr(Structr.copy(proto, { + + /** + * @param the current request + * @param ttl time to keep cached version in memory before dumping it + */ + + '__construct': function(ttl) + { + this._init(ttl); + } + +})); + +Stream.proto = proto; + + +module.exports = Stream; \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/node/beans/system.core/index.js b/node_modules/celeri/node_modules/beanpole/lib/node/beans/system.core/index.js new file mode 100644 index 0000000..d1ebe48 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/node/beans/system.core/index.js @@ -0,0 +1,26 @@ +var exec = require('child_process').exec; + +exports.plugin = function(router) +{ + + router.on({ + + /** + */ + + 'push init': function() + { + exec('hostname', function(err, hostname) + { + router.on('pull hostname', function() + { + return hostname; + }); + + router.push('hostname', hostname.replace('\n','')); + }); + }, + + + }) +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/node/index.js b/node_modules/celeri/node_modules/beanpole/lib/node/index.js new file mode 100644 index 0000000..4a0eae2 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/node/index.js @@ -0,0 +1,21 @@ +require('sk/node/log'); + +//need this for global beanpole ~ not cached with NPM. +if(global.beanpole) +{ + module.exports = global.beanpole; +} +else +{ + var Loader = require('./loader'); + + exports.router = function() + { + return new Loader(); + } + + + exports.router().copyTo(module.exports, true); + + global.beanpole = module.exports; +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/lib/node/loader.js b/node_modules/celeri/node_modules/beanpole/lib/node/loader.js new file mode 100644 index 0000000..98f8eed --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/node/loader.js @@ -0,0 +1,171 @@ +var Structr = require('structr'), +Loader = require('../core/loader'), +fs = require('fs'), +pt = require('path'); + +//let coffeescript inject require hooks +require('coffee-script'); + +function unableToLoad(bean) +{ + console.error('Unable to load bean "%s"', bean); +} + + +//replaces relative paths, with abs paths for beans. Primarily used for the package.json +//config +function replaceRelWithAbsPath(config, cwd) +{ + for(var property in config) + { + var value = config[property]; + + if(typeof value == 'string' && value.substr(0,2) == './') + { + config[property] = fs.realpathSync(cwd+value.substr(1)); + } + else + if(value instanceof Object) + { + replaceRelWithAbsPath(value, cwd); + } + } + + + return config; +} + + +//quick, temporary fix for node > 5.x. breaks +try +{ + require.paths.unshift(__dirname + '/beans'); +} +catch(e) +{ + +} +var NodeLoader = Loader.extend({ + + /** + */ + + + 'override __construct': function() + { + this._super(); + + this._loaded = []; + }, + + /** + */ + + 'override _require': function(source) + { + if(!this._super(source)) + { + if(typeof source == 'object') + { + for(var bean in source) + { + this._require2(bean).plugin(this, source[bean]); + } + } + else + if(typeof source == 'string') + { + var bean, self = this, basename = pt.basename(source); + + + if(basename == 'package.json') + { + var pkg = JSON.parse(fs.readFileSync(source, 'utf8')); + + for(var bean in pkg.beans) + { + var params = pkg.beans[bean], + plugin = self._require2(bean); + + + if(!plugin) + { + unableToLoad(bean); + continue; + } + + + plugin.plugin(self, replaceRelWithAbsPath(typeof params != 'boolean' ? params : self._params[bean] || {}, pt.dirname(source))); + } + } + else + if(!(bean = this._require2(source))) + { + try + { + + //NOT a bean, but a directory for the beans. + fs.readdirSync(source).forEach(function(name) + { + //hidden file + if(name.substr(0,1) == '.') return; + + self._require2(source + '/' + name).plugin(self, self._params[name] || {}); + }); + } + catch(e) + { + console.log(e.stack) + console.warn('Unable to load beans from directory %s', source); + unableToLoad(source); + } + } + else + { + bean.plugin(this, self._params[source.split('/').pop()] || {}); + } + } + else + { + return false; + } + + return this; + } + + //this gets hit if old require is true + return this; + }, + + /** + */ + + '_require2': function(bean) + { + try + { + var path = require.resolve(bean); + } + catch(e) + { + return false; + } + + var ret = require(bean), + name = pt.dirname(path).split('/').pop(); + + + if(this._loaded.indexOf(path) > -1) + { + console.notice('Cannot reload bean "%s"', bean); + + return { plugin: function() {} }; + } + + this._loaded.push(path); + + return ret; + } +}); + +module.exports = NodeLoader; diff --git a/node_modules/celeri/node_modules/beanpole/lib/web/index.js b/node_modules/celeri/node_modules/beanpole/lib/web/index.js new file mode 100644 index 0000000..36572d8 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/lib/web/index.js @@ -0,0 +1 @@ +module.exports = require('../core') \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/package.json b/node_modules/celeri/node_modules/beanpole/package.json new file mode 100644 index 0000000..21e4b72 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/package.json @@ -0,0 +1,25 @@ +{ + "name": "beanpole", + "description": "Routing on Steroids", + "version": "0.1.16", + "author": "Craig Condon", + "repository": { + "type": "git", + "url": "http://github.com/crcn/beanpole.git" + }, + "directories" : { "lib" : "./lib" }, + "dependencies": { + "sk":"*", + "vine":"*", + "mime":"*", + "gumbo":"*", + "cashew":"*", + "structr":"*", + "coffee-script":"*" + }, + "devDependencies": { + "ebnf-diagram":"*" + }, + + "main": "./lib/node/index.js" +} diff --git a/node_modules/celeri/node_modules/beanpole/project.sublime-project b/node_modules/celeri/node_modules/beanpole/project.sublime-project new file mode 100644 index 0000000..00dbc17 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/project.sublime-project @@ -0,0 +1,23 @@ +{ + "folders": + [ + { + "path": "." + } + ], + "build_systems": + [ + { + "name":"cbd make", + "cmd":["cbd","make","beanpole"] + }, + { + "name":"cbd start", + "cmd":["cbd","start","beanpole"] + }, + { + "name":"cbd make+start", + "cmd":["cbd","make+start","beanpole"] + } + ] +} \ No newline at end of file diff --git a/node_modules/celeri/node_modules/beanpole/project.tmproj b/node_modules/celeri/node_modules/beanpole/project.tmproj new file mode 100644 index 0000000..ff44ef4 --- /dev/null +++ b/node_modules/celeri/node_modules/beanpole/project.tmproj @@ -0,0 +1,168 @@ + + + + + currentDocument + lib/core/concrete/router.js + documents + + + expanded + + name + project + regexFolderFilter + !.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$ + sourceDirectory + + + + fileHierarchyDrawerWidth + 200 + metaData + + MIT-LICENSE.txt + + caret + + column + 61 + line + 10 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + docs/beans/README.md + + caret + + column + 8 + line + 43 + + columnSelection + + firstVisibleColumn + 0 + firstVisibleLine + 0 + selectFrom + + column + 2 + line + 43 + + selectTo + + column + 8 + line + 43 + + + examples/ws/client/release/index.js + + caret + + column + 0 + line + 1232 + + firstVisibleColumn + 0 + firstVisibleLine + 1216 + + lib/core/concrete/router.js + + caret + + column + 7 + line + 266 + + firstVisibleColumn + 0 + firstVisibleLine + 234 + + lib/core/controller.js + + caret + + column + 4 + line + 9 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/index.js + + caret + + column + 0 + line + 0 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/loader.js + + caret + + column + 1 + line + 7 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + lib/core/middleware/route/pushPull/push/router.js + + caret + + column + 4 + line + 9 + + firstVisibleColumn + 0 + firstVisibleLine + 17 + + + openDocuments + + MIT-LICENSE.txt + docs/beans/README.md + examples/ws/client/release/index.js + lib/core/controller.js + lib/core/loader.js + lib/core/concrete/router.js + lib/core/index.js + + showFileHierarchyDrawer + + windowFrame + {{210, 4}, {1230, 874}} + + diff --git a/node_modules/celeri/node_modules/colors/MIT-LICENSE.txt b/node_modules/celeri/node_modules/colors/MIT-LICENSE.txt new file mode 100644 index 0000000..7df0d5e --- /dev/null +++ b/node_modules/celeri/node_modules/colors/MIT-LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2010 Alexis Sellier (cloudhead) , Marak Squires + +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. \ No newline at end of file diff --git a/node_modules/celeri/node_modules/colors/ReadMe.md b/node_modules/celeri/node_modules/colors/ReadMe.md new file mode 100644 index 0000000..74acead --- /dev/null +++ b/node_modules/celeri/node_modules/colors/ReadMe.md @@ -0,0 +1,30 @@ +

colors.js - get color and style in your node.js console like what

+ + + + var sys = require('sys'); + var colors = require('./colors'); + + sys.puts('hello'.green); // outputs green text + sys.puts('i like cake and pies'.underline.red) // outputs red underlined text + sys.puts('inverse the color'.inverse); // inverses the color + sys.puts('OMG Rainbows!'.rainbow); // rainbow (ignores spaces) + +

colors and styles!

+- bold +- italic +- underline +- inverse +- yellow +- cyan +- white +- magenta +- green +- red +- grey +- blue + + +### Authors + +#### Alexis Sellier (cloudhead) , Marak Squires , Justin Campbell, Dustin Diaz (@ded) diff --git a/node_modules/celeri/node_modules/colors/colors.js b/node_modules/celeri/node_modules/colors/colors.js new file mode 100644 index 0000000..8c1d706 --- /dev/null +++ b/node_modules/celeri/node_modules/colors/colors.js @@ -0,0 +1,230 @@ +/* +colors.js + +Copyright (c) 2010 Alexis Sellier (cloudhead) , Marak Squires + +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. + +*/ + +exports.mode = "console"; + +// prototypes the string object to have additional method calls that add terminal colors + +var addProperty = function (color, func) { + exports[color] = function(str) { + return func.apply(str); + }; + String.prototype.__defineGetter__(color, func); +} + +var isHeadless = (typeof module !== 'undefined'); +['bold', 'underline', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta'].forEach(function (style) { + + // __defineGetter__ at the least works in more browsers + // http://robertnyman.com/javascript/javascript-getters-setters.html + // Object.defineProperty only works in Chrome + addProperty(style, function () { + return isHeadless ? + stylize(this, style) : // for those running in node (headless environments) + this.replace(/( )/, '$1'); // and for those running in browsers: + // re: ^ you'd think 'return this' works (but doesn't) so replace coerces the string to be a real string + }); +}); + +// prototypes string with method "rainbow" +// rainbow will apply a the color spectrum to a string, changing colors every letter +addProperty('rainbow', function () { + if (!isHeadless) { + return this.replace(/( )/, '$1'); + } + var rainbowcolors = ['red','yellow','green','blue','magenta']; //RoY G BiV + var exploded = this.split(""); + var i=0; + exploded = exploded.map(function(letter) { + if (letter==" ") { + return letter; + } + else { + return stylize(letter,rainbowcolors[i++ % rainbowcolors.length]); + } + }); + return exploded.join(""); +}); + +function stylize(str, style) { + if (exports.mode == 'console') { + var styles = { + //styles + 'bold' : ['\033[1m', '\033[22m'], + 'italic' : ['\033[3m', '\033[23m'], + 'underline' : ['\033[4m', '\033[24m'], + 'inverse' : ['\033[7m', '\033[27m'], + //grayscale + 'white' : ['\033[37m', '\033[39m'], + 'grey' : ['\033[90m', '\033[39m'], + 'black' : ['\033[30m', '\033[39m'], + //colors + 'blue' : ['\033[34m', '\033[39m'], + 'cyan' : ['\033[36m', '\033[39m'], + 'green' : ['\033[32m', '\033[39m'], + 'magenta' : ['\033[35m', '\033[39m'], + 'red' : ['\033[31m', '\033[39m'], + 'yellow' : ['\033[33m', '\033[39m'] + }; + } else if (exports.mode == 'browser') { + var styles = { + //styles + 'bold' : ['', ''], + 'italic' : ['', ''], + 'underline' : ['', ''], + 'inverse' : ['', ''], + //grayscale + 'white' : ['', ''], + 'grey' : ['', ''], + 'black' : ['', ''], + //colors + 'blue' : ['', ''], + 'cyan' : ['', ''], + 'green' : ['', ''], + 'magenta' : ['', ''], + 'red' : ['', ''], + 'yellow' : ['', ''] + }; + } else if (exports.mode == 'none') { + return str; + } else { + console.log('unsupported mode, try "browser", "console" or "none"'); + } + + return styles[style][0] + str + styles[style][1]; +}; + +// don't summon zalgo +addProperty('zalgo', function () { + return zalgo(this); +}); + +// please no +function zalgo(text, options) { + var soul = { + "up" : [ + '̍','̎','̄','̅', + '̿','̑','̆','̐', + '͒','͗','͑','̇', + '̈','̊','͂','̓', + '̈','͊','͋','͌', + '̃','̂','̌','͐', + '̀','́','̋','̏', + '̒','̓','̔','̽', + '̉','ͣ','ͤ','ͥ', + 'ͦ','ͧ','ͨ','ͩ', + 'ͪ','ͫ','ͬ','ͭ', + 'ͮ','ͯ','̾','͛', + '͆','̚' + ], + "down" : [ + '̖','̗','̘','̙', + '̜','̝','̞','̟', + '̠','̤','̥','̦', + '̩','̪','̫','̬', + '̭','̮','̯','̰', + '̱','̲','̳','̹', + '̺','̻','̼','ͅ', + '͇','͈','͉','͍', + '͎','͓','͔','͕', + '͖','͙','͚','̣' + ], + "mid" : [ + '̕','̛','̀','́', + '͘','̡','̢','̧', + '̨','̴','̵','̶', + '͜','͝','͞', + '͟','͠','͢','̸', + '̷','͡',' ҉' + ] + }, + all = [].concat(soul.up, soul.down, soul.mid), + zalgo = {}; + + function randomNumber(range) { + r = Math.floor(Math.random()*range); + return r; + }; + + function is_char(character) { + var bool = false; + all.filter(function(i){ + bool = (i == character); + }); + return bool; + } + + function heComes(text, options){ + result = ''; + options = options || {}; + options["up"] = options["up"] || true; + options["mid"] = options["mid"] || true; + options["down"] = options["down"] || true; + options["size"] = options["size"] || "maxi"; + var counts; + text = text.split(''); + for(var l in text){ + if(is_char(l)) { continue; } + result = result + text[l]; + + counts = {"up" : 0, "down" : 0, "mid" : 0}; + + switch(options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.min= randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.min = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down= randomNumber(8) + 1; + break; + } + + var arr = ["up", "mid", "down"]; + for(var d in arr){ + var index = arr[d]; + for (var i = 0 ; i <= counts[index]; i++) + { + if(options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + }; + return heComes(text); +} + +addProperty('stripColors', function() { + return ("" + this).replace(/\u001b\[\d+m/g,''); +}); diff --git a/node_modules/celeri/node_modules/colors/example.html b/node_modules/celeri/node_modules/colors/example.html new file mode 100644 index 0000000..c9cd68c --- /dev/null +++ b/node_modules/celeri/node_modules/colors/example.html @@ -0,0 +1,20 @@ + + + + + Colors Example + + + + + + + \ No newline at end of file diff --git a/node_modules/celeri/node_modules/colors/example.js b/node_modules/celeri/node_modules/colors/example.js new file mode 100644 index 0000000..12d8b1a --- /dev/null +++ b/node_modules/celeri/node_modules/colors/example.js @@ -0,0 +1,20 @@ +var util = require('util'); +var colors = require('./colors'); + +//colors.mode = "browser"; + +var test = colors.red("hopefully colorless output"); +util.puts('Rainbows are fun!'.rainbow); +util.puts('So '.italic + 'are'.underline + ' styles! '.bold + 'inverse'.inverse); // styles not widely supported +util.puts('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported +//util.puts('zalgo time!'.zalgo); +util.puts(test.stripColors); +util.puts("a".grey + " b".black); + +util.puts(colors.rainbow('Rainbows are fun!')); +util.puts(colors.italic('So ') + colors.underline('are') + colors.bold(' styles! ') + colors.inverse('inverse')); // styles not widely supported +util.puts(colors.bold(colors.italic(colors.underline(colors.red('Chains are also cool.'))))); // styles not widely supported +//util.puts(colors.zalgo('zalgo time!')); +util.puts(colors.stripColors(test)); +util.puts(colors.grey("a") + colors.black(" b")); + diff --git a/node_modules/celeri/node_modules/colors/package.json b/node_modules/celeri/node_modules/colors/package.json new file mode 100644 index 0000000..8fffef5 --- /dev/null +++ b/node_modules/celeri/node_modules/colors/package.json @@ -0,0 +1,14 @@ +{ + "name": "colors", + "description": "get colors in your node.js console like what", + "version": "0.5.1", + "author": "Marak Squires", + "repository": { + "type": "git", + "url": "http://github.com/Marak/colors.js.git" + }, + "engines": { + "node": ">=0.1.90" + }, + "main": "colors" +} diff --git a/node_modules/celeri/node_modules/structr/package.json b/node_modules/celeri/node_modules/structr/package.json new file mode 100644 index 0000000..95d53c7 --- /dev/null +++ b/node_modules/celeri/node_modules/structr/package.json @@ -0,0 +1,11 @@ +{ + "name": "structr", + "description": "Clean OO structure for Javascript.", + "version": "0.0.10", + "author": "Craig Condon", + "repository": { + "type": "git", + "url": "http://github.com/spiceapps/Structr.git" + }, + "main": "./structr.js" +} diff --git a/node_modules/celeri/node_modules/structr/structr.js b/node_modules/celeri/node_modules/structr/structr.js new file mode 100644 index 0000000..7a8ffa7 --- /dev/null +++ b/node_modules/celeri/node_modules/structr/structr.js @@ -0,0 +1,488 @@ +var Structr = function (target, parent) +{ + if (!parent) parent = Structr.fh({}); + + var that = Structr.extend.apply(null, [parent].concat(target)) + + that.__construct.prototype = that; + + if(!that.__construct.extend) + //allow for easy extending. + that.__construct.extend = function() + { + return Structr(Structr.argsToArray(arguments), that); + }; + + //return the constructor + return that.__construct; +}; + + +Structr.argsToArray = function(args) +{ + var ar = new Array(args.length); + for(var i = args.length; i--;) ar[i] = args[i]; + return ar; +} + +Structr.copy = function (from, to, lite) +{ + if(typeof to == 'boolean') + { + lite = to; + to = undefined; + } + + if (!to) to = from instanceof Array ? [] : {}; + + var i; + + for(i in from) + { + var fromValue = from[i], + toValue = to[i], + newValue; + + //don't copy anything fancy other than objects and arrays. this could really screw classes up, such as dates.... (yuck) + if (!lite && typeof fromValue == 'object' && (!fromValue || fromValue.__proto__ == Object.prototype || fromValue.__proto__ == Array.prototype)) + { + + //if the toValue exists, and the fromValue is the same data type as the TO value, then + //merge the FROM value with the TO value, instead of replacing it + if (toValue && fromValue instanceof toValue.constructor) + { + newValue = toValue; + } + + //otherwise replace it, because FROM has priority over TO + else + { + newValue = fromValue instanceof Array ? [] : {}; + } + + Structr.copy(fromValue, newValue); + } + else + { + newValue = fromValue; + } + + to[i] = newValue; + } + + return to; +}; + + +//returns a method owned by an object +Structr.getMethod = function (that, property) +{ + return function() + { + return that[property].apply(that, arguments); + }; +}; + +Structr.wrap = function(that, prop) +{ + if(that._wrapped) return that; + + that._wrapped = true; + + function wrap(target) + { + return function() + { + return target.apply(that, arguments); + } + } + + if(prop) + { + that[prop] = wrap(target[prop]); + return that; + } + + for(var property in that) + { + var target = that[property]; + + if(typeof target == 'function') + { + that[property] = wrap(target); + } + } + + return that; +} + +//finds all properties with modifiers +Structr.findProperties = function (target, modifier) +{ + var props = [], + property; + + for(property in target) + { + var v = target[property]; + + if (v && v[modifier]) + { + props.push(property); + } + } + + return props; +}; + +Structr.nArgs = function(func) +{ + var inf = func.toString().replace(/\{[\W\S]+\}/g, '').match(/\w+(?=[,\)])/g); + return inf ? inf.length :0; +} + +Structr.getFuncsByNArgs = function(that, property) +{ + return that.__private['overload::' + property] || (that.__private['overload::' + property] = {}); +} + +Structr.getOverloadedMethod = function(that, property, nArgs) +{ + var funcsByNArgs = Structr.getFuncsByNArgs(that, property); + + return funcsByNArgs[nArgs]; +} + +Structr.setOverloadedMethod = function(that, property, func, nArgs) +{ + var funcsByNArgs = Structr.getFuncsByNArgs(that, property); + + if(func.overloaded) return funcsByNArgs; + + funcsByNArgs[nArgs || Structr.nArgs(func)] = func; + + return funcsByNArgs; +} + +//modifies how properties behave in a class +Structr.modifiers = { + + /** + * overrides given method + */ + + m_override: function (that, property, newMethod) + { + var oldMethod = (that.__private && that.__private[property]) || that[property] || function (){}, + parentMethod = oldMethod; + + if(oldMethod.overloaded) + { + var overloadedMethod = oldMethod, + nArgs = Structr.nArgs(newMethod); + parentMethod = Structr.getOverloadedMethod(that, property, nArgs); + } + + //wrap the method so we can access the parent overloaded function + var wrappedMethod = function () + { + this._super = parentMethod; + var ret = newMethod.apply(this, arguments); + delete this._super; + return ret; + } + + if(oldMethod.overloaded) + { + return Structr.modifiers.m_overload(that, property, wrappedMethod, nArgs); + } + + return wrappedMethod; + }, + + + /** + * getter / setter which are physical functions: e.g: test.myName(), and test.myName('craig') + */ + + m_explicit: function (that, property, gs) + { + var pprop = '__'+property; + + //if GS is not defined, then set defaults. + if (typeof gs != 'object') + { + gs = {}; + } + + if (!gs.get) + gs.get = function () + { + return this._value; + } + + if (!gs.set) + gs.set = function (value) + { + this._value = value; + } + + + return function (value) + { + //getter + if (!arguments.length) + { + this._value = this[pprop]; + var ret = gs.get.apply(this); + delete this._value; + return ret; + } + + //setter + else + { + //don't call the gs if the value isn't the same + if (this[pprop] == value ) + return; + + //set the current value to the setter value + this._value = this[pprop]; + + //set + gs.set.apply(this, [value]); + + //set the new value. this only matters if the setter set it + this[pprop] = this._value; + } + }; + }, + + /** + */ + + m_implicit: function (that, property, egs) + { + //keep the original function available so we can override it + that.__private[property] = egs; + + that.__defineGetter__(property, egs); + that.__defineSetter__(property, egs); + }, + + /** + */ + + m_overload: function (that, property, value, nArgs) + { + var funcsByNArgs = Structr.setOverloadedMethod(that, property, value, nArgs); + + var multiFunc = function() + { + var func = funcsByNArgs[arguments.length]; + + if(func) + { + return funcsByNArgs[arguments.length].apply(this, arguments); + } + else + { + var expected = []; + + for(var sizes in funcsByNArgs) + { + expected.push(sizes); + } + + throw new Error('Expected '+expected.join(',')+' parameters, got '+arguments.length+'.'); + } + } + + multiFunc.overloaded = true; + + return multiFunc; + } +} + + +//extends from one class to another. note: the TO object should be the parent. a copy is returned. +Structr.extend = function () +{ + var from = arguments[0], + to = {}; + + for(var i = 1, n = arguments.length; i < n; i++) + { + var obj = arguments[i]; + + Structr.copy(obj instanceof Function ? obj() : obj, to); + } + + + var that = { + __private: { + + //contains modifiers for all properties of object + propertyModifiers: {} + } + }; + + + Structr.copy(from, that); + + var usedProperties = {}, + property; + + for(property in to) + { + var value = to[property]; + + + var propModifiersAr = property.split(' '), //property is at the end of the modifiers. e.g: override bindable testProperty + propertyName = propModifiersAr.pop(), + + modifierList = that.__private.propertyModifiers[propertyName] || (that.__private.propertyModifiers[propertyName] = []); + + + if (propModifiersAr.length) + { + var propModifiers = {}; + for(var i = propModifiersAr.length; i--;) + { + var modifier = propModifiersAr[i]; + + propModifiers['m_' + propModifiersAr[i]] = 1; + + if (modifierList.indexOf(modifier) == -1) + { + modifierList.push(modifier); + } + } + + if(propModifiers.m_merge) + { + value = Structr.copy(from[propertyName], value); + } + + //if explicit, or implicit modifiers are set, then we need an explicit modifier first + if (propModifiers.m_explicit || propModifiers.m_implicit) + { + value = Structr.modifiers.m_explicit(that, propertyName, value); + } + + if (propModifiers.m_override) + { + value = Structr.modifiers.m_override(that, propertyName, value); + } + + if (propModifiers.m_implicit) + { + //getter is set, don't continue. + Structr.modifiers.m_implicit(that, propertyName, value); + continue; + } + } + + for(var j = modifierList.length; j--;) + { + value[modifierList[j]] = true; + } + + if(usedProperties[propertyName]) + { + var oldValue = that[propertyName]; + + //first property will NOT be overloaded, so we need to check it here + if(!oldValue.overloaded) Structr.modifiers.m_overload(that, propertyName, oldValue, undefined); + + value = Structr.modifiers.m_overload(that, propertyName, value, undefined); + } + + usedProperties[propertyName] = 1; + + that.__private[propertyName] = that[propertyName] = value; + } + + //if the parent constructor exists, and the child constructor IS the parent constructor, it means + //the PARENT constructor was defined, and the CHILD constructor wasn't, so the parent prop was copied over. We need to create a new function, and + //call the parent constructor when the child is instantiated, otherwise it'll be the same class essentially (setting proto) + if (that.__construct && from.__construct && that.__construct == from.__construct) + { + that.__construct = Structr.modifiers.m_override(that, '__construct', function() + { + this._super.apply(this, arguments); + }); + } + else + if(!that.__construct) + { + that.__construct = function() {}; + } + + + //copy + for(var property in from.__construct) + { + if(from.__construct[property]['static'] && !that[property]) + { + that.__construct[property] = from.__construct[property]; + } + } + + + var propertyName; + + //apply the static props + for(propertyName in that) + { + var value = that[propertyName]; + + //if the value is static, then tack it onto the constructor + if (value && value['static']) + { + that.__construct[propertyName] = value; + delete that[propertyName]; + } + } + + + + return that; +} + + +//really.. this isn't the greatest idea if a LOT of objects +//are being allocated in a short perioud of time. use the closure +//method instead. This is great for objects which are instantiated ONCE, or a couple of times :P. +Structr.fh = function (that) +{ + that = Structr.extend({}, that); + + //deprecated + that.getMethod = function (property) + { + return Structr.getMethod(this, property); + } + + that.extend = function () + { + return Structr.extend.apply(null, [this].concat(arguments)) + } + + //copy to target object + that.copyTo = function (target, lite) + { + Structr.copy(this, target, lite); + } + + //wraps the objects methods so this always points to the right place + that.wrap = function(property) + { + return Structr.wrap(this, property); + } + + return that; +} + +module.exports = Structr; + diff --git a/node_modules/celeri/node_modules/structr/structr.min.js b/node_modules/celeri/node_modules/structr/structr.min.js new file mode 100644 index 0000000..930f670 --- /dev/null +++ b/node_modules/celeri/node_modules/structr/structr.min.js @@ -0,0 +1,8 @@ +var Structr=function(a,c){c||(c=Structr.fh({}));var b=Structr.extend(c,a);if(!b.__construct)b.__construct=function(){};b.__construct.prototype=b;b.__construct.extend=function(a){return Structr(a,b)};return b.__construct};Structr.copy=function(a,c){c||(c={});for(var b in a){var d=a[b],e=c[b];typeof d=="object"?(e=e&&d instanceof e.constructor?e:d instanceof Array?[]:{},Structr.copy(d,e)):e=d;c[b]=e}return c};Structr.getMethod=function(a,c){return function(){return a[c].apply(a,arguments)}}; +Structr.findProperties=function(a,c){var b=[],d;for(d in a){var e=a[d];e&&e[c]&&b.push(d)}return b};Structr.getNArgs=function(a){return(a=a.toString().replace(/\{[\W\S]+\}/g,"").match(/\w+(?=[,\)])/g))?a.length:0};Structr.getFuncsByNArgs=function(a,c){return a.__private["overload::"+c]||(a.__private["overload::"+c]={})};Structr.getOverloadedMethod=function(a,c,b){return Structr.getFuncsByNArgs(a,c)[b]}; +Structr.setOverloadedMethod=function(a,c,b,d){a=Structr.getFuncsByNArgs(a,c);if(b.overloaded)return a;a[d||Structr.getNArgs(b)]=b;return a}; +Structr.modifiers={m_override:function(a,c,b){var d=a.__private&&a.__private[c]||a[c]||function(){},e=d;if(d.overloaded)var g=Structr.getNArgs(b),e=Structr.getOverloadedMethod(a,c,g);var h=function(){this._super=e;var a=b.apply(this,arguments);delete this._super;return a};if(d.overloaded)return Structr.modifiers.m_overload(a,c,h,g);return h},m_explicit:function(a,c,b){var d="_gs::"+c;typeof b!="object"&&(b={});if(!b.get)b.get=function(){return this._value};if(!b.set)b.set=function(b){this._value= +b};return function(a){if(arguments.length){if(this[d]!=a)this._value=this[d],b.set.apply(this,[a]),this[d]=this._value}else{this._value=this[d];var c=b.get.apply(this);delete this._value;return c}}},m_implicit:function(a,c,b){a.__private[c]=b;a.__defineGetter__(c,b);a.__defineSetter__(c,b)},m_overload:function(a,c,b,d){var e=Structr.setOverloadedMethod(a,c,b,d),a=function(){return e[arguments.length].apply(this,arguments)};a.overloaded=!0;return a}}; +Structr.extend=function(a,c){c||(c={});var b={__private:{propertyModifiers:{}}};c instanceof Function&&(c=c());Structr.copy(a,b);var d={},e;for(e in c){var g=c[e],h=e.split(" "),f=h.pop(),i=b.__private.propertyModifiers[f]||(b.__private.propertyModifiers[f]=[]);if(h.length){for(var j={},k=h.length;k--;){var l=h[k];j["m_"+h[k]]=1;i.indexOf(l)==-1&&i.push(l)}if(j.m_explicit||j.m_implicit)g=Structr.modifiers.m_explicit(b,f,g);j.m_override&&(g=Structr.modifiers.m_override(b,f,g));if(j.m_implicit){Structr.modifiers.m_implicit(b, +f,g);continue}}for(h=i.length;h--;)g[i[h]]=!0;d[f]&&(i=b[f],i.overloaded||Structr.modifiers.m_overload(b,f,i,void 0),g=Structr.modifiers.m_overload(b,f,g,void 0));d[f]=1;b.__private[f]=b[f]=g}if(b.__construct&&a.__construct&&b.__construct==a.__construct)b.__construct=Structr.modifiers.m_override(b,"__construct",function(){this._super.apply(this,arguments)});for(f in b)if((g=b[f])&&g["static"])b.__construct[f]=g,delete b[f];return b}; +Structr.fh=function(a){a=Structr.extend({},a);a.getMethod=function(a){return Structr.getMethod(this,a)};a.extend=function(a){return Structr.extend(this,a)};a.copyTo=function(a){Structr.copy(this,a)};return a};if(this.exports)exports.Structr=Structr; \ No newline at end of file diff --git a/node_modules/celeri/package.json b/node_modules/celeri/package.json new file mode 100755 index 0000000..e27956d --- /dev/null +++ b/node_modules/celeri/package.json @@ -0,0 +1,18 @@ +{ + "name": "celeri", + "description": "CLI lib", + "version": "0.1.3", + "author": "Craig Condon", + "repository": { + "type": "git", + "url": "http://github.com/crcn/celeri.git" + }, + "directories" : { "lib" : "./lib" }, + "dependencies": { + "structr":"0.0.10", + "beanpole":"*", + "colors":"*" + }, + + "main": "./lib/index.js" +} diff --git a/node_modules/celeri/project.sublime-project b/node_modules/celeri/project.sublime-project new file mode 100644 index 0000000..1d5af0e --- /dev/null +++ b/node_modules/celeri/project.sublime-project @@ -0,0 +1,23 @@ +{ + "folders": + [ + { + "path": "." + } + ], + "build_systems": + [ + { + "name":"cbd make", + "cmd":["cbd","make","celeri"] + }, + { + "name":"cbd start", + "cmd":["cbd","start","celeri"] + }, + { + "name":"cbd make+start", + "cmd":["cbd","make+start","celeri"] + } + ] +} \ No newline at end of file diff --git a/node_modules/celeri/project.tmproj b/node_modules/celeri/project.tmproj new file mode 100644 index 0000000..3b8d49d --- /dev/null +++ b/node_modules/celeri/project.tmproj @@ -0,0 +1,48 @@ + + + + + currentDocument + lib/utils.js + documents + + + expanded + + name + project + regexFolderFilter + !.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$ + sourceDirectory + + + + fileHierarchyDrawerWidth + 200 + metaData + + lib/utils.js + + caret + + column + 0 + line + 22 + + firstVisibleColumn + 0 + firstVisibleLine + 0 + + + openDocuments + + lib/utils.js + + showFileHierarchyDrawer + + windowFrame + {{0, 4}, {1230, 874}} + + diff --git a/node_modules/findit/README.markdown b/node_modules/findit/README.markdown new file mode 100644 index 0000000..8b82ef5 --- /dev/null +++ b/node_modules/findit/README.markdown @@ -0,0 +1,91 @@ +findit +====== + +Recursively walk directory trees. Think `/usr/bin/find`. + +example time! +============= + +callback style +-------------- + +````javascript +require('findit').find(__dirname, function (file) { + console.log(file); +}) +```` + +emitter style +------------- + +````javascript +var finder = require('findit').find(__dirname); + +finder.on('directory', function (dir) { + console.log(dir + '/'); +}); + +finder.on('file', function (file) { + console.log(file); +}); +```` + +synchronous +----------- + +````javascript +var files = require('findit').sync(__dirname); + console.dir(files); +```` + +methods +======= + +find(basedir) +------------- +find(basedir, cb) +----------------- + +Do an asynchronous recursive walk starting at `basedir`. +Optionally supply a callback that will get the same arguments as the path event +documented below in "events". + +If `basedir` is actually a non-directory regular file, findit emits a single +"file" event for it then emits "end". + +Findit uses `fs.stat()` so symlinks are traversed automatically. Findit won't +traverse an inode that it has seen before so directories can have symlink cycles +and findit won't blow up. + +Returns an EventEmitter. See "events". + +sync(basedir, cb) +----------------- + +Return an array of files and directories from a synchronous recursive walk +starting at `basedir`. + +An optional callback `cb` will get called with `cb(file, stat)` if specified. + +events +====== + +file: [ file, stat ] +-------------------- + +Emitted for just files which are not directories. + +directory : [ directory, stat ] +------------------------------- + +Emitted for directories. + +path : [ file, stat ] +--------------------- + +Emitted for both files and directories. + +end +--- + +Emitted when the recursive walk is done. diff --git a/node_modules/findit/examples/callback.js b/node_modules/findit/examples/callback.js new file mode 100644 index 0000000..829630e --- /dev/null +++ b/node_modules/findit/examples/callback.js @@ -0,0 +1,3 @@ +require('findit').find(__dirname, function (file) { + console.log(file); +}) diff --git a/node_modules/findit/examples/emitter.js b/node_modules/findit/examples/emitter.js new file mode 100644 index 0000000..f97adf3 --- /dev/null +++ b/node_modules/findit/examples/emitter.js @@ -0,0 +1,9 @@ +var finder = require('findit').find(__dirname); + +finder.on('directory', function (dir) { + console.log(dir + '/'); +}); + +finder.on('file', function (file) { + console.log(file); +}); diff --git a/node_modules/findit/examples/sync.js b/node_modules/findit/examples/sync.js new file mode 100644 index 0000000..b09e0b2 --- /dev/null +++ b/node_modules/findit/examples/sync.js @@ -0,0 +1,2 @@ +var files = require('findit').findSync(__dirname); +console.dir(files); diff --git a/node_modules/findit/index.js b/node_modules/findit/index.js new file mode 100644 index 0000000..818e72d --- /dev/null +++ b/node_modules/findit/index.js @@ -0,0 +1,88 @@ +var fs = require('fs'); +var EventEmitter = require('events').EventEmitter; +var Seq = require('seq'); + +exports = module.exports = find; +exports.find = find; +function find (base, cb) { + var em = new EventEmitter; + var inodes = {}; + + function finder (dir, f) { + Seq() + .seq(fs.readdir, dir, Seq) + .flatten() + .seqEach(function (file) { + var p = dir + '/' + file; + fs.stat(p, this.into(p)); + }) + .seq(function () { + this(null, Object.keys(this.vars)); + }) + .flatten() + .seqEach(function (file) { + var stat = this.vars[file]; + if (cb) cb(file, stat); + + if (inodes[stat.ino]) { + // already seen this inode, probably a recursive symlink + this(null); + } + else { + em.emit('path', file, stat); + + if (stat.isDirectory()) { + em.emit('directory', file, stat); + finder(file, this); + } + else { + em.emit('file', file, stat); + this(null); + } + + inodes[stat.ino] = true; + } + }) + .seq(f.bind({}, null)) + .catch(em.emit.bind(em, 'error')) + ; + } + + fs.stat(base, function (err, s) { + if (err) { + em.emit('error', err); + } + else if (s.isDirectory()) { + finder(base, em.emit.bind(em, 'end')); + } + else { + em.emit('file', base); + em.emit('end'); + } + }); + + return em; +}; + +exports.findSync = function findSync (dir, cb) { + var rootStat = fs.statSync(dir); + if (!rootStat.isDirectory()) { + if (cb) cb(dir, rootStat); + return [dir]; + } + + return fs.readdirSync(dir).reduce(function (files, file) { + var p = dir + '/' + file; + var stat = fs.statSync(p); + if (cb) cb(p, stat); + files.push(p); + + if (stat.isDirectory()) { + files.push.apply(files, findSync(p, cb)); + } + + return files; + }, []); +}; + +exports.find.sync = exports.findSync; diff --git a/node_modules/findit/node_modules/seq/.npmignore b/node_modules/findit/node_modules/seq/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/findit/node_modules/seq/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/findit/node_modules/seq/README.markdown b/node_modules/findit/node_modules/seq/README.markdown new file mode 100644 index 0000000..3689261 --- /dev/null +++ b/node_modules/findit/node_modules/seq/README.markdown @@ -0,0 +1,442 @@ +Seq +=== + +Seq is an asynchronous flow control library with a chainable interface for +sequential and parallel actions. Even the error handling is chainable. + +Each action in the chain operates on a stack of values. +There is also a variables hash for storing values by name. + +[TOC] + + + +Examples +======== + +stat_all.js +----------- + +````javascript +var fs = require('fs'); +var Hash = require('hashish'); +var Seq = require('seq'); + +Seq() + .seq(function () { + fs.readdir(__dirname, this); + }) + .flatten() + .parEach(function (file) { + fs.stat(__dirname + '/' + file, this.into(file)); + }) + .seq(function () { + var sizes = Hash.map(this.vars, function (s) { return s.size }) + console.dir(sizes); + }) +; +```` + +Output: + + { 'stat_all.js': 404, 'parseq.js': 464 } + +parseq.js +--------- + +````javascript +var fs = require('fs'); +var exec = require('child_process').exec; + +var Seq = require('seq'); +Seq() + .seq(function () { + exec('whoami', this) + }) + .par(function (who) { + exec('groups ' + who, this); + }) + .par(function (who) { + fs.readFile(__filename, 'ascii', this); + }) + .seq(function (groups, src) { + console.log('Groups: ' + groups.trim()); + console.log('This file has ' + src.length + ' bytes'); + }) +; +```` + +Output: + + Groups: substack : substack dialout cdrom floppy audio src video plugdev games netdev fuse www + This file has 464 bytes + + + + +API +=== + +Each method executes callbacks with a context (its `this`) described in the next +section. Every method returns `this`. + +Whenever `this()` is called with a non-falsy first argument, the error value +propagates down to the first `catch` it sees, skipping over all actions in +between. There is an implicit `catch` at the end of all chains that prints the +error stack if available and otherwise just prints the error. + + + +Seq(xs=[]) +---------- + +The constructor function creates a new `Seq` chain with the methods described +below. The optional array argument becomes the new context stack. + +Array argument is new in 0.3. `Seq()` now behaves like `Seq.ap()`. + + +.seq(cb) +-------- +.seq(key, cb, *args) +-------------------- + +This eponymous function executes actions sequentially. +Once all running parallel actions are finished executing, +the supplied callback is `apply()`'d with the context stack. + +To execute the next action in the chain, call `this()`. The first +argument must be the error value. The rest of the values will become the stack +for the next action in the chain and are also available at `this.args`. + +If `key` is specified, the second argument sent to `this` goes to +`this.vars[key]` in addition to the stack and `this.args`. +`this.vars` persists across all requests unless it is overwritten. + +All arguments after `cb` will be bound to `cb`, which is useful because +`.bind()` makes you set `this`. If you pass in `Seq` in the arguments list, +it'll get transformed into `this` so that you can do: + +````javascript +Seq() + .seq(fs.readdir, __dirname, Seq) + .seq(function (files) { console.dir(files) }) +; +```` + +which prints an array of files in `__dirname`. + + +.par(cb) +-------- +.par(key, cb, *args) +-------------------- + +Use `par` to execute actions in parallel. +Chain multiple parallel actions together and collect all the responses on the +stack with a sequential operation like `seq`. + +Each `par` sets one element in the stack with the second argument to `this()` in +the order in which it appears, so multiple `par`s can be chained together. + +Like with `seq`, the first argument to `this()` should be the error value and +the second will get pushed to the stack. Further arguments are available in +`this.args`. + +If `key` is specified, the result from the second argument send to `this()` goes +to `this.vars[key]`. +`this.vars` persists across all requests unless it is overwritten. + +All arguments after `cb` will be bound to `cb`, which is useful because +`.bind()` makes you set `this`. Like `.seq()`, you can pass along `Seq` in these +bound arguments and it will get tranformed into `this`. + + +.catch(cb) +---------- + +Catch errors. Whenever a function calls `this` with a non-falsy first argument, +the message propagates down the chain to the first `catch` it sees. +The callback `cb` fires with the error object as its first argument and the key +that the action that caused the error was populating, which may be undefined. + +`catch` is a sequential action and further actions may appear after a `catch` in +a chain. If the execution reaches a `catch` in a chain and no error has occured, +the `catch` is skipped over. + +For convenience, there is a default error handler at the end of all chains. +This default error handler looks like this: + +````javascript +.catch(function (err) { + console.error(err.stack ? err.stack : err) +}) +```` + + +.forEach(cb) +------------ + +Execute each action in the stack under the context of the chain object. +`forEach` does not wait for any of the actions to finish and does not itself +alter the stack, but the callback may alter the stack itself by modifying +`this.stack`. + +The callback is executed `cb(x,i)` where `x` is the element and `i` is the +index. + +`forEach` is a sequential operation like `seq` and won't run until all pending +parallel requests yield results. + + +.seqEach(cb) +------------ + +Like `forEach`, call `cb` for each element on the stack, but unlike `forEach`, +`seqEach` waits for the callback to yield with `this` before moving on to the +next element in the stack. + +The callback is executed `cb(x,i)` where `x` is the element and `i` is the +index. + +If `this()` is supplied non-falsy error, the error propagates downward but any +other arguments are ignored. `seqEach` does not modify the stack itself. + + +.parEach(cb) +------------ +.parEach(limit, cb) +------------------- + +Like `forEach`, calls cb for each element in the stack and doesn't wait for the +callback to yield a result with `this()` before moving on to the next iteration. +Unlike `forEach`, `parEach` waits for all actions to call `this()` before moving +along to the next action in the chain. + +The callback is executed `cb(x,i)` where `x` is the element and `i` is the +index. + +`parEach` does not modify the stack itself and errors supplied to `this()` +propagate. + +Optionally, if limit is supplied to `parEach`, at most `limit` callbacks will be +active at a time. + + +.seqMap(cb) +----------- + +Like `seqEach`, but collect the values supplied to `this` and set the stack to +these values. + + +.parMap(cb) +----------- +.parMap(limit, cb) +------------------ + +Like `parEach`, but collect the values supplied to `this` and set the stack to +these values. + + +.seqFilter(cb) +----------- + +Executes the callback `cb(x, idx)` against each element on the stack, waiting for the +callback to yield with `this` before moving on to the next element. If the callback +returns an error or a falsey value, the element will not be included in the resulting +stack. + +Any errors from the callback are consumed and **do not** propagate. + +Calls to `this.into(i)` will place the value, if accepted by the callback, at the index in +the results as if it were ordered at i-th index on the stack before filtering (with ties +broken by the values). This implies `this.into` will never override another stack value +even if their indices collide. Finally, the value will only actually appear at `i` if the +callback accepts or moves enough values before `i`. + + +.parFilter(cb) +----------- +.parFilter(limit, cb) +------------------ + +Executes the callback `cb(x, idx)` against each element on the stack, but **does not** +wait for it to yield before moving on to the next element. If the callback returns an +error or a falsey value, the element will not be included in the resulting stack. + +Any errors from the callback are consumed and **do not** propagate. + +Calls to `this.into(i)` will place the value, if accepted by the callback, at the index in +the results as if it were ordered at i-th index on the stack before filtering (with ties +broken by the values). This implies `this.into` will never override another stack value +even if their indices collide. Finally, the value will only actually appear at `i` if the +callback accepts or moves enough values before `i`. + +Optionally, if limit is supplied to `parEach`, at most `limit` callbacks will be +active at a time. + + +.do(cb) +------- +Create a new nested context. `cb`'s first argument is the previous context, and `this` +is the nested `Seq` object. + + +.flatten(fully=true) +-------------------- + +Recursively flatten all the arrays in the stack. Set `fully=false` to flatten +only one level. + + +.unflatten() +------------ + +Turn the contents of the stack into a single array item. You can think of it +as the inverse of `flatten(false)`. + + +.extend([x,y...]) +----------------- + +Like `push`, but takes an array. This is like python's `[].extend()`. + + +.set(xs) +-------- + +Set the stack to a new array. This assigns the reference, it does not copy. + + +.empty() +-------- + +Set the stack to []. + + +.push(x,y...), .pop(), .shift(), .unshift(x), .splice(...), reverse() +--------------------------------------------------------------------- +.map(...), .filter(...), .reduce(...) +------------------------------------- + +Executes an array operation on the stack. + +The methods `map`, `filter`, and `reduce` are also proxies to their Array counterparts: +they have identical signatures to the Array methods, operate synchronously on the context +stack, and do not pass a Context object (unlike `seqMap` and `parMap`). + +The result of the transformation is assigned to the context stack; in the case of `reduce`, +if you do not return an array, the value will be wrapped in one. + +````javascript +Seq([1, 2, 3]) + .reduce(function(sum, x){ return sum + x; }, 0) + .seq(function(sum){ + console.log('sum: %s', sum); + // sum: 6 + console.log('stack is Array?', Array.isArray(this.stack)); + // stack is Array: true + console.log('stack:', this.stack); + // stack: [6] + }) +; +```` + + + + +Explicit Parameters +------------------- + +For environments like coffee-script or nested logic where threading `this` is +bothersome, you can use: + +* seq_ +* par_ +* forEach_ +* seqEach_ +* parEach_ +* seqMap_ +* parMap_ + +which work exactly like their un-underscored counterparts except for the first +parameter to the supplied callback is set to the context, `this`. + + + +Context Object +============== + +Each callback gets executed with its `this` set to a function in order to yield +results, error values, and control. The function also has these useful fields: + +this.stack +---------- + +The execution stack. + +this.stack_ +----------- + +The previous stack value, mostly used internally for hackish purposes. + +this.vars +--------- + +A hash of key/values populated with `par(key, ...)`, `seq(key, ...)` and +`this.into(key)`. + +this.into(key) +-------------- + +Instead of sending values to the stack, sets a key and returns `this`. +Use `this.into(key)` interchangeably with `this` for yielding keyed results. +`into` overrides the optional key set by `par(key, ...)` and `seq(key, ...)`. + +this.ok +------- + +Set the `err` to null. Equivalent to `this.bind(this, null)`. + +this.args +--------- + +`this.args` is like `this.stack`, but it contains all the arguments to `this()` +past the error value, not just the first. `this.args` is an array with the same +indices as `this.stack` but also stores keyed values for the last sequential +operation. Each element in `this.array` is set to `[].slice.call(arguments, 1)` +from inside `this()`. + +this.error +---------- + +This is used for error propagation. You probably shouldn't mess with it. + + + +Installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + + npm install seq + +or clone this project on github: + + git clone http://github.com/substack/node-seq.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + + + +Dependencies +------------ + +This module uses [chainsaw](http://github.com/substack/node-chainsaw) +When you `npm install seq` this dependency will automatically be installed. + + diff --git a/node_modules/findit/node_modules/seq/examples/join.js b/node_modules/findit/node_modules/seq/examples/join.js new file mode 100644 index 0000000..cc05c4f --- /dev/null +++ b/node_modules/findit/node_modules/seq/examples/join.js @@ -0,0 +1,18 @@ +var Seq = require('seq'); +Seq() + .par(function () { + var that = this; + setTimeout(function () { that(null, 'a') }, 300); + }) + .par(function () { + var that = this; + setTimeout(function () { that(null, 'b') }, 200); + }) + .par(function () { + var that = this; + setTimeout(function () { that(null, 'c') }, 100); + }) + .seq(function (a, b, c) { + console.dir([ a, b, c ]) + }) +; diff --git a/node_modules/findit/node_modules/seq/examples/parseq.coffee b/node_modules/findit/node_modules/seq/examples/parseq.coffee new file mode 100644 index 0000000..d4ca0ab --- /dev/null +++ b/node_modules/findit/node_modules/seq/examples/parseq.coffee @@ -0,0 +1,12 @@ +fs = require 'fs' +exec = require('child_process').exec +Seq = require 'seq' + +Seq() + .seq_((next) -> exec 'whoami', next) + .par_((next, who) -> exec('groups ' + who, next)) + .par_((next, who) -> fs.readFile(__filename, 'utf8', next)) + .seq_((next, groups, src) -> + console.log('Groups: ' + groups.trim()) + console.log('This file has ' + src.length + ' bytes') + ) diff --git a/node_modules/findit/node_modules/seq/examples/parseq.js b/node_modules/findit/node_modules/seq/examples/parseq.js new file mode 100644 index 0000000..2cdcf21 --- /dev/null +++ b/node_modules/findit/node_modules/seq/examples/parseq.js @@ -0,0 +1,19 @@ +var fs = require('fs'); +var exec = require('child_process').exec; + +var Seq = require('seq'); +Seq() + .seq(function () { + exec('whoami', this) + }) + .par(function (who) { + exec('groups ' + who, this); + }) + .par(function (who) { + fs.readFile(__filename, 'utf8', this); + }) + .seq(function (groups, src) { + console.log('Groups: ' + groups.trim()); + console.log('This file has ' + src.length + ' bytes'); + }) +; diff --git a/node_modules/findit/node_modules/seq/examples/stat_all.coffee b/node_modules/findit/node_modules/seq/examples/stat_all.coffee new file mode 100644 index 0000000..83ec0b2 --- /dev/null +++ b/node_modules/findit/node_modules/seq/examples/stat_all.coffee @@ -0,0 +1,16 @@ +fs = require 'fs' +Hash = require 'hashish' +Seq = require 'seq' + +Seq() + .seq_((next) -> + fs.readdir(__dirname, next) + ) + .flatten() + .parEach_((next, file) -> + fs.stat(__dirname + '/' + file, next.into(file)) + ) + .seq_((next) -> + sizes = Hash.map(next.vars, (s) -> s.size) + console.dir sizes + ) diff --git a/node_modules/findit/node_modules/seq/examples/stat_all.js b/node_modules/findit/node_modules/seq/examples/stat_all.js new file mode 100644 index 0000000..b9962eb --- /dev/null +++ b/node_modules/findit/node_modules/seq/examples/stat_all.js @@ -0,0 +1,17 @@ +var fs = require('fs'); +var Hash = require('hashish'); +var Seq = require('seq'); + +Seq() + .seq(function () { + fs.readdir(__dirname, this); + }) + .flatten() + .parEach(function (file) { + fs.stat(__dirname + '/' + file, this.into(file)); + }) + .seq(function () { + var sizes = Hash.map(this.vars, function (s) { return s.size }) + console.dir(sizes); + }) +; diff --git a/node_modules/findit/node_modules/seq/index.js b/node_modules/findit/node_modules/seq/index.js new file mode 100755 index 0000000..4e0888b --- /dev/null +++ b/node_modules/findit/node_modules/seq/index.js @@ -0,0 +1,520 @@ +var EventEmitter = require('events').EventEmitter; +var Hash = require('hashish'); +var Chainsaw = require('chainsaw'); + +module.exports = Seq; +function Seq (xs) { + if (xs && !Array.isArray(xs) || arguments.length > 1) { + throw new Error('Optional argument to Seq() is exactly one Array'); + } + + var ch = Chainsaw(function (saw) { + builder.call(this, saw, xs || []); + }); + + process.nextTick(function () { + ch['catch'](function (err) { + console.error(err.stack ? err.stack : err) + }); + }); + return ch; +} + +Seq.ap = Seq; // for compatability with versions <0.3 + +function builder (saw, xs) { + var context = { + vars : {}, + args : {}, + stack : xs, + error : null + }; + context.stack_ = context.stack; + + function action (step, key, f, g) { + var cb = function (err) { + var args = [].slice.call(arguments, 1); + if (err) { + context.error = { message : err, key : key }; + saw.jump(lastPar); + saw.down('catch'); + g(); + } + else { + if (typeof key == 'number') { + context.stack_[key] = args[0]; + context.args[key] = args; + } + else { + context.stack_.push.apply(context.stack_, args); + if (key !== undefined) { + context.vars[key] = args[0]; + context.args[key] = args; + } + } + if (g) g(args, key); + } + }; + Hash(context).forEach(function (v,k) { cb[k] = v }); + + cb.into = function (k) { + key = k; + return cb; + }; + + cb.next = function (err, xs) { + context.stack_.push.apply(context.stack_, xs); + cb.apply(cb, [err].concat(context.stack)); + }; + + cb.pass = function (err) { + cb.apply(cb, [err].concat(context.stack)); + }; + + cb.ok = cb.bind(cb, null); + + f.apply(cb, context.stack); + } + + var running = 0; + var errors = 0; + + this.seq = function (key, cb) { + var bound = [].slice.call(arguments, 2); + + if (typeof key === 'function') { + if (arguments.length > 1) bound.unshift(cb); + cb = key; + key = undefined; + } + + if (context.error) saw.next() + else if (running === 0) { + action(saw.step, key, + function () { + context.stack_ = []; + var args = [].slice.call(arguments); + args.unshift.apply(args, bound.map(function (arg) { + return arg === Seq ? this : arg + }, this)); + + cb.apply(this, args); + }, function () { + context.stack = context.stack_; + saw.next() + } + ); + } + }; + + var lastPar = null; + this.par = function (key, cb) { + lastPar = saw.step; + + if (running == 0) { + // empty the active stack for the first par() in a chain + context.stack_ = []; + } + + var bound = [].slice.call(arguments, 2); + if (typeof key === 'function') { + if (arguments.length > 1) bound.unshift(cb); + cb = key; + key = context.stack_.length; + context.stack_.push(null); + } + var cb_ = function () { + var args = [].slice.call(arguments); + args.unshift.apply(args, bound.map(function (arg) { + return arg === Seq ? this : arg + }, this)); + + cb.apply(this, args); + }; + + running ++; + + var step = saw.step; + process.nextTick(function () { + action(step, key, cb_, function (args) { + if (!args) errors ++; + + running --; + if (running == 0) { + context.stack = context.stack_.slice(); + saw.step = lastPar; + if (errors > 0) saw.down('catch'); + errors = 0; + saw.next(); + } + }); + }); + saw.next(); + }; + + [ 'seq', 'par' ].forEach(function (name) { + this[name + '_'] = function (key) { + var args = [].slice.call(arguments); + + var cb = typeof key === 'function' + ? args[0] : args[1]; + + var fn = function () { + var argv = [].slice.call(arguments); + argv.unshift(this); + cb.apply(this, argv); + }; + + if (typeof key === 'function') { + args[0] = fn; + } + else { + args[1] = fn; + } + + this[name].apply(this, args); + }; + }, this); + + this['catch'] = function (cb) { + if (context.error) { + cb.call(context, context.error.message, context.error.key); + context.error = null; + } + saw.next(); + }; + + this.forEach = function (cb) { + this.seq(function () { + context.stack_ = context.stack.slice(); + var end = context.stack.length; + + if (end === 0) this(null) + else context.stack.forEach(function (x, i) { + action(saw.step, i, function () { + cb.call(this, x, i); + if (i == end - 1) saw.next(); + }); + }); + }); + }; + + this.seqEach = function (cb) { + this.seq(function () { + context.stack_ = context.stack.slice(); + var xs = context.stack.slice(); + if (xs.length === 0) this(null); + else (function next (i) { + action( + saw.step, i, + function () { cb.call(this, xs[i], i) }, + function (args) { + if (!args || i === xs.length - 1) saw.next(); + else next(i + 1); + } + ); + }).bind(this)(0); + }); + }; + + this.parEach = function (limit, cb) { + var xs = context.stack.slice(); + if (cb === undefined) { cb = limit; limit = xs.length } + context.stack_ = []; + + var active = 0; + var finished = 0; + var queue = []; + + if (xs.length === 0) saw.next() + else xs.forEach(function call (x, i) { + if (active >= limit) { + queue.push(call.bind(this, x, i)); + } + else { + active ++; + action(saw.step, i, + function () { + cb.call(this, x, i); + }, + function () { + active --; + finished ++; + if (queue.length > 0) queue.shift()(); + else if (finished === xs.length) { + saw.next(); + } + } + ); + } + }); + }; + + this.parMap = function (limit, cb) { + var res = []; + var len = context.stack.length; + if (cb === undefined) { cb = limit; limit = len } + var res = []; + + Seq() + .extend(context.stack) + .parEach(limit, function (x, i) { + var self = this; + + var next = function () { + res[i] = arguments[1]; + self.apply(self, arguments); + }; + + next.stack = self.stack; + next.stack_ = self.stack_; + next.vars = self.vars; + next.args = self.args; + next.error = self.error; + + next.into = function (key) { + return function () { + res[key] = arguments[1]; + self.apply(self, arguments); + }; + }; + + next.ok = function () { + var args = [].slice.call(arguments); + args.unshift(null); + return next.apply(next, args); + }; + + cb.apply(next, arguments); + }) + .seq(function () { + context.stack = res; + saw.next(); + }) + ; + }; + + this.seqMap = function (cb) { + var res = []; + var lastIdx = context.stack.length - 1; + + this.seqEach(function (x, i) { + var self = this; + + var next = function () { + res[i] = arguments[1]; + if (i === lastIdx) + context.stack = res; + self.apply(self, arguments); + }; + + next.stack = self.stack; + next.stack_ = self.stack_; + next.vars = self.vars; + next.args = self.args; + next.error = self.error; + + next.into = function (key) { + return function () { + res[key] = arguments[1]; + if (i === lastIdx) + context.stack = res; + self.apply(self, arguments); + }; + }; + + next.ok = function () { + var args = [].slice.call(arguments); + args.unshift(null); + return next.apply(next, args); + }; + + cb.apply(next, arguments); + }); + }; + + /** + * Consumes any errors that occur in `cb`. Calls to `this.into(i)` will place + * that value, if accepted by the filter, at the index in the results as + * if it were the i-th index before filtering. (This means it will never + * override another value, and will only actually appear at i if the filter + * accepts all values before i.) + */ + this.parFilter = function (limit, cb) { + var res = []; + var len = context.stack.length; + if (cb === undefined) { cb = limit; limit = len } + var res = []; + + Seq() + .extend(context.stack) + .parEach(limit, function (x, i) { + var self = this; + + var next = function (err, ok) { + if (!err && ok) + res.push([i, x]); + arguments[0] = null; // discard errors + self.apply(self, arguments); + }; + + next.stack = self.stack; + next.stack_ = self.stack_; + next.vars = self.vars; + next.args = self.args; + next.error = self.error; + + next.into = function (key) { + return function (err, ok) { + if (!err && ok) + res.push([key, x]); + arguments[0] = null; // discard errors + self.apply(self, arguments); + }; + }; + + next.ok = function () { + var args = [].slice.call(arguments); + args.unshift(null); + return next.apply(next, args); + }; + + cb.apply(next, arguments); + }) + .seq(function () { + context.stack = res.sort().map(function(pair){ return pair[1]; }); + saw.next(); + }) + ; + }; + + /** + * Consumes any errors that occur in `cb`. Calls to `this.into(i)` will place + * that value, if accepted by the filter, at the index in the results as + * if it were the i-th index before filtering. (This means it will never + * override another value, and will only actually appear at i if the filter + * accepts all values before i.) + */ + this.seqFilter = function (cb) { + var res = []; + var lastIdx = context.stack.length - 1; + + this.seqEach(function (x, i) { + var self = this; + + var next = function (err, ok) { + if (!err && ok) + res.push([i, x]); + if (i === lastIdx) + context.stack = res.sort().map(function(pair){ return pair[1]; }); + arguments[0] = null; // discard errors + self.apply(self, arguments); + }; + + next.stack = self.stack; + next.stack_ = self.stack_; + next.vars = self.vars; + next.args = self.args; + next.error = self.error; + + next.into = function (key) { + return function (err, ok) { + if (!err && ok) + res.push([key, x]); + if (i === lastIdx) + context.stack = res.sort().map(function(pair){ return pair[1]; }); + arguments[0] = null; // discard errors + self.apply(self, arguments); + }; + }; + + next.ok = function () { + var args = [].slice.call(arguments); + args.unshift(null); + return next.apply(next, args); + }; + + cb.apply(next, arguments); + }); + }; + + [ 'forEach', 'seqEach', 'parEach', 'seqMap', 'parMap', 'seqFilter', 'parFilter' ] + .forEach(function (name) { + this[name + '_'] = function (cb) { + this[name].call(this, function () { + var args = [].slice.call(arguments); + args.unshift(this); + cb.apply(this, args); + }); + }; + }, this) + ; + + ['push','pop','shift','unshift','splice','reverse'] + .forEach(function (name) { + this[name] = function () { + context.stack[name].apply( + context.stack, + [].slice.call(arguments) + ); + saw.next(); + return this; + }; + }, this) + ; + + [ 'map', 'filter', 'reduce' ] + .forEach(function (name) { + this[name] = function () { + var res = context.stack[name].apply( + context.stack, + [].slice.call(arguments) + ); + // stack must be an array, or bad things happen + context.stack = (Array.isArray(res) ? res : [res]); + saw.next(); + return this; + }; + }, this) + ; + + this.extend = function (xs) { + if (!Array.isArray(xs)) { + throw new Error('argument to .extend() is not an Array'); + } + context.stack.push.apply(context.stack, xs); + saw.next(); + }; + + this.flatten = function (pancake) { + var xs = []; + // should we fully flatten this array? (default: true) + if (pancake === undefined) { pancake = true; } + context.stack.forEach(function f (x) { + if (Array.isArray(x) && pancake) x.forEach(f); + else if (Array.isArray(x)) xs = xs.concat(x); + else xs.push(x); + }); + context.stack = xs; + saw.next(); + }; + + this.unflatten = function () { + context.stack = [context.stack]; + saw.next(); + }; + + this.empty = function () { + context.stack = []; + saw.next(); + }; + + this.set = function (stack) { + context.stack = stack; + saw.next(); + }; + + this['do'] = function (cb) { + saw.nest(cb, context); + }; +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/.npmignore b/node_modules/findit/node_modules/seq/node_modules/chainsaw/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/README.markdown b/node_modules/findit/node_modules/seq/node_modules/chainsaw/README.markdown new file mode 100644 index 0000000..9bb1259 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/README.markdown @@ -0,0 +1,140 @@ +Chainsaw +======== + +Build chainable fluent interfaces the easy way in node.js. + +With this meta-module you can write modules with chainable interfaces. +Chainsaw takes care of all of the boring details and makes nested flow control +super simple too. + +Just call `Chainsaw` with a constructor function like in the examples below. +In your methods, just do `saw.next()` to move along to the next event and +`saw.nest()` to create a nested chain. + +Examples +======== + +add_do.js +--------- + +This silly example adds values with a chainsaw. + + var Chainsaw = require('chainsaw'); + + function AddDo (sum) { + return Chainsaw(function (saw) { + this.add = function (n) { + sum += n; + saw.next(); + }; + + this.do = function (cb) { + saw.nest(cb, sum); + }; + }); + } + + AddDo(0) + .add(5) + .add(10) + .do(function (sum) { + if (sum > 12) this.add(-10); + }) + .do(function (sum) { + console.log('Sum: ' + sum); + }) + ; + +Output: + Sum: 5 + +prompt.js +--------- + +This example provides a wrapper on top of stdin with the help of +[node-lazy](https://github.com/pkrumins/node-lazy) for line-processing. + + var Chainsaw = require('chainsaw'); + var Lazy = require('lazy'); + + module.exports = Prompt; + function Prompt (stream) { + var waiting = []; + var lines = []; + var lazy = Lazy(stream).lines.map(String) + .forEach(function (line) { + if (waiting.length) { + var w = waiting.shift(); + w(line); + } + else lines.push(line); + }) + ; + + var vars = {}; + return Chainsaw(function (saw) { + this.getline = function (f) { + var g = function (line) { + saw.nest(f, line, vars); + }; + + if (lines.length) g(lines.shift()); + else waiting.push(g); + }; + + this.do = function (cb) { + saw.nest(cb, vars); + }; + }); + } + +And now for the new Prompt() module in action: + + var util = require('util'); + var stdin = process.openStdin(); + + Prompt(stdin) + .do(function () { + util.print('x = '); + }) + .getline(function (line, vars) { + vars.x = parseInt(line, 10); + }) + .do(function () { + util.print('y = '); + }) + .getline(function (line, vars) { + vars.y = parseInt(line, 10); + }) + .do(function (vars) { + if (vars.x + vars.y < 10) { + util.print('z = '); + this.getline(function (line) { + vars.z = parseInt(line, 10); + }) + } + else { + vars.z = 0; + } + }) + .do(function (vars) { + console.log('x + y + z = ' + (vars.x + vars.y + vars.z)); + process.exit(); + }) + ; + +Installation +============ + +With [npm](http://github.com/isaacs/npm), just do: + npm install chainsaw + +or clone this project on github: + + git clone http://github.com/substack/node-chainsaw.git + +To run the tests with [expresso](http://github.com/visionmedia/expresso), +just do: + + expresso + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/add_do.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/add_do.js new file mode 100644 index 0000000..378705d --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/add_do.js @@ -0,0 +1,25 @@ +var Chainsaw = require('chainsaw'); + +function AddDo (sum) { + return Chainsaw(function (saw) { + this.add = function (n) { + sum += n; + saw.next(); + }; + + this.do = function (cb) { + saw.nest(cb, sum); + }; + }); +} + +AddDo(0) + .add(5) + .add(10) + .do(function (sum) { + if (sum > 12) this.add(-10); + }) + .do(function (sum) { + console.log('Sum: ' + sum); + }) +; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/prompt.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/prompt.js new file mode 100644 index 0000000..0a06d71 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/prompt.js @@ -0,0 +1,67 @@ +var Chainsaw = require('chainsaw'); +var Lazy = require('lazy'); + +module.exports = Prompt; +function Prompt (stream) { + var waiting = []; + var lines = []; + var lazy = Lazy(stream).lines.map(String) + .forEach(function (line) { + if (waiting.length) { + var w = waiting.shift(); + w(line); + } + else lines.push(line); + }) + ; + + var vars = {}; + return Chainsaw(function (saw) { + this.getline = function (f) { + var g = function (line) { + saw.nest(f, line, vars); + }; + + if (lines.length) g(lines.shift()); + else waiting.push(g); + }; + + this.do = function (cb) { + saw.nest(cb, vars); + }; + }); +} + +var util = require('util'); +if (__filename === process.argv[1]) { + var stdin = process.openStdin(); + Prompt(stdin) + .do(function () { + util.print('x = '); + }) + .getline(function (line, vars) { + vars.x = parseInt(line, 10); + }) + .do(function () { + util.print('y = '); + }) + .getline(function (line, vars) { + vars.y = parseInt(line, 10); + }) + .do(function (vars) { + if (vars.x + vars.y < 10) { + util.print('z = '); + this.getline(function (line) { + vars.z = parseInt(line, 10); + }) + } + else { + vars.z = 0; + } + }) + .do(function (vars) { + console.log('x + y + z = ' + (vars.x + vars.y + vars.z)); + process.exit(); + }) + ; +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/index.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/index.js new file mode 100755 index 0000000..597cc48 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/index.js @@ -0,0 +1,108 @@ +var Traverse = require('traverse'); +var EventEmitter = require('events').EventEmitter; + +module.exports = Chainsaw; +function Chainsaw (builder) { + var saw = Chainsaw.saw(builder, {}); + var r = builder.call(saw.handlers, saw); + if (r !== undefined) saw.handlers = r; + return saw.chain(); +}; + +Chainsaw.saw = function (builder, handlers) { + var saw = new EventEmitter; + saw.handlers = handlers; + saw.actions = []; + saw.step = 0; + + saw.chain = function () { + var ch = Traverse(saw.handlers).map(function (node) { + if (this.isRoot) return node; + var ps = this.path; + + if (typeof node === 'function') { + this.update(function () { + saw.actions.push({ + path : ps, + args : [].slice.call(arguments) + }); + return ch; + }); + } + }); + + process.nextTick(function () { + saw.emit('begin'); + saw.next(); + }); + + return ch; + }; + + saw.next = function () { + var action = saw.actions[saw.step]; + saw.step ++; + + if (!action) { + saw.emit('end'); + } + else if (!action.trap) { + var node = saw.handlers; + action.path.forEach(function (key) { node = node[key] }); + node.apply(saw.handlers, action.args); + } + }; + + saw.nest = function (cb) { + var args = [].slice.call(arguments, 1); + var autonext = true; + + if (typeof cb === 'boolean') { + var autonext = cb; + cb = args.shift(); + } + + var s = Chainsaw.saw(builder, {}); + var r = builder.call(s.handlers, s); + + if (r !== undefined) s.handlers = r; + cb.apply(s.chain(), args); + if (autonext !== false) s.on('end', saw.next); + }; + + saw.trap = function (name, cb) { + var ps = Array.isArray(name) ? name : [name]; + saw.actions.push({ + path : ps, + step : saw.step, + cb : cb, + trap : true + }); + }; + + saw.down = function (name) { + var ps = (Array.isArray(name) ? name : [name]).join('/'); + var i = saw.actions.slice(saw.step).map(function (x) { + if (x.trap && x.step <= saw.step) return false; + return x.path.join('/') == ps; + }).indexOf(true); + + if (i >= 0) saw.step += i; + else saw.step = saw.actions.length; + + var act = saw.actions[saw.step - 1]; + if (act && act.trap) { + // It's a trap! + saw.step = act.step; + act.cb(); + } + else saw.next(); + }; + + saw.jump = function (step) { + saw.step = step; + saw.next(); + }; + + return saw; +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/.npmignore b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/LICENSE b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/README.markdown b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/README.markdown new file mode 100644 index 0000000..5728639 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/README.markdown @@ -0,0 +1,247 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value) +------------------ + +Set a new value for the present node. + +this.remove() +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete() +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + +methods +======= + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.deepEqual(obj) +--------------- + +Returns a boolean, whether the instance value is equal to the supplied object +along a deep traversal using some opinionated choices. + +Some notes: + +* RegExps are equal if their .toString()s match, but not functions since +functions can close over different variables. + +* Date instances are compared using `.getTime()` just like `assert.deepEqual()`. + +* Circular references must refer to the same paths within the data structure for +both objects. For instance, in this snippet: + +````javascript +var a = [1]; +a.push(a); // a = [ 1, *a ] + +var b = [1]; +b.push(a); // b = [ 1, [ 1, *a ] ] +```` + +`a` is not the same as `b` since even though the expansion is the same, the +circular references in each refer to different paths into the data structure. + +However, in: + +````javascript +var c = [1]; +c.push(c); // c = [ 1, *c ]; +```` + +`c` is equal to `a` in a `deepEqual()` because they have the same terminal node +structure. + +* Arguments objects are not arrays and neither are they the same as regular +objects. + +* Instances created with `new` of String, Boolean, and Number types are never +equal to the native versions. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +installation +============ + +Using npm: + npm install traverse + +Or check out the repository and link your development copy: + git clone http://github.com/substack/js-traverse.git + cd js-traverse + npm link . + +You can test traverse with "expresso":http://github.com/visionmedia/expresso +(`npm install expresso`): + js-traverse $ expresso + + 100% wahoo, your stuff is not broken! + +hash transforms +=============== + +This library formerly had a hash transformation component. It has been +[moved to the hashish package](https://github.com/substack/node-hashish). diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/json.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..f3bd989 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var Traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/leaves.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..ef5325f --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var Traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/negative.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..a3996c5 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var Traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +Traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/stringify.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..0cef7ec --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var Traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +Traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/index.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/index.js new file mode 100755 index 0000000..7a34c8a --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/index.js @@ -0,0 +1,322 @@ +module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.deepEqual = function (obj) { + if (arguments.length !== 1) { + throw new Error( + 'deepEqual requires exactly one object to compare against' + ); + } + + var equal = true; + var node = obj; + + this.forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (Traverse(obj).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + Object.keys(src).forEach(function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents.slice(-1)[0], + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + }, + 'delete' : function () { + delete state.parent.node[state.key]; + }, + remove : function () { + if (Array.isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + }, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.isLeaf = Object.keys(node).length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + if (modifiers.before) modifiers.before.call(state, state.node); + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + var keys = Object.keys(state.node); + keys.forEach(function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +Object.keys(Traverse.prototype).forEach(function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array.isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else { + dst = Object.create(Object.getPrototypeOf(src)); + } + + Object.keys(src).forEach(function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/package.json b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/package.json new file mode 100644 index 0000000..5ab3fc6 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/package.json @@ -0,0 +1,18 @@ +{ + "name" : "traverse", + "version" : "0.3.9", + "description" : "Traverse and transform objects by visiting every node on a recursive walk", + "author" : "James Halliday", + "license" : "MIT/X11", + "main" : "./index", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/js-traverse.git" + }, + "devDependencies" : { + "expresso" : "0.7.x" + }, + "scripts" : { + "test" : "expresso" + } +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/circular.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..e1eef3f --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/circular.js @@ -0,0 +1,114 @@ +var assert = require('assert'); +var Traverse = require('traverse'); +var util = require('util'); + +exports.circular = function () { + var obj = { x : 3 }; + obj.y = obj; + var foundY = false; + Traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + assert.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + foundY = true; + } + }); + assert.ok(foundY); +}; + +exports.deepCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + Traverse(obj).forEach(function (x) { + if (this.circular) { + assert.deepEqual(this.circular.path, []); + assert.deepEqual(this.path, [ 'y', 2 ]); + times ++; + } + }); + + assert.deepEqual(times, 1); +}; + +exports.doubleCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + Traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]); + assert.deepEqual(circs[0].circ.path, []); + + assert.deepEqual(circs[1].self.path, [ 'y', 2 ]); + assert.deepEqual(circs[1].circ.path, []); + + assert.deepEqual(circs.length, 2); +}; + +exports.circDubForEach = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + Traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circDubMap = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = Traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circClone = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = Traverse.clone(obj); + assert.ok(obj !== clone); + + assert.ok(clone.y[2] === clone); + assert.ok(clone.y[2] !== obj); + assert.ok(clone.x[3][2] === clone); + assert.ok(clone.x[3][2] !== obj); + assert.deepEqual(clone.x.slice(0,3), [1,2,3]); + assert.deepEqual(clone.y.slice(0,2), [4,5]); +}; + +exports.circMapScrub = function () { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = Traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + assert.deepEqual( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + assert.ok(Traverse.deepEqual(scrubbed, { a : 1, b : 2 })); + + assert.equal(obj.c, obj); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/date.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/date.js new file mode 100644 index 0000000..2cb8252 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/date.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports.dateEach = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + Traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + assert.deepEqual(counts, { + object : 1, + Date : 1, + number : 2, + }); +}; + +exports.dateMap = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = Traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + assert.ok(obj.x !== res.x); + assert.deepEqual(res, { + x : obj.x, + y : 110, + z : 105, + }); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/equal.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..4d732fa --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/equal.js @@ -0,0 +1,219 @@ +var assert = require('assert'); +var traverse = require('traverse'); + +exports.deepDates = function () { + assert.ok( + traverse.deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + assert.ok( + !traverse.deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}; + +exports.deepCircular = function () { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + assert.ok( + !traverse.deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + assert.ok( + traverse.deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + assert.ok( + traverse.deepEqual(b, d), + 'non-root circular ref structural comparison' + ); +}; + +exports.deepInstances = function () { + assert.ok( + !traverse.deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + assert.ok( + !traverse.deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + assert.ok( + !traverse.deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + assert.ok( + traverse.deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + assert.ok( + !traverse.deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + assert.ok( + !traverse.deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + assert.ok( + traverse.deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); +}; + +exports.deepEqual = function () { + assert.ok( + !traverse.deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); +}; + +exports.falsy = function () { + assert.ok( + !traverse.deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + assert.ok( + !traverse.deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + assert.ok( + !traverse.deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + assert.ok( + !traverse.deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + assert.ok( + !traverse.deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); +}; + +exports.deletedArrayEqual = function () { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + assert.ok( + traverse.deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + assert.ok( + !traverse.deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + assert.ok( + !traverse.deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); +}; + +exports.deletedObjectEqual = function () { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + assert.ok( + traverse.deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + assert.ok( + !traverse.deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + assert.ok( + !traverse.deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); +}; + +exports.emptyKeyEqual = function () { + assert.ok(!traverse.deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); +}; + +exports.deepArguments = function () { + assert.ok( + !traverse.deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + assert.ok( + traverse.deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); +}; + +exports.deepUn = function () { + assert.ok(!traverse.deepEqual({ a : 1, b : 2 }, undefined)); + assert.ok(!traverse.deepEqual({ a : 1, b : 2 }, {})); + assert.ok(!traverse.deepEqual(undefined, { a : 1, b : 2 })); + assert.ok(!traverse.deepEqual({}, { a : 1, b : 2 })); + assert.ok(traverse.deepEqual(undefined, undefined)); + assert.ok(traverse.deepEqual(null, null)); + assert.ok(!traverse.deepEqual(undefined, null)); +}; + +exports.deepLevels = function () { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + assert.ok(!traverse.deepEqual(xs, [])); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/instance.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..501981f --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var assert = require('assert'); +var Traverse = require('traverse'); +var EventEmitter = require('events').EventEmitter; + +exports['check instanceof on node elems'] = function () { + + var counts = { emitter : 0 }; + + Traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + assert.equal(counts.emitter, 2); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/interface.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..df5b037 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/interface.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports['interface map'] = function () { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + assert.deepEqual( + Traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + assert.deepEqual( + Traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + assert.deepEqual( + Traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + Traverse.forEach(obj, function (node) { nodes ++ }); + assert.deepEqual(nodes, 8); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/json.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/json.js new file mode 100644 index 0000000..bf36620 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/json.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports['json test'] = function () { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + assert.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + assert.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + assert.deepEqual(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + assert.deepEqual( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + assert.deepEqual( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + assert.deepEqual(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/leaves.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..4e8d280 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/leaves.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports['leaves test'] = function () { + var acc = []; + Traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + assert.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/mutability.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..5a4d6dd --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/mutability.js @@ -0,0 +1,203 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports.mutate = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mutateT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.map = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mapT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.clone = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).clone(); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.cloneT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.clone(obj); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.reduce = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, [ 1, 2, 3, 4 ]); +}; + +exports.reduceInit = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, obj); +}; + +exports.remove = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, c : [ 3 ] }); +}; + +exports.removeMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, c : [ 3 ] }); +}; + +exports.delete = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!Traverse.deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + assert.ok(Traverse.deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + assert.ok(!Traverse.deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); +}; + +exports.deleteRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!Traverse.deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + assert.ok(Traverse.deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + assert.ok(!Traverse.deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + assert.ok(!Traverse.deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); +}; + +exports.deleteMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(Traverse.deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + assert.ok(Traverse.deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(Traverse.deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + assert.ok(Traverse.deepEqual( + res, { a : 1, c : [ 3 ] } + )); +}; + +exports.deleteMapRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(Traverse.deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + assert.ok(Traverse.deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(!Traverse.deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + assert.ok(Traverse.deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/negative.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..6cf287d --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/negative.js @@ -0,0 +1,20 @@ +var Traverse = require('traverse'); +var assert = require('assert'); + +exports['negative update test'] = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = Traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + assert.deepEqual(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + assert.deepEqual(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); +} + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/obj.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..9c3b0db --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/obj.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports['traverse an object with nested functions'] = function () { + var to = setTimeout(function () { + assert.fail('never ran'); + }, 1000); + + function Cons (x) { + clearTimeout(to); + assert.equal(x, 10); + }; + Traverse(new Cons(10)); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stop.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..ef6b36e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stop.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var traverse = require('traverse'); + +exports.stop = function () { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + assert.equal(visits, 5); +}; + +exports.stopMap = function () { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + assert.equal(s, 'ABCDEfghij'); +}; + +exports.stopReduce = function () { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + assert.deepEqual(xs, [ 4, 5, 6 ]); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stringify.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..bf36f63 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var Traverse = require('traverse'); + +exports.stringify = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + Traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + assert.equal(s, JSON.stringify(obj)); +} + diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/super_deep.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..974181e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/super_deep.js @@ -0,0 +1,54 @@ +var assert = require('assert'); +var traverse = require('traverse'); + +exports.super_deep = function () { + var util = require('util'); + var a0 = make(); + var a1 = make(); + assert.ok(traverse.deepEqual(a0, a1)); + + a0.c.d.moo = true; + assert.ok(!traverse.deepEqual(a0, a1)); + + a1.c.d.moo = true; + assert.ok(traverse.deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //assert.ok(!traverse.deepEqual(a0, a1)); +}; + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/package.json b/node_modules/findit/node_modules/seq/node_modules/chainsaw/package.json new file mode 100644 index 0000000..01aedf4 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/package.json @@ -0,0 +1,23 @@ +{ + "name" : "chainsaw", + "version" : "0.0.9", + "description" : "Build chainable fluent interfaces the easy way... with a freakin' chainsaw!", + "main" : "./index.js", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-chainsaw.git" + }, + "dependencies" : { + "traverse" : ">=0.3.0 <0.4" + }, + "keywords" : [ + "chain", + "fluent", + "interface", + "monad", + "monadic" + ], + "author" : "James Halliday (http://substack.net)", + "license" : "MIT/X11", + "engine" : { "node" : ">=0.4.0" } +} diff --git a/node_modules/findit/node_modules/seq/node_modules/chainsaw/test/chainsaw.js b/node_modules/findit/node_modules/seq/node_modules/chainsaw/test/chainsaw.js new file mode 100644 index 0000000..0c24729 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/chainsaw/test/chainsaw.js @@ -0,0 +1,418 @@ +var assert = require('assert'); +var Chainsaw = require('chainsaw'); + +exports.getset = function () { + var to = setTimeout(function () { + assert.fail('builder never fired'); + }, 1000); + + var ch = Chainsaw(function (saw) { + clearTimeout(to); + var num = 0; + + this.get = function (cb) { + cb(num); + saw.next(); + }; + + this.set = function (n) { + num = n; + saw.next(); + }; + + var ti = setTimeout(function () { + assert.fail('end event not emitted'); + }, 50); + + saw.on('end', function () { + clearTimeout(ti); + assert.equal(times, 3); + }); + }); + + var times = 0; + ch + .get(function (x) { + assert.equal(x, 0); + times ++; + }) + .set(10) + .get(function (x) { + assert.equal(x, 10); + times ++; + }) + .set(20) + .get(function (x) { + assert.equal(x, 20); + times ++; + }) + ; +}; + +exports.nest = function () { + var ch = (function () { + var vars = {}; + return Chainsaw(function (saw) { + this.do = function (cb) { + saw.nest(cb, vars); + }; + }); + })(); + + var order = []; + var to = setTimeout(function () { + assert.fail("Didn't get to the end"); + }, 50); + + ch + .do(function (vars) { + vars.x = 'y'; + order.push(1); + + this + .do(function (vs) { + order.push(2); + vs.x = 'x'; + }) + .do(function (vs) { + order.push(3); + vs.z = 'z'; + }) + ; + }) + .do(function (vars) { + vars.y = 'y'; + order.push(4); + }) + .do(function (vars) { + assert.eql(order, [1,2,3,4]); + assert.eql(vars, { x : 'x', y : 'y', z : 'z' }); + clearTimeout(to); + }) + ; +}; + +exports.nestWait = function () { + var ch = (function () { + var vars = {}; + return Chainsaw(function (saw) { + this.do = function (cb) { + saw.nest(cb, vars); + }; + + this.wait = function (n) { + setTimeout(function () { + saw.next(); + }, n); + }; + }); + })(); + + var order = []; + var to = setTimeout(function () { + assert.fail("Didn't get to the end"); + }, 1000); + + var times = {}; + + ch + .do(function (vars) { + vars.x = 'y'; + order.push(1); + + this + .do(function (vs) { + order.push(2); + vs.x = 'x'; + times.x = Date.now(); + }) + .wait(50) + .do(function (vs) { + order.push(3); + vs.z = 'z'; + + times.z = Date.now(); + var dt = times.z - times.x; + assert.ok(dt >= 50 && dt < 75); + }) + ; + }) + .do(function (vars) { + vars.y = 'y'; + order.push(4); + + times.y = Date.now(); + }) + .wait(100) + .do(function (vars) { + assert.eql(order, [1,2,3,4]); + assert.eql(vars, { x : 'x', y : 'y', z : 'z' }); + clearTimeout(to); + + times.end = Date.now(); + var dt = times.end - times.y; + assert.ok(dt >= 100 && dt < 125) + }) + ; +}; + +exports.nestNext = function () { + var ch = (function () { + var vars = {}; + return Chainsaw(function (saw) { + this.do = function (cb) { + saw.nest(false, function () { + var args = [].slice.call(arguments); + args.push(saw.next); + cb.apply(this, args); + }, vars); + }; + }); + })(); + + var order = []; + var to = setTimeout(function () { + assert.fail("Didn't get to the end"); + }, 500); + + var times = []; + + ch + .do(function (vars, next_) { + vars.x = 'y'; + order.push(1); + + this + .do(function (vs, next) { + order.push(2); + vs.x = 'x'; + setTimeout(next, 30); + }) + .do(function (vs, next) { + order.push(3); + vs.z = 'z'; + setTimeout(next, 10); + }) + .do(function () { + setTimeout(next_, 20); + }) + ; + }) + .do(function (vars, next) { + vars.y = 'y'; + order.push(4); + setTimeout(next, 5); + }) + .do(function (vars) { + assert.eql(order, [1,2,3,4]); + assert.eql(vars, { x : 'x', y : 'y', z : 'z' }); + + clearTimeout(to); + }) + ; +}; + +exports.builder = function () { + var cx = Chainsaw(function (saw) { + this.x = function () {}; + }); + assert.ok(cx.x); + + var cy = Chainsaw(function (saw) { + return { y : function () {} }; + }); + assert.ok(cy.y); + + var cz = Chainsaw(function (saw) { + return { z : function (cb) { saw.nest(cb) } }; + }); + assert.ok(cz.z); + + var to = setTimeout(function () { + assert.fail("Nested z didn't run"); + }, 50); + + cz.z(function () { + clearTimeout(to); + assert.ok(this.z); + }); +}; + +this.attr = function () { + var to = setTimeout(function () { + assert.fail("attr chain didn't finish"); + }, 50); + + var xy = []; + var ch = Chainsaw(function (saw) { + this.h = { + x : function () { + xy.push('x'); + saw.next(); + }, + y : function () { + xy.push('y'); + saw.next(); + assert.eql(xy, ['x','y']); + clearTimeout(to); + } + }; + }); + assert.ok(ch.h); + assert.ok(ch.h.x); + assert.ok(ch.h.y); + + ch.h.x().h.y(); +}; + +exports.down = function () { + var error = null; + var s; + var ch = Chainsaw(function (saw) { + s = saw; + this.raise = function (err) { + error = err; + saw.down('catch'); + }; + + this.do = function (cb) { + cb.call(this); + }; + + this.catch = function (cb) { + if (error) { + saw.nest(cb, error); + error = null; + } + else saw.next(); + }; + }); + + var to = setTimeout(function () { + assert.fail(".do() after .catch() didn't fire"); + }, 50); + + ch + .do(function () { + this.raise('pow'); + }) + .do(function () { + assert.fail("raise didn't skip over this do block"); + }) + .catch(function (err) { + assert.equal(err, 'pow'); + }) + .do(function () { + clearTimeout(to); + }) + ; +}; + +exports.trap = function () { + var error = null; + var ch = Chainsaw(function (saw) { + var pars = 0; + var stack = []; + var i = 0; + + this.par = function (cb) { + pars ++; + var j = i ++; + cb.call(function () { + pars --; + stack[j] = [].slice.call(arguments); + saw.down('result'); + }); + saw.next(); + }; + + this.join = function (cb) { + saw.trap('result', function () { + if (pars == 0) { + cb.apply(this, stack); + saw.next(); + } + }); + }; + + this.raise = function (err) { + error = err; + saw.down('catch'); + }; + + this.do = function (cb) { + cb.call(this); + }; + + this.catch = function (cb) { + if (error) { + saw.nest(cb, error); + error = null; + } + else saw.next(); + }; + }); + + var to = setTimeout(function () { + assert.fail(".do() after .join() didn't fire"); + }, 100); + var tj = setTimeout(function () { + assert.fail('.join() never fired'); + }, 100); + + var joined = false; + ch + .par(function () { + setTimeout(this.bind(null, 1), 50); + }) + .par(function () { + setTimeout(this.bind(null, 2), 25); + }) + .join(function (x, y) { + assert.equal(x[0], 1); + assert.equal(y[0], 2); + clearTimeout(tj); + joined = true; + }) + .do(function () { + clearTimeout(to); + assert.ok(joined); + }) + ; +}; + +exports.jump = function () { + var to = setTimeout(function () { + assert.fail('builder never fired'); + }, 50); + + var xs = [ 4, 5, 6, -4, 8, 9, -1, 8 ]; + var xs_ = []; + + var ch = Chainsaw(function (saw) { + this.x = function (i) { + xs_.push(i); + saw.next(); + }; + + this.y = function (step) { + var x = xs.shift(); + if (x > 0) saw.jump(step); + else saw.next(); + }; + + saw.on('end', function () { + clearTimeout(to); + assert.eql(xs, [ 8 ]); + assert.eql(xs_, [ 1, 1, 1, 1, 2, 3, 2, 3, 2, 3 ]); + }); + }); + + ch + .x(1) + .y(0) + .x(2) + .x(3) + .y(2) + ; +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/README.markdown b/node_modules/findit/node_modules/seq/node_modules/hashish/README.markdown new file mode 100644 index 0000000..1f39d59 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/README.markdown @@ -0,0 +1,191 @@ +Hashish +======= + +Hashish is a node.js library for manipulating hash data structures. +It is distilled from the finest that ruby, perl, and haskell have to offer by +way of hash/map interfaces. + +Hashish provides a chaining interface, where you can do: + + var Hash = require('hashish'); + + Hash({ a : 1, b : 2, c : 3, d : 4 }) + .map(function (x) { return x * 10 }) + .filter(function (x) { return x < 30 }) + .forEach(function (x, key) { + console.log(key + ' => ' + x); + }) + ; + +Output: + + a => 10 + b => 20 + +Some functions and attributes in the chaining interface are terminal, like +`.items` or `.detect()`. They return values of their own instead of the chain +context. + +Each function in the chainable interface is also attached to `Hash` in chainless +form: + + var Hash = require('hashish'); + var obj = { a : 1, b : 2, c : 3, d : 4 }; + + var mapped = Hash.map(obj, function (x) { + return x * 10 + }); + + console.dir(mapped); + +Output: + + { a: 10, b: 20, c: 30, d: 40 } + +In either case, the 'this' context of the function calls is the same object that +the chained functions return, so you can make nested chains. + +Methods +======= + +forEach(cb) +----------- + +For each key/value in the hash, calls `cb(value, key)`. + +map(cb) +------- + +For each key/value in the hash, calls `cb(value, key)`. +The return value of `cb` is the new value at `key` in the resulting hash. + +filter(cb) +---------- + +For each key/value in the hash, calls `cb(value, key)`. +The resulting hash omits key/value pairs where `cb` returned a falsy value. + +detect(cb) +---------- + +Returns the first value in the hash for which `cb(value, key)` is non-falsy. +Order of hashes is not well-defined so watch out for that. + +reduce(cb) +---------- + +Returns the accumulated value of a left-fold over the key/value pairs. + +some(cb) +-------- + +Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy +value. + +update(obj1, [obj2, obj3, ...]) +----------- + +Mutate the context hash, merging the key/value pairs from the passed objects +and overwriting keys from the context hash if the current `obj` has keys of +the same name. Falsy arguments are silently ignored. + +updateAll([ obj1, obj2, ... ]) +------------------------------ + +Like multi-argument `update()` but operate on an array directly. + +merge(obj1, [obj2, obj3, ...]) +---------- + +Merge the key/value pairs from the passed objects into the resultant hash +without modifying the context hash. Falsy arguments are silently ignored. + +mergeAll([ obj1, obj2, ... ]) +------------------------------ + +Like multi-argument `merge()` but operate on an array directly. + +has(key) +-------- + +Return whether the hash has a key, `key`. + +valuesAt(keys) +-------------- + +Return an Array with the values at the keys from `keys`. + +tap(cb) +------- + +Call `cb` with the present raw hash. +This function is chainable. + +extract(keys) +------------- + +Filter by including only those keys in `keys` in the resulting hash. + +exclude(keys) +------------- + +Filter by excluding those keys in `keys` in the resulting hash. + +Attributes +========== + +These are attributes in the chaining interface and functions in the `Hash.xxx` +interface. + +keys +---- + +Return all the enumerable attribute keys in the hash. + +values +------ + +Return all the enumerable attribute values in the hash. + +compact +------- + +Filter out values which are `=== undefined`. + +clone +----- + +Make a deep copy of the hash. + +copy +---- + +Make a shallow copy of the hash. + +length +------ + +Return the number of key/value pairs in the hash. +Note: use `Hash.size()` for non-chain mode. + +size +---- + +Alias for `length` since `Hash.length` is masked by `Function.prototype`. + +See Also +======== + +See also [creationix's pattern/hash](http://github.com/creationix/pattern), +which does a similar thing except with hash inputs and array outputs. + +Installation +============ + +To install with [npm](http://github.com/isaacs/npm): + + npm install hashish + +To run the tests with [expresso](http://github.com/visionmedia/expresso): + + expresso diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/examples/chain.js b/node_modules/findit/node_modules/seq/node_modules/hashish/examples/chain.js new file mode 100644 index 0000000..74ded5e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/examples/chain.js @@ -0,0 +1,9 @@ +var Hash = require('hashish'); + +Hash({ a : 1, b : 2, c : 3, d : 4 }) + .map(function (x) { return x * 10 }) + .filter(function (x) { return x < 30 }) + .forEach(function (x, key) { + console.log(key + ' => ' + x); + }) +; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/examples/map.js b/node_modules/findit/node_modules/seq/node_modules/hashish/examples/map.js new file mode 100644 index 0000000..119d3d9 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/examples/map.js @@ -0,0 +1,7 @@ +var Hash = require('hashish'); +var obj = { a : 1, b : 2, c : 3, d : 4 }; + +var mapped = Hash.map(obj, function (x) { + return x * 10 +}); +console.dir(mapped); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/index.js b/node_modules/findit/node_modules/seq/node_modules/hashish/index.js new file mode 100644 index 0000000..1bc28e2 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/index.js @@ -0,0 +1,253 @@ +module.exports = Hash; +var Traverse = require('traverse'); + +function Hash (hash, xs) { + if (Array.isArray(hash) && Array.isArray(xs)) { + var to = Math.min(hash.length, xs.length); + var acc = {}; + for (var i = 0; i < to; i++) { + acc[hash[i]] = xs[i]; + } + return Hash(acc); + } + + if (hash === undefined) return Hash({}); + + var self = { + map : function (f) { + var acc = { __proto__ : hash.__proto__ }; + Object.keys(hash).forEach(function (key) { + acc[key] = f.call(self, hash[key], key); + }); + return Hash(acc); + }, + forEach : function (f) { + Object.keys(hash).forEach(function (key) { + f.call(self, hash[key], key); + }); + return self; + }, + filter : function (f) { + var acc = { __proto__ : hash.__proto__ }; + Object.keys(hash).forEach(function (key) { + if (f.call(self, hash[key], key)) { + acc[key] = hash[key]; + } + }); + return Hash(acc); + }, + detect : function (f) { + for (var key in hash) { + if (f.call(self, hash[key], key)) { + return hash[key]; + } + } + return undefined; + }, + reduce : function (f, acc) { + var keys = Object.keys(hash); + if (acc === undefined) acc = keys.shift(); + keys.forEach(function (key) { + acc = f.call(self, acc, hash[key], key); + }); + return acc; + }, + some : function (f) { + for (var key in hash) { + if (f.call(self, hash[key], key)) return true; + } + return false; + }, + update : function (obj) { + if (arguments.length > 1) { + self.updateAll([].slice.call(arguments)); + } + else { + Object.keys(obj).forEach(function (key) { + hash[key] = obj[key]; + }); + } + return self; + }, + updateAll : function (xs) { + xs.filter(Boolean).forEach(function (x) { + self.update(x); + }); + return self; + }, + merge : function (obj) { + if (arguments.length > 1) { + return self.copy.updateAll([].slice.call(arguments)); + } + else { + return self.copy.update(obj); + } + }, + mergeAll : function (xs) { + return self.copy.updateAll(xs); + }, + has : function (key) { // only operates on enumerables + return Array.isArray(key) + ? key.every(function (k) { return self.has(k) }) + : self.keys.indexOf(key.toString()) >= 0; + }, + valuesAt : function (keys) { + return Array.isArray(keys) + ? keys.map(function (key) { return hash[key] }) + : hash[keys] + ; + }, + tap : function (f) { + f.call(self, hash); + return self; + }, + extract : function (keys) { + var acc = {}; + keys.forEach(function (key) { + acc[key] = hash[key]; + }); + return Hash(acc); + }, + exclude : function (keys) { + return self.filter(function (_, key) { + return keys.indexOf(key) < 0 + }); + }, + end : hash, + items : hash + }; + + var props = { + keys : function () { return Object.keys(hash) }, + values : function () { + return Object.keys(hash).map(function (key) { return hash[key] }); + }, + compact : function () { + return self.filter(function (x) { return x !== undefined }); + }, + clone : function () { return Hash(Hash.clone(hash)) }, + copy : function () { return Hash(Hash.copy(hash)) }, + length : function () { return Object.keys(hash).length }, + size : function () { return self.length } + }; + + if (Object.defineProperty) { + // es5-shim has an Object.defineProperty but it throws for getters + try { + for (var key in props) { + Object.defineProperty(self, key, { get : props[key] }); + } + } + catch (err) { + for (var key in props) { + if (key !== 'clone' && key !== 'copy' && key !== 'compact') { + // ^ those keys use Hash() so can't call them without + // a stack overflow + self[key] = props[key](); + } + } + } + } + else if (self.__defineGetter__) { + for (var key in props) { + self.__defineGetter__(key, props[key]); + } + } + else { + // non-lazy version for browsers that suck >_< + for (var key in props) { + self[key] = props[key](); + } + } + + return self; +}; + +// deep copy +Hash.clone = function (ref) { + return Traverse.clone(ref); +}; + +// shallow copy +Hash.copy = function (ref) { + var hash = { __proto__ : ref.__proto__ }; + Object.keys(ref).forEach(function (key) { + hash[key] = ref[key]; + }); + return hash; +}; + +Hash.map = function (ref, f) { + return Hash(ref).map(f).items; +}; + +Hash.forEach = function (ref, f) { + Hash(ref).forEach(f); +}; + +Hash.filter = function (ref, f) { + return Hash(ref).filter(f).items; +}; + +Hash.detect = function (ref, f) { + return Hash(ref).detect(f); +}; + +Hash.reduce = function (ref, f, acc) { + return Hash(ref).reduce(f, acc); +}; + +Hash.some = function (ref, f) { + return Hash(ref).some(f); +}; + +Hash.update = function (a /*, b, c, ... */) { + var args = Array.prototype.slice.call(arguments, 1); + var hash = Hash(a); + return hash.update.apply(hash, args).items; +}; + +Hash.merge = function (a /*, b, c, ... */) { + var args = Array.prototype.slice.call(arguments, 1); + var hash = Hash(a); + return hash.merge.apply(hash, args).items; +}; + +Hash.has = function (ref, key) { + return Hash(ref).has(key); +}; + +Hash.valuesAt = function (ref, keys) { + return Hash(ref).valuesAt(keys); +}; + +Hash.tap = function (ref, f) { + return Hash(ref).tap(f).items; +}; + +Hash.extract = function (ref, keys) { + return Hash(ref).extract(keys).items; +}; + +Hash.exclude = function (ref, keys) { + return Hash(ref).exclude(keys).items; +}; + +Hash.concat = function (xs) { + var hash = Hash({}); + xs.forEach(function (x) { hash.update(x) }); + return hash.items; +}; + +Hash.zip = function (xs, ys) { + return Hash(xs, ys).items; +}; + +// .length is already defined for function prototypes +Hash.size = function (ref) { + return Hash(ref).size; +}; + +Hash.compact = function (ref) { + return Hash(ref).compact.items; +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/.npmignore b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/LICENSE b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/LICENSE new file mode 100644 index 0000000..7b75500 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/LICENSE @@ -0,0 +1,24 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: +http://www.opensource.org/licenses/mit-license.php + +Copyright 2010 James Halliday (mail@substack.net) + +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/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/README.markdown b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/README.markdown new file mode 100644 index 0000000..f86ef76 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/README.markdown @@ -0,0 +1,237 @@ +traverse +======== + +Traverse and transform objects by visiting every node on a recursive walk. + +examples +======== + +transform negative numbers in-place +----------------------------------- + +negative.js + +````javascript +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); +```` + +Output: + + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ] + +collect leaf nodes +------------------ + +leaves.js + +````javascript +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); +```` + +Output: + + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +scrub circular references +------------------------- + +scrub.js: + +````javascript +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); +```` + +output: + + { a: 1, b: 2, c: [ 3, 4 ] } + +context +======= + +Each method that takes a callback has a context (its `this` object) with these +attributes: + +this.node +--------- + +The present node on the recursive walk + +this.path +--------- + +An array of string keys from the root to the present node + +this.parent +----------- + +The context of the node's parent. +This is `undefined` for the root node. + +this.key +-------- + +The name of the key of the present node in its parent. +This is `undefined` for the root node. + +this.isRoot, this.notRoot +------------------------- + +Whether the present node is the root node + +this.isLeaf, this.notLeaf +------------------------- + +Whether or not the present node is a leaf node (has no children) + +this.level +---------- + +Depth of the node within the traversal + +this.circular +------------- + +If the node equals one of its parents, the `circular` attribute is set to the +context of that parent and the traversal progresses no deeper. + +this.update(value, stopHere=false) +---------------------------------- + +Set a new value for the present node. + +All the elements in `value` will be recursively traversed unless `stopHere` is +true. + +this.remove(stopHere=false) +------------- + +Remove the current element from the output. If the node is in an Array it will +be spliced off. Otherwise it will be deleted from its parent. + +this.delete(stopHere=false) +------------- + +Delete the current element from its parent in the output. Calls `delete` even on +Arrays. + +this.before(fn) +--------------- + +Call this function before any of the children are traversed. + +You can assign into `this.keys` here to traverse in a custom order. + +this.after(fn) +-------------- + +Call this function after any of the children are traversed. + +this.pre(fn) +------------ + +Call this function before each of the children are traversed. + +this.post(fn) +------------- + +Call this function after each of the children are traversed. + +methods +======= + +.map(fn) +-------- + +Execute `fn` for each node in the object and return a new object with the +results of the walk. To update nodes in the result use `this.update(value)`. + +.forEach(fn) +------------ + +Execute `fn` for each node in the object but unlike `.map()`, when +`this.update()` is called it updates the object in-place. + +.reduce(fn, acc) +---------------- + +For each node in the object, perform a +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function)) +with the return value of `fn(acc, node)`. + +If `acc` isn't specified, `acc` is set to the root object for the first step +and the root element is skipped. + +.paths() +-------- + +Return an `Array` of every possible non-cyclic path in the object. +Paths are `Array`s of string keys. + +.nodes() +-------- + +Return an `Array` of every node in the object. + +.clone() +-------- + +Create a deep clone of the object. + +install +======= + +Using [npm](http://npmjs.org) do: + + $ npm install traverse + +test +==== + +Using [expresso](http://github.com/visionmedia/expresso) do: + + $ expresso + + 100% wahoo, your stuff is not broken! + +in the browser +============== + +Use [browserify](https://github.com/substack/node-browserify) to run traverse in +the browser. + +traverse has been tested and works with: + +* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0 +* Firefox 3.5 +* Chrome 6.0 +* Opera 10.6 +* Safari 5.0 diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/json.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/json.js new file mode 100755 index 0000000..50d612e --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/json.js @@ -0,0 +1,16 @@ +var traverse = require('traverse'); + +var id = 54; +var callbacks = {}; +var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + +var scrubbed = traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } +}); + +console.dir(scrubbed); +console.dir(callbacks); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/leaves.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/leaves.js new file mode 100755 index 0000000..c1b310b --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/leaves.js @@ -0,0 +1,15 @@ +var traverse = require('traverse'); + +var obj = { + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 }, +}; + +var leaves = traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; +}, []); + +console.dir(leaves); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/negative.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/negative.js new file mode 100755 index 0000000..78608a0 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/negative.js @@ -0,0 +1,8 @@ +var traverse = require('traverse'); +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +traverse(obj).forEach(function (x) { + if (x < 0) this.update(x + 128); +}); + +console.dir(obj); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/scrub.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/scrub.js new file mode 100755 index 0000000..5d15b91 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/scrub.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('traverse'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/stringify.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/stringify.js new file mode 100755 index 0000000..167b68b --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/stringify.js @@ -0,0 +1,38 @@ +#!/usr/bin/env node +var traverse = require('traverse'); + +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + +var s = ''; +traverse(obj).forEach(function to_s (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + to_s(key); + s += ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'string') { + s += '"' + node.toString().replace(/"/g, '\\"') + '"'; + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } +}); + +console.log('JSON.stringify: ' + JSON.stringify(obj)); +console.log('this stringify: ' + s); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/index.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/index.js new file mode 100644 index 0000000..038a1ad --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/index.js @@ -0,0 +1,267 @@ +module.exports = Traverse; +function Traverse (obj) { + if (!(this instanceof Traverse)) return new Traverse(obj); + this.value = obj; +} + +Traverse.prototype.get = function (ps) { + var node = this.value; + for (var i = 0; i < ps.length; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) { + node = undefined; + break; + } + node = node[key]; + } + return node; +}; + +Traverse.prototype.set = function (ps, value) { + var node = this.value; + for (var i = 0; i < ps.length - 1; i ++) { + var key = ps[i]; + if (!Object.hasOwnProperty.call(node, key)) node[key] = {}; + node = node[key]; + } + node[ps[i]] = value; + return value; +}; + +Traverse.prototype.map = function (cb) { + return walk(this.value, cb, true); +}; + +Traverse.prototype.forEach = function (cb) { + this.value = walk(this.value, cb, false); + return this.value; +}; + +Traverse.prototype.reduce = function (cb, init) { + var skip = arguments.length === 1; + var acc = skip ? this.value : init; + this.forEach(function (x) { + if (!this.isRoot || !skip) { + acc = cb.call(this, acc, x); + } + }); + return acc; +}; + +Traverse.prototype.paths = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.path); + }); + return acc; +}; + +Traverse.prototype.nodes = function () { + var acc = []; + this.forEach(function (x) { + acc.push(this.node); + }); + return acc; +}; + +Traverse.prototype.clone = function () { + var parents = [], nodes = []; + + return (function clone (src) { + for (var i = 0; i < parents.length; i++) { + if (parents[i] === src) { + return nodes[i]; + } + } + + if (typeof src === 'object' && src !== null) { + var dst = copy(src); + + parents.push(src); + nodes.push(dst); + + forEach(Object_keys(src), function (key) { + dst[key] = clone(src[key]); + }); + + parents.pop(); + nodes.pop(); + return dst; + } + else { + return src; + } + })(this.value); +}; + +function walk (root, cb, immutable) { + var path = []; + var parents = []; + var alive = true; + + return (function walker (node_) { + var node = immutable ? copy(node_) : node_; + var modifiers = {}; + + var keepGoing = true; + + var state = { + node : node, + node_ : node_, + path : [].concat(path), + parent : parents[parents.length - 1], + parents : parents, + key : path.slice(-1)[0], + isRoot : path.length === 0, + level : path.length, + circular : null, + update : function (x, stopHere) { + if (!state.isRoot) { + state.parent.node[state.key] = x; + } + state.node = x; + if (stopHere) keepGoing = false; + }, + 'delete' : function (stopHere) { + delete state.parent.node[state.key]; + if (stopHere) keepGoing = false; + }, + remove : function (stopHere) { + if (Array_isArray(state.parent.node)) { + state.parent.node.splice(state.key, 1); + } + else { + delete state.parent.node[state.key]; + } + if (stopHere) keepGoing = false; + }, + keys : null, + before : function (f) { modifiers.before = f }, + after : function (f) { modifiers.after = f }, + pre : function (f) { modifiers.pre = f }, + post : function (f) { modifiers.post = f }, + stop : function () { alive = false }, + block : function () { keepGoing = false } + }; + + if (!alive) return state; + + if (typeof node === 'object' && node !== null) { + state.keys = Object_keys(node); + + state.isLeaf = state.keys.length == 0; + + for (var i = 0; i < parents.length; i++) { + if (parents[i].node_ === node_) { + state.circular = parents[i]; + break; + } + } + } + else { + state.isLeaf = true; + } + + state.notLeaf = !state.isLeaf; + state.notRoot = !state.isRoot; + + // use return values to update if defined + var ret = cb.call(state, state.node); + if (ret !== undefined && state.update) state.update(ret); + + if (modifiers.before) modifiers.before.call(state, state.node); + + if (!keepGoing) return state; + + if (typeof state.node == 'object' + && state.node !== null && !state.circular) { + parents.push(state); + + forEach(state.keys, function (key, i) { + path.push(key); + + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key); + + var child = walker(state.node[key]); + if (immutable && Object.hasOwnProperty.call(state.node, key)) { + state.node[key] = child.node; + } + + child.isLast = i == state.keys.length - 1; + child.isFirst = i == 0; + + if (modifiers.post) modifiers.post.call(state, child); + + path.pop(); + }); + parents.pop(); + } + + if (modifiers.after) modifiers.after.call(state, state.node); + + return state; + })(root).node; +} + +function copy (src) { + if (typeof src === 'object' && src !== null) { + var dst; + + if (Array_isArray(src)) { + dst = []; + } + else if (src instanceof Date) { + dst = new Date(src); + } + else if (src instanceof Boolean) { + dst = new Boolean(src); + } + else if (src instanceof Number) { + dst = new Number(src); + } + else if (src instanceof String) { + dst = new String(src); + } + else if (Object.create && Object.getPrototypeOf) { + dst = Object.create(Object.getPrototypeOf(src)); + } + else if (src.__proto__ || src.constructor.prototype) { + var proto = src.__proto__ || src.constructor.prototype || {}; + var T = function () {}; + T.prototype = proto; + dst = new T; + if (!dst.__proto__) dst.__proto__ = proto; + } + + forEach(Object_keys(src), function (key) { + dst[key] = src[key]; + }); + return dst; + } + else return src; +} + +var Object_keys = Object.keys || function keys (obj) { + var res = []; + for (var key in obj) res.push(key) + return res; +}; + +var Array_isArray = Array.isArray || function isArray (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +var forEach = function (xs, fn) { + if (xs.forEach) return xs.forEach(fn) + else for (var i = 0; i < xs.length; i++) { + fn(xs[i], i, xs); + } +}; + +forEach(Object_keys(Traverse.prototype), function (key) { + Traverse[key] = function (obj) { + var args = [].slice.call(arguments, 1); + var t = Traverse(obj); + return t[key].apply(t, args); + }; +}); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/main.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/main.js new file mode 100755 index 0000000..d562d37 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/main.js @@ -0,0 +1,10 @@ +// scrub out circular references +var traverse = require('./index.js'); + +var obj = { a : 1, b : 2, c : [ 3, 4 ] }; +obj.c.push(obj); + +var scrubbed = traverse(obj).map(function (x) { + if (this.circular) this.remove() +}); +console.dir(scrubbed); diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/package.json b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/package.json new file mode 100644 index 0000000..f86322a --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/package.json @@ -0,0 +1,18 @@ +{ + "name" : "traverse", + "version" : "0.5.2", + "description" : "Traverse and transform objects by visiting every node on a recursive walk", + "author" : "James Halliday", + "license" : "MIT/X11", + "main" : "./index", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/js-traverse.git" + }, + "devDependencies" : { + "expresso" : "0.7.x" + }, + "scripts" : { + "test" : "expresso" + } +} diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/circular.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/circular.js new file mode 100644 index 0000000..9162601 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/circular.js @@ -0,0 +1,115 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); +var util = require('util'); + +exports.circular = function () { + var obj = { x : 3 }; + obj.y = obj; + var foundY = false; + Traverse(obj).forEach(function (x) { + if (this.path.join('') == 'y') { + assert.equal( + util.inspect(this.circular.node), + util.inspect(obj) + ); + foundY = true; + } + }); + assert.ok(foundY); +}; + +exports.deepCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + + var times = 0; + Traverse(obj).forEach(function (x) { + if (this.circular) { + assert.deepEqual(this.circular.path, []); + assert.deepEqual(this.path, [ 'y', 2 ]); + times ++; + } + }); + + assert.deepEqual(times, 1); +}; + +exports.doubleCirc = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var circs = []; + Traverse(obj).forEach(function (x) { + if (this.circular) { + circs.push({ circ : this.circular, self : this, node : x }); + } + }); + + assert.deepEqual(circs[0].self.path, [ 'x', 3, 2 ]); + assert.deepEqual(circs[0].circ.path, []); + + assert.deepEqual(circs[1].self.path, [ 'y', 2 ]); + assert.deepEqual(circs[1].circ.path, []); + + assert.deepEqual(circs.length, 2); +}; + +exports.circDubForEach = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + Traverse(obj).forEach(function (x) { + if (this.circular) this.update('...'); + }); + + assert.deepEqual(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circDubMap = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var c = Traverse(obj).map(function (x) { + if (this.circular) { + this.update('...'); + } + }); + + assert.deepEqual(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] }); +}; + +exports.circClone = function () { + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] }; + obj.y[2] = obj; + obj.x.push(obj.y); + + var clone = Traverse.clone(obj); + assert.ok(obj !== clone); + + assert.ok(clone.y[2] === clone); + assert.ok(clone.y[2] !== obj); + assert.ok(clone.x[3][2] === clone); + assert.ok(clone.x[3][2] !== obj); + assert.deepEqual(clone.x.slice(0,3), [1,2,3]); + assert.deepEqual(clone.y.slice(0,2), [4,5]); +}; + +exports.circMapScrub = function () { + var obj = { a : 1, b : 2 }; + obj.c = obj; + + var scrubbed = Traverse(obj).map(function (node) { + if (this.circular) this.remove(); + }); + assert.deepEqual( + Object.keys(scrubbed).sort(), + [ 'a', 'b' ] + ); + assert.ok(deepEqual(scrubbed, { a : 1, b : 2 })); + + assert.equal(obj.c, obj); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/date.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/date.js new file mode 100644 index 0000000..4ca06dc --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/date.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.dateEach = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var counts = {}; + + Traverse(obj).forEach(function (node) { + var t = (node instanceof Date && 'Date') || typeof node; + counts[t] = (counts[t] || 0) + 1; + }); + + assert.deepEqual(counts, { + object : 1, + Date : 1, + number : 2, + }); +}; + +exports.dateMap = function () { + var obj = { x : new Date, y : 10, z : 5 }; + + var res = Traverse(obj).map(function (node) { + if (typeof node === 'number') this.update(node + 100); + }); + + assert.ok(obj.x !== res.x); + assert.deepEqual(res, { + x : obj.x, + y : 110, + z : 105, + }); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/equal.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/equal.js new file mode 100644 index 0000000..decc755 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/equal.js @@ -0,0 +1,220 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.deepDates = function () { + assert.ok( + deepEqual( + { d : new Date, x : [ 1, 2, 3 ] }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'dates should be equal' + ); + + var d0 = new Date; + setTimeout(function () { + assert.ok( + !deepEqual( + { d : d0, x : [ 1, 2, 3 ], }, + { d : new Date, x : [ 1, 2, 3 ] } + ), + 'microseconds should count in date equality' + ); + }, 5); +}; + +exports.deepCircular = function () { + var a = [1]; + a.push(a); // a = [ 1, *a ] + + var b = [1]; + b.push(a); // b = [ 1, [ 1, *a ] ] + + assert.ok( + !deepEqual(a, b), + 'circular ref mount points count towards equality' + ); + + var c = [1]; + c.push(c); // c = [ 1, *c ] + assert.ok( + deepEqual(a, c), + 'circular refs are structurally the same here' + ); + + var d = [1]; + d.push(a); // c = [ 1, [ 1, *d ] ] + assert.ok( + deepEqual(b, d), + 'non-root circular ref structural comparison' + ); +}; + +exports.deepInstances = function () { + assert.ok( + !deepEqual([ new Boolean(false) ], [ false ]), + 'boolean instances are not real booleans' + ); + + assert.ok( + !deepEqual([ new String('x') ], [ 'x' ]), + 'string instances are not real strings' + ); + + assert.ok( + !deepEqual([ new Number(4) ], [ 4 ]), + 'number instances are not real numbers' + ); + + assert.ok( + deepEqual([ new RegExp('x') ], [ /x/ ]), + 'regexp instances are real regexps' + ); + + assert.ok( + !deepEqual([ new RegExp(/./) ], [ /../ ]), + 'these regexps aren\'t the same' + ); + + assert.ok( + !deepEqual( + [ function (x) { return x * 2 } ], + [ function (x) { return x * 2 } ] + ), + 'functions with the same .toString() aren\'t necessarily the same' + ); + + var f = function (x) { return x * 2 }; + assert.ok( + deepEqual([ f ], [ f ]), + 'these functions are actually equal' + ); +}; + +exports.deepEqual = function () { + assert.ok( + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }), + 'arrays are not objects' + ); +}; + +exports.falsy = function () { + assert.ok( + !deepEqual([ undefined ], [ null ]), + 'null is not undefined!' + ); + + assert.ok( + !deepEqual([ null ], [ undefined ]), + 'undefined is not null!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'undefined is not null, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); + + assert.ok( + !deepEqual( + { a : 1, b : 2, c : [ 3, undefined, 5 ] }, + { a : 1, b : 2, c : [ 3, null, 5 ] } + ), + 'null is not undefined, however deeply!' + ); +}; + +exports.deletedArrayEqual = function () { + var xs = [ 1, 2, 3, 4 ]; + delete xs[2]; + + var ys = Object.create(Array.prototype); + ys[0] = 1; + ys[1] = 2; + ys[3] = 4; + + assert.ok( + deepEqual(xs, ys), + 'arrays with deleted elements are only equal to' + + ' arrays with similarly deleted elements' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, undefined, 4 ]), + 'deleted array elements cannot be undefined' + ); + + assert.ok( + !deepEqual(xs, [ 1, 2, null, 4 ]), + 'deleted array elements cannot be null' + ); +}; + +exports.deletedObjectEqual = function () { + var obj = { a : 1, b : 2, c : 3 }; + delete obj.c; + + assert.ok( + deepEqual(obj, { a : 1, b : 2 }), + 'deleted object elements should not show up' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : undefined }), + 'deleted object elements are not undefined' + ); + + assert.ok( + !deepEqual(obj, { a : 1, b : 2, c : null }), + 'deleted object elements are not null' + ); +}; + +exports.emptyKeyEqual = function () { + assert.ok(!deepEqual( + { a : 1 }, { a : 1, '' : 55 } + )); +}; + +exports.deepArguments = function () { + assert.ok( + !deepEqual( + [ 4, 5, 6 ], + (function () { return arguments })(4, 5, 6) + ), + 'arguments are not arrays' + ); + + assert.ok( + deepEqual( + (function () { return arguments })(4, 5, 6), + (function () { return arguments })(4, 5, 6) + ), + 'arguments should equal' + ); +}; + +exports.deepUn = function () { + assert.ok(!deepEqual({ a : 1, b : 2 }, undefined)); + assert.ok(!deepEqual({ a : 1, b : 2 }, {})); + assert.ok(!deepEqual(undefined, { a : 1, b : 2 })); + assert.ok(!deepEqual({}, { a : 1, b : 2 })); + assert.ok(deepEqual(undefined, undefined)); + assert.ok(deepEqual(null, null)); + assert.ok(!deepEqual(undefined, null)); +}; + +exports.deepLevels = function () { + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ]; + assert.ok(!deepEqual(xs, [])); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/instance.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/instance.js new file mode 100644 index 0000000..8d73525 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/instance.js @@ -0,0 +1,17 @@ +var assert = require('assert'); +var Traverse = require('../'); +var EventEmitter = require('events').EventEmitter; + +exports['check instanceof on node elems'] = function () { + + var counts = { emitter : 0 }; + + Traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }]) + .forEach(function (node) { + if (node instanceof EventEmitter) counts.emitter ++; + }) + ; + + assert.equal(counts.emitter, 2); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/interface.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/interface.js new file mode 100644 index 0000000..fce5bf9 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/interface.js @@ -0,0 +1,42 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['interface map'] = function () { + var obj = { a : [ 5,6,7 ], b : { c : [8] } }; + + assert.deepEqual( + Traverse.paths(obj) + .sort() + .map(function (path) { return path.join('/') }) + .slice(1) + .join(' ') + , + 'a a/0 a/1 a/2 b b/c b/c/0' + ); + + assert.deepEqual( + Traverse.nodes(obj), + [ + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } }, + [ 5, 6, 7 ], 5, 6, 7, + { c: [ 8 ] }, [ 8 ], 8 + ] + ); + + assert.deepEqual( + Traverse.map(obj, function (node) { + if (typeof node == 'number') { + return node + 1000; + } + else if (Array.isArray(node)) { + return node.join(' '); + } + }), + { a: '5 6 7', b: { c: '8' } } + ); + + var nodes = 0; + Traverse.forEach(obj, function (node) { nodes ++ }); + assert.deepEqual(nodes, 8); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/json.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/json.js new file mode 100644 index 0000000..0a04529 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/json.js @@ -0,0 +1,47 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['json test'] = function () { + var id = 54; + var callbacks = {}; + var obj = { moo : function () {}, foo : [2,3,4, function () {}] }; + + var scrubbed = Traverse(obj).map(function (x) { + if (typeof x === 'function') { + callbacks[id] = { id : id, f : x, path : this.path }; + this.update('[Function]'); + id++; + } + }); + + assert.equal( + scrubbed.moo, '[Function]', + 'obj.moo replaced with "[Function]"' + ); + + assert.equal( + scrubbed.foo[3], '[Function]', + 'obj.foo[3] replaced with "[Function]"' + ); + + assert.deepEqual(scrubbed, { + moo : '[Function]', + foo : [ 2, 3, 4, "[Function]" ] + }, 'Full JSON string matches'); + + assert.deepEqual( + typeof obj.moo, 'function', + 'Original obj.moo still a function' + ); + + assert.deepEqual( + typeof obj.foo[3], 'function', + 'Original obj.foo[3] still a function' + ); + + assert.deepEqual(callbacks, { + 54: { id: 54, f : obj.moo, path: [ 'moo' ] }, + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] }, + }, 'Check the generated callbacks list'); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/keys.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/keys.js new file mode 100644 index 0000000..7ecd545 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/keys.js @@ -0,0 +1,29 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['sort test'] = function () { + var acc = []; + Traverse({ + a: 30, + b: 22, + id: 9 + }).forEach(function (node) { + if ((! Array.isArray(node)) && typeof node === 'object') { + this.before(function(node) { + this.keys = Object.keys(node); + this.keys.sort(function(a, b) { + a = [a === "id" ? 0 : 1, a]; + b = [b === "id" ? 0 : 1, b]; + return a < b ? -1 : a > b ? 1 : 0; + }); + }); + } + if (this.isLeaf) acc.push(node); + }); + + assert.equal( + acc.join(' '), + '9 30 22', + 'Traversal in a custom order' + ); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/leaves.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/leaves.js new file mode 100644 index 0000000..e520b72 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/leaves.js @@ -0,0 +1,21 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['leaves test'] = function () { + var acc = []; + Traverse({ + a : [1,2,3], + b : 4, + c : [5,6], + d : { e : [7,8], f : 9 } + }).forEach(function (x) { + if (this.isLeaf) acc.push(x); + }); + + assert.equal( + acc.join(' '), + '1 2 3 4 5 6 7 8 9', + 'Traversal in the right(?) order' + ); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js new file mode 100644 index 0000000..4fa07bb --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js @@ -0,0 +1,92 @@ +var traverse = require('../../'); + +module.exports = function (a, b) { + if (arguments.length !== 2) { + throw new Error( + 'deepEqual requires exactly two objects to compare against' + ); + } + + var equal = true; + var node = b; + + traverse(a).forEach(function (y) { + var notEqual = (function () { + equal = false; + //this.stop(); + return undefined; + }).bind(this); + + //if (node === undefined || node === null) return notEqual(); + + if (!this.isRoot) { + /* + if (!Object.hasOwnProperty.call(node, this.key)) { + return notEqual(); + } + */ + if (typeof node !== 'object') return notEqual(); + node = node[this.key]; + } + + var x = node; + + this.post(function () { + node = x; + }); + + var toS = function (o) { + return Object.prototype.toString.call(o); + }; + + if (this.circular) { + if (traverse(b).get(this.circular.path) !== x) notEqual(); + } + else if (typeof x !== typeof y) { + notEqual(); + } + else if (x === null || y === null || x === undefined || y === undefined) { + if (x !== y) notEqual(); + } + else if (x.__proto__ !== y.__proto__) { + notEqual(); + } + else if (x === y) { + // nop + } + else if (typeof x === 'function') { + if (x instanceof RegExp) { + // both regexps on account of the __proto__ check + if (x.toString() != y.toString()) notEqual(); + } + else if (x !== y) notEqual(); + } + else if (typeof x === 'object') { + if (toS(y) === '[object Arguments]' + || toS(x) === '[object Arguments]') { + if (toS(x) !== toS(y)) { + notEqual(); + } + } + else if (x instanceof Date || y instanceof Date) { + if (!(x instanceof Date) || !(y instanceof Date) + || x.getTime() !== y.getTime()) { + notEqual(); + } + } + else { + var kx = Object.keys(x); + var ky = Object.keys(y); + if (kx.length !== ky.length) return notEqual(); + for (var i = 0; i < kx.length; i++) { + var k = kx[i]; + if (!Object.hasOwnProperty.call(y, k)) { + notEqual(); + } + } + } + } + }); + + return equal; +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/mutability.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/mutability.js new file mode 100644 index 0000000..2236f56 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/mutability.js @@ -0,0 +1,252 @@ +var assert = require('assert'); +var Traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.mutate = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).forEach(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mutateT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.forEach(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, res); + assert.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.map = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.mapT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.map(obj, function (x) { + if (typeof x === 'number' && x % 2 === 0) { + this.update(x * 10); + } + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, b : 20, c : [ 3, 40 ] }); +}; + +exports.clone = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).clone(); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.cloneT = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse.clone(obj); + assert.deepEqual(obj, res); + assert.ok(obj !== res); + obj.a ++; + assert.deepEqual(res.a, 1); + obj.c.push(5); + assert.deepEqual(res.c, [ 3, 4 ]); +}; + +exports.reduce = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isLeaf) acc.push(x); + return acc; + }, []); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, [ 1, 2, 3, 4 ]); +}; + +exports.reduceInit = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).reduce(function (acc, x) { + if (this.isRoot) assert.fail('got root'); + return acc; + }); + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, obj); +}; + +exports.remove = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, c : [ 3 ] }); +}; + +exports.removeNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f']) +} + +exports.removeStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.remove(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'f']) +} + +exports.removeMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.remove(); + }); + + assert.deepEqual(obj, { a : 1, b : 2, c : [ 3, 4 ] }); + assert.deepEqual(res, { a : 1, c : [ 3 ] }); +}; + +exports.delete = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null ] } + )); +}; + +exports.deleteNoStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c', 'd', 'e']) +} + +exports.deleteStop = function() { + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } }; + + var keys = []; + Traverse(obj).forEach(function (x) { + keys.push(this.key) + if (this.key == 'c') this.delete(true); + }); + + assert.deepEqual(keys, [undefined, 'a', 'b', 'c']) +} + +exports.deleteRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + Traverse(obj).forEach(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, undefined, 5 ] } + )); + + assert.ok(deepEqual( + obj, { a : 1, c : [ 3 ,, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, null, 5 ] } + )); + + assert.ok(!deepEqual( + obj, { a : 1, c : [ 3, 5 ] } + )); +}; + +exports.deleteMap = function () { + var obj = { a : 1, b : 2, c : [ 3, 4 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4 ] } + )); + + var xs = [ 3, 4 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3, ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ] } + )); +}; + +exports.deleteMapRedux = function () { + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] }; + var res = Traverse(obj).map(function (x) { + if (this.isLeaf && x % 2 == 0) this.delete(); + }); + + assert.ok(deepEqual( + obj, + { a : 1, b : 2, c : [ 3, 4, 5 ] } + )); + + var xs = [ 3, 4, 5 ]; + delete xs[1]; + + assert.ok(deepEqual( + res, { a : 1, c : xs } + )); + + assert.ok(!deepEqual( + res, { a : 1, c : [ 3, 5 ] } + )); + + assert.ok(deepEqual( + res, { a : 1, c : [ 3 ,, 5 ] } + )); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/negative.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/negative.js new file mode 100644 index 0000000..f92dfb0 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/negative.js @@ -0,0 +1,20 @@ +var Traverse = require('../'); +var assert = require('assert'); + +exports['negative update test'] = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + var fixed = Traverse.map(obj, function (x) { + if (x < 0) this.update(x + 128); + }); + + assert.deepEqual(fixed, + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ], + 'Negative values += 128' + ); + + assert.deepEqual(obj, + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ], + 'Original references not modified' + ); +} + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/obj.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/obj.js new file mode 100644 index 0000000..d46fd38 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/obj.js @@ -0,0 +1,15 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports['traverse an object with nested functions'] = function () { + var to = setTimeout(function () { + assert.fail('never ran'); + }, 1000); + + function Cons (x) { + clearTimeout(to); + assert.equal(x, 10); + }; + Traverse(new Cons(10)); +}; + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/siblings.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/siblings.js new file mode 100644 index 0000000..99c0f1b --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/siblings.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.siblings = function () { + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] }; + + var res = traverse(obj).reduce(function (acc, x) { + var p = '/' + this.path.join('/'); + if (this.parent) { + acc[p] = { + siblings : this.parent.keys, + key : this.key, + index : this.parent.keys.indexOf(this.key) + }; + } + else { + acc[p] = { + siblings : [], + key : this.key, + index : -1 + } + } + return acc; + }, {}); + + assert.deepEqual(res, { + '/' : { siblings : [], key : undefined, index : -1 }, + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 }, + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 }, + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 }, + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 }, + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 }, + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 } + }); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stop.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stop.js new file mode 100644 index 0000000..3529847 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stop.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var traverse = require('../'); + +exports.stop = function () { + var visits = 0; + traverse('abcdefghij'.split('')).forEach(function (node) { + if (typeof node === 'string') { + visits ++; + if (node === 'e') this.stop() + } + }); + + assert.equal(visits, 5); +}; + +exports.stopMap = function () { + var s = traverse('abcdefghij'.split('')).map(function (node) { + if (typeof node === 'string') { + if (node === 'e') this.stop() + return node.toUpperCase(); + } + }).join(''); + + assert.equal(s, 'ABCDEfghij'); +}; + +exports.stopReduce = function () { + var obj = { + a : [ 4, 5 ], + b : [ 6, [ 7, 8, 9 ] ] + }; + var xs = traverse(obj).reduce(function (acc, node) { + if (this.isLeaf) { + if (node === 7) this.stop(); + else acc.push(node) + } + return acc; + }, []); + + assert.deepEqual(xs, [ 4, 5, 6 ]); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stringify.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stringify.js new file mode 100644 index 0000000..932f5d3 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stringify.js @@ -0,0 +1,36 @@ +var assert = require('assert'); +var Traverse = require('../'); + +exports.stringify = function () { + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ]; + + var s = ''; + Traverse(obj).forEach(function (node) { + if (Array.isArray(node)) { + this.before(function () { s += '[' }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += ']' }); + } + else if (typeof node == 'object') { + this.before(function () { s += '{' }); + this.pre(function (x, key) { + s += '"' + key + '"' + ':'; + }); + this.post(function (child) { + if (!child.isLast) s += ','; + }); + this.after(function () { s += '}' }); + } + else if (typeof node == 'function') { + s += 'null'; + } + else { + s += node.toString(); + } + }); + + assert.equal(s, JSON.stringify(obj)); +} + diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/subexpr.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/subexpr.js new file mode 100644 index 0000000..a217beb --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/subexpr.js @@ -0,0 +1,34 @@ +var traverse = require('../'); +var assert = require('assert'); + +exports.subexpr = function () { + var obj = [ 'a', 4, 'b', 5, 'c', 6 ]; + var r = traverse(obj).map(function (x) { + if (typeof x === 'number') { + this.update([ x - 0.1, x, x + 0.1 ], true); + } + }); + + assert.deepEqual(obj, [ 'a', 4, 'b', 5, 'c', 6 ]); + assert.deepEqual(r, [ + 'a', [ 3.9, 4, 4.1 ], + 'b', [ 4.9, 5, 5.1 ], + 'c', [ 5.9, 6, 6.1 ], + ]); +}; + +exports.block = function () { + var obj = [ [ 1 ], [ 2 ], [ 3 ] ]; + var r = traverse(obj).map(function (x) { + if (Array.isArray(x) && !this.isRoot) { + if (x[0] === 5) this.block() + else this.update([ [ x[0] + 1 ] ]) + } + }); + + assert.deepEqual(r, [ + [ [ [ [ [ 5 ] ] ] ] ], + [ [ [ [ 5 ] ] ] ], + [ [ [ 5 ] ] ], + ]); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/super_deep.js b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/super_deep.js new file mode 100644 index 0000000..acac2fd --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/super_deep.js @@ -0,0 +1,55 @@ +var assert = require('assert'); +var traverse = require('../'); +var deepEqual = require('./lib/deep_equal'); + +exports.super_deep = function () { + var util = require('util'); + var a0 = make(); + var a1 = make(); + assert.ok(deepEqual(a0, a1)); + + a0.c.d.moo = true; + assert.ok(!deepEqual(a0, a1)); + + a1.c.d.moo = true; + assert.ok(deepEqual(a0, a1)); + + // TODO: this one + //a0.c.a = a1; + //assert.ok(!deepEqual(a0, a1)); +}; + +function make () { + var a = { self : 'a' }; + var b = { self : 'b' }; + var c = { self : 'c' }; + var d = { self : 'd' }; + var e = { self : 'e' }; + + a.a = a; + a.b = b; + a.c = c; + + b.a = a; + b.b = b; + b.c = c; + + c.a = a; + c.b = b; + c.c = c; + c.d = d; + + d.a = a; + d.b = b; + d.c = c; + d.d = d; + d.e = e; + + e.a = a; + e.b = b; + e.c = c; + e.d = d; + e.e = e; + + return a; +} diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/package.json b/node_modules/findit/node_modules/seq/node_modules/hashish/package.json new file mode 100644 index 0000000..33c7f22 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/package.json @@ -0,0 +1,33 @@ +{ + "name" : "hashish", + "version" : "0.0.4", + "description" : "Hash data structure manipulation functions", + "main" : "./index.js", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-hashish.git" + }, + "keywords": [ + "hash", + "object", + "convenience", + "manipulation", + "data structure" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "dependencies" : { + "traverse" : ">=0.2.4" + }, + "devDependencies" : { + "expresso" : ">=0.6.0" + }, + "scripts" : { + "test" : "expresso" + }, + "license" : "MIT/X11", + "engine" : ["node >=0.2.0"] +} diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/test/hash.js b/node_modules/findit/node_modules/seq/node_modules/hashish/test/hash.js new file mode 100644 index 0000000..6afce60 --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/test/hash.js @@ -0,0 +1,250 @@ +var Hash = require('hashish'); +var assert = require('assert'); + +exports.map = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).map(function (v) { return v + 1 }).items; + var hash = Hash.map(ref, function (v) { return v + 1 }); + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 2, b : 3 }); + assert.deepEqual(hash, { a : 2, b : 3 }); +}; + +exports['cloned map'] = function () { + var ref = { foo : [1,2], bar : [4,5] }; + var hash = Hash(ref).clone.map( + function (v) { v.unshift(v[0] - 1); return v } + ).items; + assert.deepEqual(ref.foo, [1,2]); + assert.deepEqual(ref.bar, [4,5]); + assert.deepEqual(hash.foo, [0,1,2]); + assert.deepEqual(hash.bar, [3,4,5]); +}; + +exports.forEach = function () { + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' }; + var xs = []; + Hash(ref).forEach(function (x, i) { + xs.push([ i, x ]); + }); + + assert.eql( + xs.map(function (x) { return x[0] }).sort(), + [ '1337', 'a', 'b', 'c' ] + ); + + assert.eql( + xs.map(function (x) { return x[1] }).sort(), + [ 2, 5, 7, 'leet' ] + ); + + var ys = []; + Hash.forEach(ref, function (x, i) { + ys.push([ i, x ]); + }); + + assert.eql(xs.sort(), ys.sort()); +}; + +exports.filter_items = function () { + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' }; + var items = Hash(ref).filter(function (v, k) { + return v > 5 || k > 5 + }).items; + var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 }); + assert.deepEqual(items, { 1337 : 'leet', c : 7 }); + assert.deepEqual(hash, { 1337 : 'leet', c : 7 }); + assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' }); + assert.equal(Hash(ref).length, 4); +}; + +exports.detect = function () { + var h = { a : 5, b : 6, c : 7, d : 8 }; + var hh = Hash(h); + var gt6hh = hh.detect(function (x) { return x > 6 }); + assert.ok(gt6hh == 7 || gt6hh == 8); + var gt6h = Hash.detect(h, function (x) { return x > 6 }); + assert.ok(gt6h == 7 || gt6h == 8); + assert.equal(hh.detect(function (x) { return x > 100 }), undefined); +}; + +exports.reduce = function () { + var ref = { foo : [1,2], bar : [4,5] }; + + var sum1 = Hash(ref).reduce(function (acc, v) { + return acc + v.length + }, 0); + assert.equal(sum1, 4); + + var sum2 = Hash.reduce(ref, function (acc, v) { + return acc + v.length + }, 0); + assert.equal(sum2, 4); +}; + +exports.some = function () { + var h = { a : 5, b : 6, c : 7, d : 8 }; + var hh = Hash(h); + assert.ok(Hash.some(h, function (x) { return x > 7 })); + assert.ok(Hash.some(h, function (x) { return x < 6 })); + assert.ok(!Hash.some(h, function (x) { return x > 10 })); + assert.ok(!Hash.some(h, function (x) { return x < 0 })); + + assert.ok(hh.some(function (x) { return x > 7 })); + assert.ok(hh.some(function (x) { return x < 6 })); + assert.ok(!hh.some(function (x) { return x > 10 })); + assert.ok(!hh.some(function (x) { return x < 0 })); +}; + +exports.update = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).clone.update({ c : 3, a : 0 }).items; + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 0, b : 2, c : 3 }); + + var hash = Hash.update(ref, { c : 3, a : 0 }); + assert.deepEqual(ref, hash); + assert.deepEqual(hash, { a : 0, b : 2, c : 3 }); + + var ref2 = {a: 1}; + var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 }); + assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 }); +}; + +exports.merge = function () { + var ref = { a : 1, b : 2 }; + var items = Hash(ref).merge({ b : 3, c : 3.14 }).items; + var hash = Hash.merge(ref, { b : 3, c : 3.14 }); + + assert.deepEqual(ref, { a : 1, b : 2 }); + assert.deepEqual(items, { a : 1, b : 3, c : 3.14 }); + assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 }); + + var ref2 = { a : 1 }; + var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 }); + assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 }); +}; + +exports.has = function () { + var h = { a : 4, b : 5 }; + var hh = Hash(h); + + assert.ok(hh.has('a')); + assert.equal(hh.has('c'), false); + assert.ok(hh.has(['a','b'])); + assert.equal(hh.has(['a','b','c']), false); + + assert.ok(Hash.has(h, 'a')); + assert.equal(Hash.has(h, 'c'), false); + assert.ok(Hash.has(h, ['a','b'])); + assert.equal(Hash.has(h, ['a','b','c']), false); +}; + +exports.valuesAt = function () { + var h = { a : 4, b : 5, c : 6 }; + assert.equal(Hash(h).valuesAt('a'), 4); + assert.equal(Hash(h).valuesAt(['a'])[0], 4); + assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]); + assert.equal(Hash.valuesAt(h, 'a'), 4); + assert.deepEqual(Hash.valuesAt(h, ['a']), [4]); + assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]); +}; + +exports.tap = function () { + var h = { a : 4, b : 5, c : 6 }; + var hh = Hash(h); + hh.tap(function (x) { + assert.ok(this === hh) + assert.eql(x, h); + }); + + Hash.tap(h, function (x) { + assert.eql( + Object.keys(this).sort(), + Object.keys(hh).sort() + ); + assert.eql(x, h); + }); +}; + +exports.extract = function () { + var hash = Hash({ a : 1, b : 2, c : 3 }).clone; + var extracted = hash.extract(['a','b']); + assert.equal(extracted.length, 2); + assert.deepEqual(extracted.items, { a : 1, b : 2 }); +}; + +exports.exclude = function () { + var hash = Hash({ a : 1, b : 2, c : 3 }).clone; + var extracted = hash.exclude(['a','b']); + assert.equal(extracted.length, 1); + assert.deepEqual(extracted.items, { c : 3 }); +}; + +exports.concat = function () { + var ref1 = { a : 1, b : 2 }; + var ref2 = { foo : 100, bar : 200 }; + var ref3 = { b : 3, c : 4, bar : 300 }; + + assert.deepEqual( + Hash.concat([ ref1, ref2 ]), + { a : 1, b : 2, foo : 100, bar : 200 } + ); + + assert.deepEqual( + Hash.concat([ ref1, ref2, ref3 ]), + { a : 1, b : 3, c : 4, foo : 100, bar : 300 } + ); +}; + +exports.zip = function () { + var xs = ['a','b','c']; + var ys = [1,2,3,4]; + var h = Hash(xs,ys); + assert.equal(h.length, 3); + assert.deepEqual(h.items, { a : 1, b : 2, c : 3 }); + + var zipped = Hash.zip(xs,ys); + assert.deepEqual(zipped, { a : 1, b : 2, c : 3 }); +}; + +exports.length = function () { + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3); + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3); + assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3); +}; + +exports.compact = function () { + var hash = { + a : 1, + b : undefined, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + }; + var compacted = Hash(hash).compact; + assert.deepEqual( + { + a : 1, + b : undefined, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + }, + hash, 'compact modified the hash' + ); + assert.deepEqual( + compacted.items, + { + a : 1, + c : false, + d : 4, + e : [ undefined, 4 ], + f : null + } + ); + var h = Hash.compact(hash); + assert.deepEqual(h, compacted.items); +}; diff --git a/node_modules/findit/node_modules/seq/node_modules/hashish/test/property.js b/node_modules/findit/node_modules/seq/node_modules/hashish/test/property.js new file mode 100644 index 0000000..1183c5d --- /dev/null +++ b/node_modules/findit/node_modules/seq/node_modules/hashish/test/property.js @@ -0,0 +1,69 @@ +var Hash = require('hashish'); +var assert = require('assert'); +var vm = require('vm'); +var fs = require('fs'); + +var src = fs.readFileSync(__dirname + '/../index.js', 'utf8'); + +exports.defineGetter = function () { + var context = { + module : { exports : {} }, + Object : { + keys : Object.keys, + defineProperty : undefined, + }, + require : require, + }; + context.exports = context.module.exports; + + vm.runInNewContext('(function () {' + src + '})()', context); + var Hash_ = context.module.exports; + + var times = 0; + Hash_.__proto__.__proto__.__defineGetter__ = function () { + times ++; + return Object.__defineGetter__.apply(this, arguments); + }; + + assert.equal(vm.runInNewContext('Object.defineProperty', context), null); + + assert.deepEqual( + Hash_({ a : 1, b : 2, c : 3 }).values, + [ 1, 2, 3 ] + ); + + assert.ok(times > 5); +}; + +exports.defineProperty = function () { + var times = 0; + var context = { + module : { exports : {} }, + Object : { + keys : Object.keys, + defineProperty : function (prop) { + times ++; + if (prop.get) throw new TypeError('engine does not support') + assert.fail('should have asserted by now'); + }, + }, + require : require + }; + context.exports = context.module.exports; + + vm.runInNewContext('(function () {' + src + '})()', context); + var Hash_ = context.module.exports; + + Hash_.__proto__.__proto__.__defineGetter__ = function () { + assert.fail('getter called when a perfectly good' + + ' defineProperty was available' + ); + }; + + assert.deepEqual( + Hash_({ a : 1, b : 2, c : 3 }).values, + [ 1, 2, 3 ] + ); + + assert.equal(times, 1); +}; diff --git a/node_modules/findit/node_modules/seq/package.json b/node_modules/findit/node_modules/seq/package.json new file mode 100644 index 0000000..0c971d6 --- /dev/null +++ b/node_modules/findit/node_modules/seq/package.json @@ -0,0 +1,33 @@ +{ + "name" : "seq", + "version" : "0.3.5", + "description" : "Chainable asynchronous flow control with sequential and parallel primitives and pipeline-style error handling", + "main" : "./index.js", + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-seq.git" + }, + "dependencies" : { + "chainsaw" : ">=0.0.7 <0.1", + "hashish" : ">=0.0.2 <0.1" + }, + "devDependencies" : { + "expresso" : ">=0.7.x" + }, + "script" : { + "test" : "expresso" + }, + "keywords" : [ + "flow-control", "flow", "control", "async", "asynchronous", "chain", + "pipeline", "sequence", "sequential", "parallel", "error" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : { + "node" : ">=0.4.0" + } +} diff --git a/node_modules/findit/node_modules/seq/test/readdir.js b/node_modules/findit/node_modules/seq/test/readdir.js new file mode 100644 index 0000000..fe1a38b --- /dev/null +++ b/node_modules/findit/node_modules/seq/test/readdir.js @@ -0,0 +1,35 @@ +var assert = require('assert'); +var Seq = require('seq'); +var fs = require('fs'); + +exports.readdir = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 500); + + Seq() + .seq(fs.readdir, __dirname, Seq) + .seq(function (files) { + clearTimeout(to); + assert.ok(files.length >= 2); + }) + .catch(assert.fail) + ; +}; + +exports.readdirs = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 500); + + Seq() + .par(fs.readdir, __dirname, Seq) + .par(fs.readdir, __dirname + '/../examples', Seq) + .seq(function (tests, examples) { + clearTimeout(to); + assert.ok(tests.length >= 2); + assert.ok(examples.length >= 2); + }) + .catch(assert.fail) + ; +}; diff --git a/node_modules/findit/node_modules/seq/test/seq.js b/node_modules/findit/node_modules/seq/test/seq.js new file mode 100644 index 0000000..2e34aec --- /dev/null +++ b/node_modules/findit/node_modules/seq/test/seq.js @@ -0,0 +1,946 @@ +var Seq = require('seq'); +var assert = require('assert'); + +exports.seq = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 100); + + Seq([0]) + .seq('pow', function (n) { + this(null, 1); + }) + .seq(function (n) { + assert.eql(n, 1); + assert.eql(n, this.vars.pow); + var seq = this; + setTimeout(function () { seq(null, 2) }, 25); + assert.eql(this.stack, [n]); + }) + .seq(function (n) { + assert.eql(n, 2); + assert.eql(this.stack, [n]); + this(null, 5, 6, 7); + }) + .seq(function (x, y, z) { + clearTimeout(to); + assert.eql([x,y,z], [5,6,7]); + }) + ; +}; + +exports.into = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 10); + var calls = 0; + + Seq([3,4,5]) + .seq(function () { + this.into('w')(null, 5); + }) + .seq(function (w) { + clearTimeout(to); + assert.eql(w, this.vars.w); + assert.eql(arguments.length, 1); + assert.eql(w, 5); + }) + ; +}; + +exports.catchSeq = function () { + var to = setTimeout(function () { + assert.fail('never caught the error'); + }, 100); + + var tf = setTimeout(function () { + assert.fail('final action never executed'); + }, 100); + + var calls = {}; + Seq([1]) + .seq(function (n) { + assert.eql(n, 1); + calls.before = true; + this('pow!'); + calls.after = true; + }) + .seq(function (n) { + calls.next = true; + assert.fail('should have skipped this'); + }) + .catch(function (err) { + assert.eql(err, 'pow!'); + assert.ok(calls.before); + assert.ok(!calls.after); + assert.ok(!calls.next); + clearTimeout(to); + }) + .do(function () { + //assert.ok(calls.after); + clearTimeout(tf); + }) + ; +}; + +exports.par = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 1000); + + Seq() + .seq(function () { + this(null, 'mew'); + }) + .par(function () { + var seq = this; + setTimeout(function () { seq(null, 'x') }, 50); + }) + .par(function () { + var seq = this; + setTimeout(function () { seq(null, 'y') }, 25); + }) + .par('z', function () { + this(null, 42); + }) + .seq(function (x, y, z) { + clearTimeout(to); + assert.eql(x, 'x'); + assert.eql(y, 'y'); + assert.eql(z, 42); + assert.eql(this.args, { 0 : ['x'], 1 : ['y'], z : [42] }); + assert.eql(this.stack, [ 'x', 'y', 42 ]); + assert.eql(this.vars, { z : 42 }); + }) + ; +}; + +exports.catchPar = function () { + var done = false, caught = false; + var tc = setTimeout(function () { + assert.fail('error not caught'); + }, 1000); + + Seq() + .par('one', function () { + setTimeout(this.bind({}, 'rawr'), 25); + }) + .par('two', function () { + setTimeout(this.bind({}, null, 'y'), 50); + }) + .seq(function (x, y) { + assert.fail('seq fired with error above'); + }) + .catch(function (err, key) { + clearTimeout(tc); + assert.eql(err, 'rawr'); + assert.eql(key, 'one'); + }) + ; +}; + +exports.catchParWithoutSeq = function () { + var done = false, caught = false; + var tc = setTimeout(function () { + assert.fail('error not caught'); + }, 5000); + + Seq() + .par('one', function () { + setTimeout(this.bind({}, 'rawr'), 25); + }) + .par('two', function () { + setTimeout(this.bind({}, null, 'y'), 50); + }) + .catch(function (err, key) { + clearTimeout(tc); + assert.eql(err, 'rawr'); + assert.eql(key, 'one'); + }) + ; +} + +exports.catchParMultipleErrors = function() { + var caught={}; + var to = setTimeout(function() { + assert.fail('Never finished'); + }, 1000); + var times = 0; + + Seq() + .par('one', function() { + setTimeout(this.bind({}, 'rawr1'), 25); + }) + .par('two', function() { + setTimeout(this.bind({}, 'rawr2'), 50); + }) + .catch(function(err,key) { + caught[key] = err; + }) + .seq(function() { + clearTimeout(to); + times ++; + assert.eql(times, 1); + assert.eql(caught, { one:'rawr1', two:'rawr2' }); + }) + ; +}; + +exports.catchParThenSeq = function () { + var tc = setTimeout(function () { + assert.fail('error not caught'); + }, 1000); + var tf = setTimeout(function () { + assert.fail('final seq not run'); + }, 500); + var times = 0; + var errs = [ + { key : 'one', msg : 'rawr' }, + { key : 'four', msg : 'pow' }, + ]; + + Seq() + .par('one', function () { + setTimeout(this.bind({}, 'rawr'), 25); + }) + .par('two', function () { + setTimeout(this.bind({}, null, 'y'), 50); + }) + .par('three', function () { + setTimeout(this.bind({}, null, 'z'), 30); + }) + .par('four', function () { + setTimeout(this.bind({}, 'pow'), 45); + }) + .seq(function (x, y) { + assert.fail('seq fired with error above'); + }) + .catch(function (err, key) { + clearTimeout(tc); + var e = errs.shift(); + assert.eql(err, e.msg); + assert.eql(key, e.key); + }) + .seq(function () { + clearTimeout(tf); + times ++; + assert.eql(times, 1); + }) + ; +} + +exports.forEach = function () { + var to = setTimeout(function () { + assert.fail('seq never fired after forEach'); + }, 25); + + var count = 0; + Seq([1,2,3]) + .push(4) + .forEach(function (x, i) { + assert.eql(x - 1, i); + count ++; + }) + .seq(function () { + clearTimeout(to); + assert.eql(count, 4); + }) + ; +}; + +exports.seqEach = function () { + var to = setTimeout(function () { + assert.fail('seqEach never finished'); + }, 25); + + var count = 0; + var ii = 0; + Seq([1,2,3]) + .seqEach(function (x, i) { + assert.eql(i, ii++); + assert.eql(x, [1,2,3][i]); + count ++; + this(null); + }) + .seq(function () { + clearTimeout(to); + assert.eql(count, 3); + }) + ; +}; + +exports.seqEachCatch = function () { + var to = setTimeout(function () { + assert.fail('never caught the error'); + }, 25); + var tf = setTimeout(function () { + assert.fail('never resumed afterwards'); + }, 25); + + var meows = []; + + var values = []; + Seq([1,2,3,4]) + .seqEach(function (x, i) { + values.push([i,x]); + assert.eql(x - 1, i); + if (i >= 2) this('meow ' + i) + else this(null, x * 10); + }) + .seq(function (xs) { + assert.fail('should fail before this action'); + }) + .catch(function (err) { + clearTimeout(to); + meows.push(err); + assert.eql(err, 'meow 2'); + assert.eql(values, [[0,1],[1,2],[2,3]]); + }) + .seq(function () { + clearTimeout(tf); + }) + ; +}; + +exports.parEach = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + var values = []; + Seq([1,2,3,4]) + .parEach(function (x, i) { + values.push([i,x]); + setTimeout(this.bind({}, null), 20); + }) + .seq(function () { + assert.deepEqual(this.stack, [1,2,3,4]) + assert.deepEqual(values, [[0,1],[1,2],[2,3],[3,4]]); + clearTimeout(to); + }) + ; +}; + +exports.parEachVars = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 1000); + var values = []; + + Seq() + .seq('abc', function () { + this(null, 'a', 'b', 'c'); + }) + .parEach(function (x) { + values.push(x); + setTimeout(this.bind(this, null), Math.floor(Math.random() * 50)); + }) + .seq(function () { + clearTimeout(to); + assert.eql(values, ['a','b','c']); + assert.eql(this.stack, ['a','b','c']); + assert.eql(this.vars.abc, 'a'); + }) + ; +}; + +exports.parEachInto = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + Seq([1,2,3,4]) + .parEach(function (x, i) { + setTimeout((function () { + this.into('abcd'.charAt(i))(null, x); + }).bind(this), 20); + }) + .seq(function () { + clearTimeout(to); + assert.deepEqual(this.stack, [1,2,3,4]) + assert.deepEqual(this.vars, { a : 1, b : 2, c : 3, d : 4 }); + }) + ; +}; + +exports.parEachCatch = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + var values = []; + Seq([1,2,3,4]) + .parEach(function (x, i) { + values.push([i,x]); + setTimeout(this.bind({}, 'zing'), 10); + }) + .seq(function () { + assert.fail('should have errored before this point') + }) + .catch(function (err) { + clearTimeout(to); + assert.eql(err, 'zing'); + assert.deepEqual(values, [[0,1],[1,2],[2,3],[3,4]]); + }) + ; +}; + +exports.parEachLimited = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parEach(3, function (x, i) { + running ++; + + assert.ok(running <= 3); + + values.push([i,x]); + setTimeout((function () { + running --; + this(null); + }).bind(this), 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(values, + [[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,10]] + ); + }) + ; +}; + +exports.parMap = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parMap(2, function (x, i) { + running ++; + + assert.ok(running <= 2); + + setTimeout((function () { + running --; + this(null, x * 10); + }).bind(this), Math.floor(Math.random() * 100)); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [10,20,30,40,50,60,70,80,90,100]); + assert.eql(this.stack, [].slice.call(arguments)); + }) + ; +}; + +exports.parMapFast = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parMap(function (x, i) { + this(null, x * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [10,20,30,40,50,60,70,80,90,100]); + assert.eql(this.stack, [].slice.call(arguments)); + }) + ; +}; + +exports.parMapInto = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parMap(function (x, i) { + this.into(9 - i)(null, x * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]); + assert.eql(this.stack, [].slice.call(arguments)); + }) + ; +}; + +exports.seqMap = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .seqMap(function (x, i) { + running ++; + + assert.eql(running, 1); + + setTimeout((function () { + running --; + this(null, x * 10); + }).bind(this), 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [10,20,30,40,50,60,70,80,90,100]); + }) + ; +}; + + +exports.seqMapInto = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .seqMap(function (x, i) { + running ++; + + assert.eql(running, 1); + + setTimeout((function () { + running --; + this.into(9 - i)(null, x * 10); + }).bind(this), 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [100, 90, 80, 70, 60, 50, 40, 30, 20, 10]); + }) + ; +}; + +exports.parFilter = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parFilter(2, function (x, i) { + running ++; + + assert.ok(running <= 2); + + setTimeout((function () { + running --; + this(null, x % 2 === 0); + }).bind(this), Math.floor(Math.random() * 100)); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [2,4,6,8,10]); + assert.eql(this.stack, [].slice.call(arguments)); + }) + ; +}; + +exports.seqFilter = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .seqFilter(function (x, i) { + running ++; + + assert.eql(running, 1); + + setTimeout((function () { + running --; + this(null, x % 2 === 0); + }).bind(this), 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [2,4,6,8,10]); + }) + ; +}; + +exports.parFilterInto = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .parFilter(2, function (x, i) { + running ++; + + assert.ok(running <= 2); + + setTimeout((function () { + running --; + this.into(x % 3)(null, x % 2 === 0); + }).bind(this), Math.floor(Math.random() * 100)); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [ 6, 10, 4, 2, 8 ]); + assert.eql(this.stack, [].slice.call(arguments)); + }) + ; +}; + +exports.seqFilterInto = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 500); + + var running = 0; + var values = []; + Seq([1,2,3,4,5,6,7,8,9,10]) + .seqFilter(function (x, i) { + running ++; + + assert.eql(running, 1); + + setTimeout((function () { + running --; + this.into(x % 3)(null, x % 2 === 0); + }).bind(this), 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(this.stack, [ 6, 10, 4, 2, 8 ]); + }) + ; +}; + +exports.stack = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + Seq([4,5,6]) + .seq(function (x, y, z) { + assert.eql(arguments.length, 3); + assert.eql([x,y,z], [4,5,6]); + assert.eql(this.stack, [4,5,6]); + this(null); + }) + .set([3,4]) + .seq(function (x, y) { + assert.eql(arguments.length, 2); + assert.eql([x,y], [3,4]); + assert.eql(this.stack, [3,4]); + this(null); + }) + .empty() + .seq(function () { + assert.eql(arguments.length, 0); + assert.eql(this.stack, []); + this.next(null, ['a']); + }) + .extend(['b','c']) + .seq(function (a, b, c) { + assert.eql(arguments.length, 3); + assert.eql([a,b,c], ['a','b','c']); + assert.eql(this.stack, ['a','b','c']); + this.pass(null); + }) + .pop() + .push('c', 'd', 'e') + .seq(function (a, b, c, d, e) { + assert.eql(arguments.length, 5); + assert.eql([a,b,c,d,e], ['a','b','c','d','e']); + assert.eql(this.stack, ['a','b','c','d','e']); + this.pass(null); + }) + .shift() + .shift() + .seq(function (c, d, e) { + assert.eql(arguments.length, 3); + assert.eql([c,d,e], ['c','d','e']); + assert.eql(this.stack, ['c','d','e']); + this.pass(null); + }) + .set([['a',['b']],['c','d',['e']]]) + .flatten(false) // only flatten one level + .seq(function (a, b, c, d, e) { + assert.eql(arguments.length, 5); + assert.eql([a,b,c,d,e], ['a',['b'],'c','d',['e']]); + assert.eql(this.stack, ['a',['b'],'c','d',['e']]); + this.pass(null); + }) + .set([['a','b'],['c','d',['e']]]) + .flatten() + .seq(function (a, b, c, d, e) { + assert.eql(arguments.length, 5); + assert.eql([a,b,c,d,e], ['a','b','c','d','e']); + assert.eql(this.stack, ['a','b','c','d','e']); + this.pass(null); + }) + .splice(2, 2) + .seq(function (a, b, e) { + assert.eql(arguments.length, 3); + assert.eql([a,b,e], ['a','b','e']); + assert.eql(this.stack, ['a','b','e']); + this.pass(null); + }) + .reverse() + .seq(function (a, b, e){ + assert.eql(arguments.length, 3); + assert.eql([a,b,e], ['e','b','a']); + assert.eql(this.stack, ['e','b','a']); + this.pass(null); + }) + .map(function(ch){ return ch.toUpperCase(); }) + .seq(function (A, B, E){ + assert.eql(arguments.length, 3); + assert.eql([A,B,E], ['E','B','A']); + assert.eql(this.stack, ['E','B','A']); + this.pass(null); + }) + .reduce(function(s, ch){ return s + ':' + ch; }) + .seq(function (acc){ + assert.eql(arguments.length, 1); + assert.eql(acc, 'E:B:A'); + assert.eql(this.stack, ['E:B:A']); + this.pass(null); + }) + .seq(function () { + clearTimeout(to); + this(null); + }) + ; +}; + +exports.ap = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + var cmp = [1,2,3]; + Seq.ap([1,2,3]) + .seqEach(function (x) { + assert.eql(cmp.shift(), x); + this(null); + }) + .seq(function () { + clearTimeout(to); + assert.eql(cmp, []); + }) + ; + + assert.throws(function () { + Seq.ap({ a : 1, b : 2 }); + }); +}; + +exports.seqBind = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + Seq([4,5]) + .seq(function (a, b, c, d) { + assert.eql(a, 2); + assert.eql(b, 3); + assert.eql(c, 4); + assert.eql(d, 5); + this(null); + }, 2, 3) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.parBind = function () { + var t1 = setTimeout(function () { + assert.fail('1 never finished'); + }, 500); + var t2 = setTimeout(function () { + assert.fail('2 never finished'); + }, 500); + var t3 = setTimeout(function () { + assert.fail('3 never finished'); + }, 500); + + Seq(['c']) + .par(function (a, b, c) { + clearTimeout(t1); + assert.eql(a, 'a'); + assert.eql(b, 'b'); + assert.eql(c, 'c'); + this(null); + }, 'a', 'b') + .par(function (x, c) { + clearTimeout(t2); + assert.eql(x, 'x'); + assert.eql(c, 'c'); + this(null); + }, 'x') + .seq(function () { + clearTimeout(t3); + }) + ; +}; + +exports.emptySeqEach = function () { + var to = setTimeout(function () { + assert.fail('never finished'); + }, 100); + + Seq() + .seqEach(function (x) { + assert.fail('no elements'); + }) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.emptyForEach = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + Seq() + .forEach(function () { + assert.fail('non-empty stack'); + }) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.emptyParEach = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + Seq() + .parEach(function () { + assert.fail('non-empty stack'); + }) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.emptyParMap = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + Seq() + .parMap(function () { + assert.fail('non-empty stack'); + }) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.emptySeqMap = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + Seq() + .seqMap(function () { + assert.fail('non-empty stack'); + }) + .seq(function () { + clearTimeout(to); + }) + ; +}; + +exports.ok = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + function moo1 (cb) { cb(3) } + function moo2 (cb) { cb(4) } + + Seq() + .par(function () { moo1(this.ok) }) + .par(function () { moo2(this.ok) }) + .seq(function (x, y) { + clearTimeout(to); + assert.eql(x, 3); + assert.eql(y, 4); + }) + ; +}; + +exports.nextOk = function () { + var to = setTimeout(function () { + assert.fail('seq never fired'); + }, 500); + + function moo1 (cb) { cb(3) } + function moo2 (cb) { cb(4) } + + Seq() + .par_(function (next) { moo1(next.ok) }) + .par_(function (next) { moo2(next.ok) }) + .seq_(function (next, x, y) { + assert.eql(x, 3); + assert.eql(y, 4); + next.ok([ 1, 2, 3 ]) + }) + .flatten() + .parMap_(function (next, x) { + next.ok(x * 100) + }) + .seq_(function (next) { + clearTimeout(to); + assert.deepEqual(next.stack, [ 100, 200, 300 ]); + }) + ; +}; + +exports.regressionTestForAccidentalDeepTraversalOfTheContext = function () { + // Create a single-item stack with a bunch of references to other objects: + var stack = [{}]; + for (var i = 0 ; i < 10000 ; i += 1) { + stack[0][i] = stack[0]; + } + + var startTime = new Date(), + numCalled = 0, + to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 1000); + + Seq(stack) + .parEach(function (item) { + numCalled += 1; + this(); + }) + .seq(function () { + clearTimeout(to); + assert.eql(numCalled, 1); + assert.ok((new Date().getTime() - startTime) < 1000, 'if this test takes longer than a second, the bug must have been reintroduced'); + }); +}; diff --git a/node_modules/findit/node_modules/seq/test/seq_.js b/node_modules/findit/node_modules/seq/test/seq_.js new file mode 100644 index 0000000..369cc86 --- /dev/null +++ b/node_modules/findit/node_modules/seq/test/seq_.js @@ -0,0 +1,149 @@ +var Seq = require('seq'); +var assert = require('assert'); + +exports.seq_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + Seq(['xxx']) + .seq_('pow', function (next, x) { + assert.eql(next, this); + assert.eql(x, 'xxx'); + next(null, 'yyy'); + }) + .seq(function (y) { + clearTimeout(to); + assert.eql(y, 'yyy'); + assert.eql(this.vars.pow, 'yyy'); + }) + ; +}; + +exports.par_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + Seq() + .par_(function (next) { + assert.eql(next, this); + next(null, 111); + }) + .par_(function (next) { + assert.eql(next, this); + next(null, 222); + }) + .seq(function (x, y) { + clearTimeout(to); + assert.eql(x, 111); + assert.eql(y, 222); + }) + ; +}; + +exports.forEach_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + var acc = []; + Seq([7,8,9]) + .forEach_(function (next, x) { + assert.eql(next, this); + acc.push(x); + }) + .seq(function () { + clearTimeout(to); + assert.eql(acc, [ 7, 8, 9 ]); + }) + ; +}; + +exports.seqEach_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + var acc = []; + Seq([7,8,9]) + .seqEach_(function (next, x) { + assert.eql(next, this); + acc.push(x); + setTimeout(function () { + next(null, x); + }, Math.random() * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(acc, [ 7, 8, 9 ]); + assert.eql(this.stack, [ 7, 8, 9 ]); + }) + ; +}; + +exports.parEach_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + var acc = []; + Seq([7,8,9]) + .parEach_(function (next, x) { + assert.eql(next, this); + acc.push(x); + setTimeout(function () { + next(null, x); + }, Math.random() * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(acc, [ 7, 8, 9 ]); + assert.eql(this.stack, [ 7, 8, 9 ]); + }) + ; +}; + +exports.seqMap_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + var acc = []; + Seq([7,8,9]) + .seqMap_(function (next, x) { + assert.eql(next, this); + acc.push(x); + setTimeout(function () { + next(null, x * 10); + }, Math.random() * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(acc, [ 7, 8, 9 ]); + assert.eql(this.stack, [ 70, 80, 90 ]); + }) + ; +}; + +exports.parMap_ = function () { + var to = setTimeout(function () { + assert.fail('never got to the end of the chain'); + }, 5000); + + var acc = []; + Seq([7,8,9]) + .parMap_(function (next, x) { + assert.eql(next, this); + acc.push(x); + setTimeout(function () { + next(null, x * 10); + }, Math.random() * 10); + }) + .seq(function () { + clearTimeout(to); + assert.eql(acc, [ 7, 8, 9 ]); + assert.eql(this.stack, [ 70, 80, 90 ]); + }) + ; +}; diff --git a/node_modules/findit/package.json b/node_modules/findit/package.json new file mode 100644 index 0000000..d0c2ec9 --- /dev/null +++ b/node_modules/findit/package.json @@ -0,0 +1,31 @@ +{ + "name" : "findit", + "version" : "0.1.1", + "description" : "Walk a directory tree.", + "main" : "./index.js", + "dependencies" : { + "seq" : ">=0.1.7" + }, + "devDependencies" : { + "hashish" : ">=0.0.2 <0.1", + "expresso" : "0.7.x" + }, + "repository" : { + "type" : "git", + "url" : "http://github.com/substack/node-findit.git" + }, + "keywords" : [ + "find", + "walk", + "directory", + "recursive", + "tree" + ], + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + }, + "license" : "MIT/X11", + "engine" : ["node >=0.2.0"] +} diff --git a/node_modules/findit/test/cb.js b/node_modules/findit/test/cb.js new file mode 100644 index 0000000..dd535e7 --- /dev/null +++ b/node_modules/findit/test/cb.js @@ -0,0 +1,24 @@ +var assert = require('assert'); +var path = require('path'); +var find = require('../'); + +exports.cbSync = function () { + var files = []; + var dirs = []; + find.sync(__dirname + '/foo', function (file, stat) { + if (stat.isDirectory()) dirs.push(file) + else files.push(file) + }); + + function equal (xs, ys) { + assert.deepEqual( + xs.sort().map(function (x) { + return path.relative(__dirname + '/foo', x) + }), + ys.sort() + ); + } + + equal(dirs, [ 'a', 'a/b', 'a/b/c' ]); + equal(files, [ 'x', 'a/y', 'a/b/z', 'a/b/c/w' ]); +}; diff --git a/node_modules/findit/test/cycle.js b/node_modules/findit/test/cycle.js new file mode 100644 index 0000000..3296387 --- /dev/null +++ b/node_modules/findit/test/cycle.js @@ -0,0 +1,41 @@ +var assert = require('assert'); +var findit = require('../'); +var Hash = require('hashish'); + +exports.cycle = function () { + var find = findit.find(__dirname + '/cycle'); + var found = { directory : [], file : [], path : [] }; + + find.on('directory', function (dir) { + found.directory.push(dir); + }); + + find.on('file', function (file) { + found.file.push(file); + }); + + find.on('path', function (file) { + found.path.push(file); + }); + + var to = setTimeout(function () { + assert.fail('never ended'); + }, 5000); + + find.on('end', function () { + clearTimeout(to); + var dirs = Hash.map({ + directory : [ 'meep', 'meep/moop' ], + file : [], + path : [ 'meep', 'meep/moop' ] + }, function (x) { + return x.map(function (dir) { + return __dirname + '/cycle/' + dir + }) + }); + + assert.deepEqual(dirs.directory, found.directory); + assert.deepEqual(dirs.file, found.file); + assert.deepEqual(dirs.path, found.path); + }); +}; diff --git a/node_modules/findit/test/foo.js b/node_modules/findit/test/foo.js new file mode 100644 index 0000000..ba0c1cb --- /dev/null +++ b/node_modules/findit/test/foo.js @@ -0,0 +1,79 @@ +var assert = require('assert'); +var find = require('../').find; +var findSync = require('../').findSync; + +exports.foo = function () { + var to = setTimeout(function () { + assert.fail('Never caught "end"'); + }, 5000); + + var ps = {}; + var finder = find(__dirname + '/foo', function (file, stat) { + ps[file] = stat.isDirectory(); + }); + + var paths = [] + finder.on('path', function (p) { + paths.push(p); + }); + + var dirs = [] + finder.on('directory', function (dir) { + dirs.push(dir); + }); + + var files = [] + finder.on('file', function (file) { + files.push(file); + }); + + finder.on('end', function () { + clearTimeout(to); + var ref = { + 'a' : true, + 'a/b' : true, + 'a/b/c' : true, + 'x' : false, + 'a/y' : false, + 'a/b/z' : false, + 'a/b/c/w' : false, + }; + + assert.eql(Object.keys(ref).length, Object.keys(ps).length); + var count = { dirs : 0, files : 0, paths : 0 }; + + Object.keys(ref).forEach(function (key) { + var file = __dirname + '/foo/' + key; + assert.eql(ref[key], ps[file]); + if (ref[key]) { + assert.ok(dirs.indexOf(file) >= 0); + count.dirs ++; + } + else { + assert.ok(files.indexOf(file) >= 0); + count.files ++; + } + }); + + assert.eql(count.dirs, dirs.length); + assert.eql(count.files, files.length); + assert.eql(paths.sort(), Object.keys(ps).sort()); + }); +}; + +exports.fooSync = function () { + assert.eql( + findSync(__dirname + '/foo') + .reduce(function (files, file) { + files[file] = true; + return files; + }, {}), + [ 'a', 'a/b', 'a/b/c', 'x', 'a/y', 'a/b/z', 'a/b/c/w' ] + .reduce(function (files, file) { + files[__dirname + '/foo/' + file] = true; + return files; + }, {}) + ); + + assert.eql(findSync(__dirname + '/foo/x'), [ __dirname + '/foo/x' ]); +}; diff --git a/node_modules/findit/test/foo/a/b/c/w b/node_modules/findit/test/foo/a/b/c/w new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/findit/test/foo/a/b/z b/node_modules/findit/test/foo/a/b/z new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/findit/test/foo/a/y b/node_modules/findit/test/foo/a/y new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/findit/test/foo/x b/node_modules/findit/test/foo/x new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/findit/test/module.js b/node_modules/findit/test/module.js new file mode 100644 index 0000000..046274f --- /dev/null +++ b/node_modules/findit/test/module.js @@ -0,0 +1,29 @@ +var assert = require('assert'); +var find = require('../'); + +exports.module = function () { + assert.eql(find.findSync, find.find.sync); + assert.eql(find, find.find); +}; + +exports.file = function () { + var to = setTimeout(function () { + assert.fail('never ended'); + }, 5000); + + var finder = find(__filename); + var files = []; + finder.on('file', function (file) { + assert.equal(file, __filename); + files.push(file); + }); + + finder.on('directory', function (dir) { + assert.fail(dir); + }); + + finder.on('end', function () { + clearTimeout(to); + assert.deepEqual(files, [ __filename ]); + }); +}; diff --git a/node_modules/mkdirp/.gitignore b/node_modules/mkdirp/.gitignore new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mkdirp/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mkdirp/.gitignore.orig b/node_modules/mkdirp/.gitignore.orig new file mode 100644 index 0000000..9303c34 --- /dev/null +++ b/node_modules/mkdirp/.gitignore.orig @@ -0,0 +1,2 @@ +node_modules/ +npm-debug.log \ No newline at end of file diff --git a/node_modules/mkdirp/.gitignore.rej b/node_modules/mkdirp/.gitignore.rej new file mode 100644 index 0000000..69244ff --- /dev/null +++ b/node_modules/mkdirp/.gitignore.rej @@ -0,0 +1,5 @@ +--- /dev/null ++++ .gitignore +@@ -0,0 +1,2 @@ ++node_modules/ ++npm-debug.log \ No newline at end of file diff --git a/node_modules/mkdirp/LICENSE b/node_modules/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/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/node_modules/mkdirp/README.markdown b/node_modules/mkdirp/README.markdown new file mode 100644 index 0000000..c7cec72 --- /dev/null +++ b/node_modules/mkdirp/README.markdown @@ -0,0 +1,50 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/mkdirp/examples/pow.js b/node_modules/mkdirp/examples/pow.js new file mode 100644 index 0000000..7741462 --- /dev/null +++ b/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mkdirp/examples/pow.js.orig b/node_modules/mkdirp/examples/pow.js.orig new file mode 100644 index 0000000..7741462 --- /dev/null +++ b/node_modules/mkdirp/examples/pow.js.orig @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/node_modules/mkdirp/examples/pow.js.rej b/node_modules/mkdirp/examples/pow.js.rej new file mode 100644 index 0000000..81e7f43 --- /dev/null +++ b/node_modules/mkdirp/examples/pow.js.rej @@ -0,0 +1,19 @@ +--- examples/pow.js ++++ examples/pow.js +@@ -1,6 +1,15 @@ +-var mkdirp = require('mkdirp').mkdirp; ++var mkdirp = require('../').mkdirp, ++ mkdirpSync = require('../').mkdirpSync; + + mkdirp('/tmp/foo/bar/baz', 0755, function (err) { + if (err) console.error(err) + else console.log('pow!') + }); ++ ++try { ++ mkdirpSync('/tmp/bar/foo/baz', 0755); ++ console.log('double pow!'); ++} ++catch (ex) { ++ console.log(ex); ++} \ No newline at end of file diff --git a/node_modules/mkdirp/index.js b/node_modules/mkdirp/index.js new file mode 100644 index 0000000..f6e4f2b --- /dev/null +++ b/node_modules/mkdirp/index.js @@ -0,0 +1,85 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f) { + if (mode === undefined) throw new Error('mode not specified'); + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) return cb(); + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er) { + if (er) cb(er); + else mkdirP(p, mode, cb); + }); + break; + + case 'EEXIST': + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original EEXIST be the failure reason. + if (er2 || !stat.isDirectory()) cb(er) + else if ((stat.mode & 0777) !== mode) fs.chmod(p, mode, cb); + else cb(); + }); + break; + + default: + cb(er); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode) { + if (mode === undefined) throw new Error('mode not specified'); + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode) + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + var err1 = sync(path.dirname(p), mode) + if (err1) throw err1; + else return sync(p, mode); + break; + + case 'EEXIST' : + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0 + } + if (!stat.isDirectory()) throw err0; + else if ((stat.mode & 0777) !== mode) { + try { + fs.chmodSync(p, mode); + } + catch (err) { + if (err && err.code === 'EPERM') return null; + else throw err; + } + return null; + } + else return null; + break; + default : + throw err0 + break; + } + } + + return null; +}; diff --git a/node_modules/mkdirp/package.json b/node_modules/mkdirp/package.json new file mode 100644 index 0000000..a783046 --- /dev/null +++ b/node_modules/mkdirp/package.json @@ -0,0 +1,23 @@ +{ + "name" : "mkdirp", + "description" : "Recursively mkdir, like `mkdir -p`", + "version" : "0.2.1", + "author" : "James Halliday (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.0.x" + }, + "license" : "MIT/X11", + "engines": { "node": "*" } +} diff --git a/node_modules/mkdirp/test/chmod.js b/node_modules/mkdirp/test/chmod.js new file mode 100644 index 0000000..0609694 --- /dev/null +++ b/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,39 @@ +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.equal(stat && stat.mode & 0777, mode, 'should be 0755'); + t.end(); + }); + }); +}); diff --git a/node_modules/mkdirp/test/clobber.js b/node_modules/mkdirp/test/clobber.js new file mode 100644 index 0000000..0eb7099 --- /dev/null +++ b/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/node_modules/mkdirp/test/mkdirp.js b/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 0000000..b07cd70 --- /dev/null +++ b/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/node_modules/mkdirp/test/perm.js b/node_modules/mkdirp/test/perm.js new file mode 100644 index 0000000..23a7abb --- /dev/null +++ b/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/node_modules/mkdirp/test/perm_sync.js b/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 0000000..f685f60 --- /dev/null +++ b/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/node_modules/mkdirp/test/race.js b/node_modules/mkdirp/test/race.js new file mode 100644 index 0000000..96a0447 --- /dev/null +++ b/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/node_modules/mkdirp/test/rel.js b/node_modules/mkdirp/test/rel.js new file mode 100644 index 0000000..7985824 --- /dev/null +++ b/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/node_modules/mkdirp/test/sync.js b/node_modules/mkdirp/test/sync.js new file mode 100644 index 0000000..e0e389d --- /dev/null +++ b/node_modules/mkdirp/test/sync.js @@ -0,0 +1,27 @@ +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('/'); + + var err = mkdirp.sync(file, 0755); + 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/node_modules/request/LICENSE b/node_modules/request/LICENSE new file mode 100644 index 0000000..a4a9aee --- /dev/null +++ b/node_modules/request/LICENSE @@ -0,0 +1,55 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/node_modules/request/README.md b/node_modules/request/README.md new file mode 100644 index 0000000..c29d086 --- /dev/null +++ b/node_modules/request/README.md @@ -0,0 +1,285 @@ +# Request -- Simplified HTTP request method + +## Install + +
+  npm install request
+
+ +Or from source: + +
+  git clone git://github.com/mikeal/request.git 
+  cd request
+  npm link
+
+ +## Super simple to use + +Request is designed to be the simplest way possible to make http calls. It support HTTPS and follows redirects by default. + +```javascript +var request = require('request'); +request('http://www.google.com', function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body) // Print the google web page. + } +}) +``` + +## Streaming + +You can stream any response to a file stream. + +```javascript +request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png')) +``` + +You can also stream a file to a PUT or POST request. This method will also check the file extension against a mapping of file extensions to content-types, in this case `application/json`, and use the proper content-type in the PUT request if one is not already provided in the headers. + +```javascript +fs.readStream('file.json').pipe(request.put('http://mysite.com/obj.json')) +``` + +Request can also pipe to itself. When doing so the content-type and content-length will be preserved in the PUT headers. + +```javascript +request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png')) +``` + +Now let's get fancy. + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + if (req.method === 'PUT') { + req.pipe(request.put('http://mysite.com/doodle.png')) + } else if (req.method === 'GET' || req.method === 'HEAD') { + request.get('http://mysite.com/doodle.png').pipe(resp) + } + } +}) +``` + +You can also pipe() from a http.ServerRequest instance and to a http.ServerResponse instance. The HTTP method and headers will be sent as well as the entity-body data. Which means that, if you don't really care about security, you can do: + +```javascript +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + var x = request('http://mysite.com/doodle.png') + req.pipe(x) + x.pipe(resp) + } +}) +``` + +And since pipe() returns the destination stream in node 0.5.x you can do one line proxying :) + +```javascript +req.pipe(request('http://mysite.com/doodle.png')).pipe(resp) +``` + +Also, none of this new functionality conflicts with requests previous features, it just expands them. + +```javascript +var r = request.defaults({'proxy':'http://localproxy.com'}) + +http.createServer(function (req, resp) { + if (req.url === '/doodle.png') { + r.get('http://google.com/doodle.png').pipe(resp) + } +}) +``` + +You can still use intermediate proxies, the requests will still follow HTTP forwards, etc. + +## OAuth Signing + +```javascript +// Twitter OAuth +var qs = require('querystring') + , oauth = + { callback: 'http://mysite.com/callback/' + , consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + } + , url = 'https://api.twitter.com/oauth/request_token' + ; +request.post({url:url, oauth:oauth}, function (e, r, body) { + // Assume by some stretch of magic you aquired the verifier + var access_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: access_token.oauth_token + , verifier: VERIFIER + , token_secret: access_token.oauth_token_secret + } + , url = 'https://api.twitter.com/oauth/access_token' + ; + request.post({url:url, oauth:oauth}, function (e, r, body) { + var perm_token = qs.parse(body) + , oauth = + { consumer_key: CONSUMER_KEY + , consumer_secret: CONSUMER_SECRET + , token: perm_token.oauth_token + , token_secret: perm_token.oauth_token_secret + } + , url = 'https://api.twitter.com/1/users/show.json?' + , params = + { screen_name: perm_token.screen_name + , user_id: perm_token.user_id + } + ; + url += qs.stringify(params) + request.get({url:url, oauth:oauth, json:true}, function (e, r, user) { + console.log(user) + }) + }) +}) +``` + + + +### request(options, callback) + +The first argument can be either a url or an options object. The only required option is uri, all others are optional. + +* `uri` || `url` - fully qualified uri or a parsed url object from url.parse() +* `method` - http method, defaults to GET +* `headers` - http headers, defaults to {} +* `body` - entity body for POST and PUT requests. Must be buffer or string. +* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. +* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below. +* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true. +* `maxRedirects` - the maximum number of redirects to follow, defaults to 10. +* `onResponse` - If true the callback will be fired on the "response" event instead of "end". If a function it will be called on "response" and not effect the regular semantics of the main callback on "end". +* `encoding` - Encoding to be used on response.setEncoding when buffering the response data. +* `pool` - A hash object containing the agents for these requests. If omitted this request will use the global pool which is set to node's default maxSockets. +* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. +* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request +* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. +* `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. +* `strictSSL` - Set to `true` to require that SSL certificates be valid. Note: to use your own certificate authority, you need to specify an agent that was created with that ca as an option. +* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section) + + +The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body buffer. + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. + +### request.put + +Same as request() but defaults to `method: "PUT"`. + +```javascript +request.put(url) +``` + +### request.post + +Same as request() but defaults to `method: "POST"`. + +```javascript +request.post(url) +``` + +### request.head + +Same as request() but defaults to `method: "HEAD"`. + +```javascript +request.head(url) +``` + +### request.del + +Same as request() but defaults to `method: "DELETE"`. + +```javascript +request.del(url) +``` + +### request.get + +Alias to normal request method for uniformity. + +```javascript +request.get(url) +``` +### request.cookie + +Function that creates a new cookie. + +```javascript +request.cookie('cookie_string_here') +``` +### request.jar + +Function that creates a new cookie jar. + +```javascript +request.jar() +``` + + +## Examples: + +```javascript + var request = require('request') + , rand = Math.floor(Math.random()*100000000).toString() + ; + request( + { method: 'PUT' + , uri: 'http://mikeal.couchone.com/testjs/' + rand + , multipart: + [ { 'content-type': 'application/json' + , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) + } + , { body: 'I am an attachment' } + ] + } + , function (error, response, body) { + if(response.statusCode == 201){ + console.log('document saved as: http://mikeal.couchone.com/testjs/'+ rand) + } else { + console.log('error: '+ response.statusCode) + console.log(body) + } + } + ) +``` +Cookies are enabled by default (so they can be used in subsequent requests). To disable cookies set jar to false (either in defaults or in the options sent). + +```javascript +var request = request.defaults({jar: false}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` + +If you to use a custom cookie jar (instead of letting request use its own global cookie jar) you do so by setting the jar default or by specifying it as an option: + +```javascript +var j = request.jar() +var request = request.defaults({jar:j}) +request('http://www.google.com', function () { + request('http://images.google.com') +}) +``` +OR + +```javascript +var j = request.jar() +var cookie = request.cookie('your_cookie_here') +j.add(cookie) +request({url: 'http://www.google.com', jar: j}, function () { + request('http://images.google.com') +}) +``` diff --git a/node_modules/request/main.js b/node_modules/request/main.js new file mode 100644 index 0000000..26f877d --- /dev/null +++ b/node_modules/request/main.js @@ -0,0 +1,591 @@ +// Copyright 2010-2011 Mikeal Rogers +// +// 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. + +var http = require('http') + , https = false + , tls = false + , url = require('url') + , util = require('util') + , stream = require('stream') + , qs = require('querystring') + , mimetypes = require('./mimetypes') + , oauth = require('./oauth') + , uuid = require('./uuid') + , Cookie = require('./vendor/cookie') + , CookieJar = require('./vendor/cookie/jar') + , cookieJar = new CookieJar + ; + +try { + https = require('https') +} catch (e) {} + +try { + tls = require('tls') +} catch (e) {} + +function toBase64 (str) { + return (new Buffer(str || "", "ascii")).toString("base64") +} + +// Hacky fix for pre-0.4.4 https +if (https && !https.Agent) { + https.Agent = function (options) { + http.Agent.call(this, options) + } + util.inherits(https.Agent, http.Agent) + https.Agent.prototype._getConnection = function(host, port, cb) { + var s = tls.connect(port, host, this.options, function() { + // do other checks here? + if (cb) cb() + }) + return s + } +} + +function isReadStream (rs) { + if (rs.readable && rs.path && rs.mode) { + return true + } +} + +function copy (obj) { + var o = {} + for (var i in obj) o[i] = obj[i] + return o +} + +var isUrl = /^https?:/ + +var globalPool = {} + +function Request (options) { + stream.Stream.call(this) + this.readable = true + this.writable = true + + if (typeof options === 'string') { + options = {uri:options} + } + + for (var i in options) { + this[i] = options[i] + } + if (!this.pool) this.pool = globalPool + this.dests = [] + this.__isRequestRequest = true +} +util.inherits(Request, stream.Stream) +Request.prototype.getAgent = function (host, port) { + if (!this.pool[host+':'+port]) { + this.pool[host+':'+port] = new this.httpModule.Agent({host:host, port:port}) + } + return this.pool[host+':'+port] +} +Request.prototype.request = function () { + var self = this + + // Protect against double callback + if (!self._callback && self.callback) { + self._callback = self.callback + self.callback = function () { + if (self._callbackCalled) return // Print a warning maybe? + self._callback.apply(self, arguments) + self._callbackCalled = true + } + } + + if (self.url) { + // People use this property instead all the time so why not just support it. + self.uri = self.url + delete self.url + } + + if (!self.uri) { + throw new Error("options.uri is a required argument") + } else { + if (typeof self.uri == "string") self.uri = url.parse(self.uri) + } + if (self.proxy) { + if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + } + + self._redirectsFollowed = self._redirectsFollowed || 0 + self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10 + self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true + if (self.followRedirect) + self.redirects = self.redirects || [] + + self.headers = self.headers ? copy(self.headers) : {} + + var setHost = false + if (!self.headers.host) { + self.headers.host = self.uri.hostname + if (self.uri.port) { + if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && + !(self.uri.port === 443 && self.uri.protocol === 'https:') ) + self.headers.host += (':'+self.uri.port) + } + setHost = true + } + + if (self.jar === false) { + // disable cookies + var cookies = false; + self._disableCookies = true; + } else if (self.jar) { + // fetch cookie from the user defined cookie jar + var cookies = self.jar.get({ url: self.uri.href }) + } else { + // fetch cookie from the global cookie jar + var cookies = cookieJar.get({ url: self.uri.href }) + } + if (cookies) {self.headers.Cookie = cookies} + + if (!self.uri.pathname) {self.uri.pathname = '/'} + if (!self.uri.port) { + if (self.uri.protocol == 'http:') {self.uri.port = 80} + else if (self.uri.protocol == 'https:') {self.uri.port = 443} + } + + if (self.proxy) { + self.port = self.proxy.port + self.host = self.proxy.hostname + } else { + self.port = self.uri.port + self.host = self.uri.hostname + } + + if (self.onResponse === true) { + self.onResponse = self.callback + delete self.callback + } + + var clientErrorHandler = function (error) { + if (setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) clearTimeout(self.timeoutTimer) + self.emit('error', error) + } + if (self.onResponse) self.on('error', function (e) {self.onResponse(e)}) + if (self.callback) self.on('error', function (e) {self.callback(e)}) + + if (self.form) { + self.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' + self.body = qs.stringify(self.form).toString('utf8') + } + + if (self.oauth) { + var form + if (self.headers['content-type'] && + self.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === + 'application/x-www-form-urlencoded' + ) { + form = qs.parse(self.body) + } + if (self.uri.query) { + form = qs.parse(self.uri.query) + } + if (!form) form = {} + var oa = {} + for (i in form) oa[i] = form[i] + for (i in self.oauth) oa['oauth_'+i] = self.oauth[i] + if (!oa.oauth_version) oa.oauth_version = '1.0' + if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() + if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') + + oa.oauth_signature_method = 'HMAC-SHA1' + + var consumer_secret = oa.oauth_consumer_secret + delete oa.oauth_consumer_secret + var token_secret = oa.oauth_token_secret + delete oa.oauth_token_secret + + var baseurl = self.uri.protocol + '//' + self.uri.host + self.uri.pathname + var signature = oauth.hmacsign(self.method, baseurl, oa, consumer_secret, token_secret) + + // oa.oauth_signature = signature + for (i in form) { + if ( i.slice(0, 'oauth_') in self.oauth) { + // skip + } else { + delete oa['oauth_'+i] + } + } + self.headers.authorization = + 'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+encodeURIComponent(oa[i])+'"'}).join(',') + self.headers.authorization += ',oauth_signature="'+encodeURIComponent(signature)+'"' + } + + if (self.uri.auth && !self.headers.authorization) { + self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization']) { + self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) + } + + if (self.uri.path) { + self.path = self.uri.path + } else { + self.path = self.uri.pathname + (self.uri.search || "") + } + + if (self.path.length === 0) self.path = '/' + + if (self.proxy) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + + if (self.json) { + self.headers['content-type'] = 'application/json' + if (typeof self.json === 'boolean') { + if (typeof self.body === 'object') self.body = JSON.stringify(self.body) + } else { + self.body = JSON.stringify(self.json) + } + + } else if (self.multipart) { + self.body = '' + self.headers['content-type'] = 'multipart/related;boundary="frontier"' + if (!self.multipart.forEach) throw new Error('Argument error, options.multipart.') + + self.multipart.forEach(function (part) { + var body = part.body + if(!body) throw Error('Body attribute missing in multipart.') + delete part.body + self.body += '--frontier\r\n' + Object.keys(part).forEach(function(key){ + self.body += key + ': ' + part[key] + '\r\n' + }) + self.body += '\r\n' + body + '\r\n' + }) + self.body += '--frontier--' + } + + if (self.body) { + if (!Buffer.isBuffer(self.body)) { + self.body = new Buffer(self.body) + } + if (self.body.length) { + self.headers['content-length'] = self.body.length + } else { + throw new Error('Argument error, options.body.') + } + } + + self.httpModule = + {"http:":http, "https:":https}[self.proxy ? self.proxy.protocol : self.uri.protocol] + + if (!self.httpModule) throw new Error("Invalid protocol") + + if (self.pool === false) { + self.agent = false + } else { + if (self.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent = self.httpModule.globalAgent || self.getAgent(self.host, self.port) + self.agent.maxSockets = self.maxSockets + } + if (self.pool.maxSockets) { + // Don't use our pooling if node has the refactored client + self.agent = self.httpModule.globalAgent || self.getAgent(self.host, self.port) + self.agent.maxSockets = self.pool.maxSockets + } + } + + self.start = function () { + self._started = true + self.method = self.method || 'GET' + + self.req = self.httpModule.request(self, function (response) { + self.response = response + response.request = self + + if (self.httpModule === https && + self.strictSSL && + !response.client.authorized) { + var sslErr = response.client.authorizationError + self.emit('error', new Error('SSL Error: '+ sslErr)) + return + } + + if (setHost) delete self.headers.host + if (self.timeout && self.timeoutTimer) clearTimeout(self.timeoutTimer) + + if (response.statusCode >= 300 && + response.statusCode < 400 && + self.followRedirect && + self.method !== 'PUT' && + self.method !== 'POST' && + response.headers.location) { + if (self._redirectsFollowed >= self.maxRedirects) { + self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop.")) + return + } + self._redirectsFollowed += 1 + + if (!isUrl.test(response.headers.location)) { + response.headers.location = url.resolve(self.uri.href, response.headers.location) + } + self.uri = response.headers.location + self.redirects.push( { statusCode : response.statusCode, + redirectUri: response.headers.location }) + delete self.req + delete self.agent + delete self._started + if (self.headers) { + delete self.headers.host + } + request(self, self.callback) + return // Ignore the rest of the response + } else { + self._redirectsFollowed = self._redirectsFollowed || 0 + // Be a good stream and emit end when the response is finished. + // Hack to emit end on close because of a core bug that never fires end + response.on('close', function () { + if (!self._ended) self.response.emit('end') + }) + + if (self.encoding) { + if (self.dests.length !== 0) { + console.error("Ingoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") + } else { + response.setEncoding(self.encoding) + } + } + + self.pipeDest = function (dest) { + if (dest.headers) { + dest.headers['content-type'] = response.headers['content-type'] + if (response.headers['content-length']) { + dest.headers['content-length'] = response.headers['content-length'] + } + } + if (dest.setHeader) { + for (var i in response.headers) { + dest.setHeader(i, response.headers[i]) + } + dest.statusCode = response.statusCode + } + if (self.pipefilter) self.pipefilter(response, dest) + } + + self.dests.forEach(function (dest) { + self.pipeDest(dest) + }) + + response.on("data", function (chunk) { + self._destdata = true + self.emit("data", chunk) + }) + response.on("end", function (chunk) { + self._ended = true + self.emit("end", chunk) + }) + response.on("close", function () {self.emit("close")}) + + self.emit('response', response) + + if (self.onResponse) { + self.onResponse(null, response) + } + if (self.callback) { + var buffer = [] + var bodyLen = 0 + self.on("data", function (chunk) { + buffer.push(chunk) + bodyLen += chunk.length + }) + self.on("end", function () { + if (buffer.length && Buffer.isBuffer(buffer[0])) { + var body = new Buffer(bodyLen) + var i = 0 + buffer.forEach(function (chunk) { + chunk.copy(body, i, 0, chunk.length) + i += chunk.length + }) + response.body = body.toString() + } else if (buffer.length) { + response.body = buffer.join('') + } + + if (self.json) { + try { + response.body = JSON.parse(response.body) + } catch (e) {} + } + if (response.statusCode == 200 && response.headers['set-cookie'] && (!self._disableCookies)) { + response.headers['set-cookie'].forEach(function(cookie) { + if (self.jar) { + // custom defined jar + self.jar.add(new Cookie(cookie)); + } else { + // add to the global cookie jar if user don't define his own + cookieJar.add(new Cookie(cookie)); + } + }); + } + + self.callback(null, response, response.body) + }) + } + } + }) + + if (self.timeout) { + self.timeoutTimer = setTimeout(function() { + self.req.abort() + var e = new Error("ETIMEDOUT") + e.code = "ETIMEDOUT" + self.emit("error", e) + }, self.timeout) + } + + self.req.on('error', clientErrorHandler) + } + + self.once('pipe', function (src) { + if (self.ntick) throw new Error("You cannot pipe to this stream after the first nextTick() after creation of the request stream.") + self.src = src + if (isReadStream(src)) { + if (!self.headers['content-type'] && !self.headers['Content-Type']) + self.headers['content-type'] = mimetypes.lookup(src.path.slice(src.path.lastIndexOf('.')+1)) + } else { + if (src.headers) { + for (var i in src.headers) { + if (!self.headers[i]) { + self.headers[i] = src.headers[i] + } + } + } + if (src.method && !self.method) { + self.method = src.method + } + } + + self.on('pipe', function () { + console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") + }) + }) + + process.nextTick(function () { + if (self.body) { + self.write(self.body) + self.end() + } else if (self.requestBodyStream) { + console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") + self.requestBodyStream.pipe(self) + } else if (!self.src) { + self.headers['content-length'] = 0 + self.end() + } + self.ntick = true + }) +} +Request.prototype.pipe = function (dest) { + if (this.response) { + if (this._destdata) { + throw new Error("You cannot pipe after data has been emitted from the response.") + } else if (this._ended) { + throw new Error("You cannot pipe after the response has been ended.") + } else { + stream.Stream.prototype.pipe.call(this, dest) + this.pipeDest(dest) + return dest + } + } else { + this.dests.push(dest) + stream.Stream.prototype.pipe.call(this, dest) + return dest + } +} +Request.prototype.write = function () { + if (!this._started) this.start() + if (!this.req) throw new Error("This request has been piped before http.request() was called.") + this.req.write.apply(this.req, arguments) +} +Request.prototype.end = function () { + if (!this._started) this.start() + if (!this.req) throw new Error("This request has been piped before http.request() was called.") + this.req.end.apply(this.req, arguments) +} +Request.prototype.pause = function () { + if (!this.response) throw new Error("This request has been piped before http.request() was called.") + this.response.pause.apply(this.response, arguments) +} +Request.prototype.resume = function () { + if (!this.response) throw new Error("This request has been piped before http.request() was called.") + this.response.resume.apply(this.response, arguments) +} + +function request (options, callback) { + if (typeof options === 'string') options = {uri:options} + if (callback) options.callback = callback + var r = new Request(options) + r.request() + return r +} + +module.exports = request + +request.defaults = function (options) { + var def = function (method) { + var d = function (opts, callback) { + if (typeof opts === 'string') opts = {uri:opts} + for (var i in options) { + if (opts[i] === undefined) opts[i] = options[i] + } + return method(opts, callback) + } + return d + } + var de = def(request) + de.get = def(request.get) + de.post = def(request.post) + de.put = def(request.put) + de.head = def(request.head) + de.del = def(request.del) + de.cookie = def(request.cookie) + de.jar = def(request.jar) + return de +} + +request.get = request +request.post = function (options, callback) { + if (typeof options === 'string') options = {uri:options} + options.method = 'POST' + return request(options, callback) +} +request.put = function (options, callback) { + if (typeof options === 'string') options = {uri:options} + options.method = 'PUT' + return request(options, callback) +} +request.head = function (options, callback) { + if (typeof options === 'string') options = {uri:options} + options.method = 'HEAD' + if (options.body || options.requestBodyStream || options.json || options.multipart) { + throw new Error("HTTP HEAD requests MUST NOT include a request body.") + } + return request(options, callback) +} +request.del = function (options, callback) { + if (typeof options === 'string') options = {uri:options} + options.method = 'DELETE' + return request(options, callback) +} +request.jar = function () { + return new CookieJar +} +request.cookie = function (str) { + if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") + return new Cookie(str) +} diff --git a/node_modules/request/mimetypes.js b/node_modules/request/mimetypes.js new file mode 100644 index 0000000..8691006 --- /dev/null +++ b/node_modules/request/mimetypes.js @@ -0,0 +1,146 @@ +// from http://github.com/felixge/node-paperboy +exports.types = { + "aiff":"audio/x-aiff", + "arj":"application/x-arj-compressed", + "asf":"video/x-ms-asf", + "asx":"video/x-ms-asx", + "au":"audio/ulaw", + "avi":"video/x-msvideo", + "bcpio":"application/x-bcpio", + "ccad":"application/clariscad", + "cod":"application/vnd.rim.cod", + "com":"application/x-msdos-program", + "cpio":"application/x-cpio", + "cpt":"application/mac-compactpro", + "csh":"application/x-csh", + "css":"text/css", + "deb":"application/x-debian-package", + "dl":"video/dl", + "doc":"application/msword", + "drw":"application/drafting", + "dvi":"application/x-dvi", + "dwg":"application/acad", + "dxf":"application/dxf", + "dxr":"application/x-director", + "etx":"text/x-setext", + "ez":"application/andrew-inset", + "fli":"video/x-fli", + "flv":"video/x-flv", + "gif":"image/gif", + "gl":"video/gl", + "gtar":"application/x-gtar", + "gz":"application/x-gzip", + "hdf":"application/x-hdf", + "hqx":"application/mac-binhex40", + "html":"text/html", + "ice":"x-conference/x-cooltalk", + "ico":"image/x-icon", + "ief":"image/ief", + "igs":"model/iges", + "ips":"application/x-ipscript", + "ipx":"application/x-ipix", + "jad":"text/vnd.sun.j2me.app-descriptor", + "jar":"application/java-archive", + "jpeg":"image/jpeg", + "jpg":"image/jpeg", + "js":"text/javascript", + "json":"application/json", + "latex":"application/x-latex", + "lsp":"application/x-lisp", + "lzh":"application/octet-stream", + "m":"text/plain", + "m3u":"audio/x-mpegurl", + "man":"application/x-troff-man", + "me":"application/x-troff-me", + "midi":"audio/midi", + "mif":"application/x-mif", + "mime":"www/mime", + "movie":"video/x-sgi-movie", + "mustache":"text/plain", + "mp4":"video/mp4", + "mpg":"video/mpeg", + "mpga":"audio/mpeg", + "ms":"application/x-troff-ms", + "nc":"application/x-netcdf", + "oda":"application/oda", + "ogm":"application/ogg", + "pbm":"image/x-portable-bitmap", + "pdf":"application/pdf", + "pgm":"image/x-portable-graymap", + "pgn":"application/x-chess-pgn", + "pgp":"application/pgp", + "pm":"application/x-perl", + "png":"image/png", + "pnm":"image/x-portable-anymap", + "ppm":"image/x-portable-pixmap", + "ppz":"application/vnd.ms-powerpoint", + "pre":"application/x-freelance", + "prt":"application/pro_eng", + "ps":"application/postscript", + "qt":"video/quicktime", + "ra":"audio/x-realaudio", + "rar":"application/x-rar-compressed", + "ras":"image/x-cmu-raster", + "rgb":"image/x-rgb", + "rm":"audio/x-pn-realaudio", + "rpm":"audio/x-pn-realaudio-plugin", + "rtf":"text/rtf", + "rtx":"text/richtext", + "scm":"application/x-lotusscreencam", + "set":"application/set", + "sgml":"text/sgml", + "sh":"application/x-sh", + "shar":"application/x-shar", + "silo":"model/mesh", + "sit":"application/x-stuffit", + "skt":"application/x-koan", + "smil":"application/smil", + "snd":"audio/basic", + "sol":"application/solids", + "spl":"application/x-futuresplash", + "src":"application/x-wais-source", + "stl":"application/SLA", + "stp":"application/STEP", + "sv4cpio":"application/x-sv4cpio", + "sv4crc":"application/x-sv4crc", + "svg":"image/svg+xml", + "swf":"application/x-shockwave-flash", + "tar":"application/x-tar", + "tcl":"application/x-tcl", + "tex":"application/x-tex", + "texinfo":"application/x-texinfo", + "tgz":"application/x-tar-gz", + "tiff":"image/tiff", + "tr":"application/x-troff", + "tsi":"audio/TSP-audio", + "tsp":"application/dsptype", + "tsv":"text/tab-separated-values", + "unv":"application/i-deas", + "ustar":"application/x-ustar", + "vcd":"application/x-cdlink", + "vda":"application/vda", + "vivo":"video/vnd.vivo", + "vrm":"x-world/x-vrml", + "wav":"audio/x-wav", + "wax":"audio/x-ms-wax", + "wma":"audio/x-ms-wma", + "wmv":"video/x-ms-wmv", + "wmx":"video/x-ms-wmx", + "wrl":"model/vrml", + "wvx":"video/x-ms-wvx", + "xbm":"image/x-xbitmap", + "xlw":"application/vnd.ms-excel", + "xml":"text/xml", + "xpm":"image/x-xpixmap", + "xwd":"image/x-xwindowdump", + "xyz":"chemical/x-pdb", + "zip":"application/zip", +}; + +exports.lookup = function(ext, defaultType) { + defaultType = defaultType || 'application/octet-stream'; + + return (ext in exports.types) + ? exports.types[ext] + : defaultType; +}; \ No newline at end of file diff --git a/node_modules/request/oauth.js b/node_modules/request/oauth.js new file mode 100644 index 0000000..e49c16e --- /dev/null +++ b/node_modules/request/oauth.js @@ -0,0 +1,23 @@ +var crypto = require('crypto') + , qs = require('querystring') + ; + +function sha1 (key, body) { + return crypto.createHmac('sha1', key).update(body).digest('base64') +} + +function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret, body) { + // adapted from https://dev.twitter.com/docs/auth/oauth + var base = + httpMethod + "&" + + encodeURIComponent( base_uri ) + "&" + + Object.keys(params).sort().map(function (i) { + // big WTF here with the escape + encoding but it's what twitter wants + return encodeURIComponent(qs.escape(i)) + "%3D" + encodeURIComponent(qs.escape(params[i])) + }).join("%26") + var key = consumer_secret + '&' + if (token_secret) key += token_secret + return sha1(key, base) +} + +exports.hmacsign = hmacsign \ No newline at end of file diff --git a/node_modules/request/package.json b/node_modules/request/package.json new file mode 100644 index 0000000..80cdcd8 --- /dev/null +++ b/node_modules/request/package.json @@ -0,0 +1,15 @@ +{ "name" : "request" +, "description" : "Simplified HTTP request client." +, "tags" : ["http", "simple", "util", "utility"] +, "version" : "2.2.5" +, "author" : "Mikeal Rogers " +, "repository" : + { "type" : "git" + , "url" : "http://github.com/mikeal/request.git" + } +, "bugs" : + { "url" : "http://github.com/mikeal/request/issues" } +, "engines" : ["node >= 0.3.6"] +, "main" : "./main" +, "scripts": { "test": "bash tests/run.sh" } +} diff --git a/node_modules/request/tests/googledoodle.png b/node_modules/request/tests/googledoodle.png new file mode 100644 index 0000000..f80c9c5 Binary files /dev/null and b/node_modules/request/tests/googledoodle.png differ diff --git a/node_modules/request/tests/run.sh b/node_modules/request/tests/run.sh new file mode 100755 index 0000000..57d0f64 --- /dev/null +++ b/node_modules/request/tests/run.sh @@ -0,0 +1,6 @@ +FAILS=0 +for i in tests/test-*.js; do + echo $i + node $i || let FAILS++ +done +exit $FAILS diff --git a/node_modules/request/tests/server.js b/node_modules/request/tests/server.js new file mode 100644 index 0000000..bad1e50 --- /dev/null +++ b/node_modules/request/tests/server.js @@ -0,0 +1,57 @@ +var http = require('http') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + ; + +exports.createServer = function (port) { + port = port || 6767 + var s = http.createServer(function (req, resp) { + s.emit(req.url, req, resp); + }) + s.port = port + s.url = 'http://localhost:'+port + return s; +} + +exports.createPostStream = function (text) { + var postStream = new stream.Stream(); + postStream.writeable = true; + postStream.readable = true; + setTimeout(function () {postStream.emit('data', new Buffer(text)); postStream.emit('end')}, 0); + return postStream; +} +exports.createPostValidator = function (text) { + var l = function (req, resp) { + var r = ''; + req.on('data', function (chunk) {r += chunk}) + req.on('end', function () { + if (r !== text) console.log(r, text); + assert.equal(r, text) + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write('OK') + resp.end() + }) + } + return l; +} +exports.createGetResponse = function (text, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + resp.write(text) + resp.end() + } + return l; +} +exports.createChunkResponse = function (chunks, contentType) { + var l = function (req, resp) { + contentType = contentType || 'text/plain' + resp.writeHead(200, {'content-type':contentType}) + chunks.forEach(function (chunk) { + resp.write(chunk) + }) + resp.end() + } + return l; +} diff --git a/node_modules/request/tests/test-body.js b/node_modules/request/tests/test-body.js new file mode 100644 index 0000000..18ad5b9 --- /dev/null +++ b/node_modules/request/tests/test-body.js @@ -0,0 +1,90 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); + +var tests = + { testGet : + { resp : server.createGetResponse("TESTING!") + , expectBody: "TESTING!" + } + , testGetChunkBreak : + { resp : server.createChunkResponse( + [ new Buffer([239]) + , new Buffer([163]) + , new Buffer([191]) + , new Buffer([206]) + , new Buffer([169]) + , new Buffer([226]) + , new Buffer([152]) + , new Buffer([131]) + ]) + , expectBody: "Ω☃" + } + , testGetJSON : + { resp : server.createGetResponse('{"test":true}', 'application/json') + , json : true + , expectBody: {"test":true} + } + , testPutString : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : "PUTTINGDATA" + } + , testPutBuffer : + { resp : server.createPostValidator("PUTTINGDATA") + , method : "PUT" + , body : new Buffer("PUTTINGDATA") + } + , testPutJSON : + { resp : server.createPostValidator(JSON.stringify({foo: 'bar'})) + , method: "PUT" + , json: {foo: 'bar'} + } + , testPutMultipart : + { resp: server.createPostValidator( + '--frontier\r\n' + + 'content-type: text/html\r\n' + + '\r\n' + + 'Oh hi.' + + '\r\n--frontier\r\n\r\n' + + 'Oh hi.' + + '\r\n--frontier--' + ) + , method: "PUT" + , multipart: + [ {'content-type': 'text/html', 'body': 'Oh hi.'} + , {'body': 'Oh hi.'} + ] + } + } + +s.listen(s.port, function () { + + var counter = 0 + + for (i in tests) { + (function () { + var test = tests[i] + s.on('/'+i, test.resp) + test.uri = s.url + '/' + i + request(test, function (err, resp, body) { + if (err) throw err + if (test.expectBody) { + assert.deepEqual(test.expectBody, body) + } + counter = counter - 1; + if (counter === 0) { + console.log(Object.keys(tests).length+" tests passed.") + s.close() + } + }) + counter++ + })() + } +}) + diff --git a/node_modules/request/tests/test-cookie.js b/node_modules/request/tests/test-cookie.js new file mode 100644 index 0000000..aeafd10 --- /dev/null +++ b/node_modules/request/tests/test-cookie.js @@ -0,0 +1,29 @@ +var Cookie = require('../vendor/cookie') + , assert = require('assert'); + +var str = 'sid=s543qactge.wKE61E01Bs%2BKhzmxrwrnug; path=/; httpOnly; expires=Sat, 04 Dec 2010 23:27:28 GMT'; +var cookie = new Cookie(str); + +// test .toString() +assert.equal(cookie.toString(), str); + +// test .path +assert.equal(cookie.path, '/'); + +// test .httpOnly +assert.equal(cookie.httpOnly, true); + +// test .name +assert.equal(cookie.name, 'sid'); + +// test .value +assert.equal(cookie.value, 's543qactge.wKE61E01Bs%2BKhzmxrwrnug'); + +// test .expires +assert.equal(cookie.expires instanceof Date, true); + +// test .path default +var cookie = new Cookie('foo=bar', { url: 'http://foo.com/bar' }); +assert.equal(cookie.path, '/bar'); + +console.log('All tests passed'); diff --git a/node_modules/request/tests/test-cookiejar.js b/node_modules/request/tests/test-cookiejar.js new file mode 100644 index 0000000..76fcd71 --- /dev/null +++ b/node_modules/request/tests/test-cookiejar.js @@ -0,0 +1,90 @@ +var Cookie = require('../vendor/cookie') + , Jar = require('../vendor/cookie/jar') + , assert = require('assert'); + +function expires(ms) { + return new Date(Date.now() + ms).toUTCString(); +} + +// test .get() expiration +(function() { + var jar = new Jar; + var cookie = new Cookie('sid=1234; path=/; expires=' + expires(1000)); + jar.add(cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], cookie); + setTimeout(function(){ + var cookies = jar.get({ url: 'http://foo.com/foo' }); + assert.equal(cookies.length, 0); + }, 1000); + }, 5); +})(); + +// test .get() path support +(function() { + var jar = new Jar; + var a = new Cookie('sid=1234; path=/'); + var b = new Cookie('sid=1111; path=/foo/bar'); + var c = new Cookie('sid=2222; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + + // should remove the duplicates + assert.equal(jar.cookies.length, 2); + + // same name, same path, latter prevails + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], c); + + // same name, diff path, path specifity prevails, latter prevails + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], a); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], b); + + var jar = new Jar; + var a = new Cookie('sid=1111; path=/foo/bar'); + var b = new Cookie('sid=3333; path=/foo/bar'); + var c = new Cookie('pid=3333; path=/foo/bar'); + var d = new Cookie('sid=2222; path=/foo/'); + var e = new Cookie('sid=1234; path=/'); + jar.add(a); + jar.add(b); + jar.add(c); + jar.add(d); + jar.add(e); + + var cookies = jar.get({ url: 'http://foo.com/foo/bar' }); + assert.equal(cookies.length, 2); + assert.equal(cookies[0], b); + assert.equal(cookies[1], c); + + var cookies = jar.get({ url: 'http://foo.com/foo/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], d); + + var cookies = jar.get({ url: 'http://foo.com/' }); + assert.equal(cookies.length, 1); + assert.equal(cookies[0], e); +})(); + +setTimeout(function() { + console.log('All tests passed'); +}, 1200); diff --git a/node_modules/request/tests/test-errors.js b/node_modules/request/tests/test-errors.js new file mode 100644 index 0000000..a7db1f7 --- /dev/null +++ b/node_modules/request/tests/test-errors.js @@ -0,0 +1,30 @@ +var server = require('./server') + , events = require('events') + , assert = require('assert') + , request = require('../main.js') + ; + +var local = 'http://localhost:8888/asdf' + +try { + request({uri:local, body:{}}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.body.') +} + +try { + request({uri:local, multipart: 'foo'}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Argument error, options.multipart.') +} + +try { + request({uri:local, multipart: [{}]}) + assert.fail("Should have throw") +} catch(e) { + assert.equal(e.message, 'Body attribute missing in multipart.') +} + +console.log("All tests passed.") diff --git a/node_modules/request/tests/test-oauth.js b/node_modules/request/tests/test-oauth.js new file mode 100644 index 0000000..7d969a0 --- /dev/null +++ b/node_modules/request/tests/test-oauth.js @@ -0,0 +1,109 @@ +var hmacsign = require('../oauth').hmacsign + , assert = require('assert') + , qs = require('querystring') + , request = require('../main') + ; + +function getsignature (r) { + var sign + r.headers.authorization.slice('OAuth '.length).replace(/,\ /g, ',').split(',').forEach(function (v) { + if (v.slice(0, 'oauth_signature="'.length) === 'oauth_signature="') sign = v.slice('oauth_signature="'.length, -1) + }) + return decodeURIComponent(sign) +} + +// Tests from Twitter documentation https://dev.twitter.com/docs/auth/oauth + +var reqsign = hmacsign('POST', 'https://api.twitter.com/oauth/request_token', + { oauth_callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_timestamp: '1272323042' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98") + +console.log(reqsign) +console.log('8wUi7m5HFQy76nowoCThusfgB+Q=') +assert.equal(reqsign, '8wUi7m5HFQy76nowoCThusfgB+Q=') + +var accsign = hmacsign('POST', 'https://api.twitter.com/oauth/access_token', + { oauth_consumer_key: 'GDdmIQH6jhtmLUypg82g' + , oauth_nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , oauth_signature_method: 'HMAC-SHA1' + , oauth_token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , oauth_timestamp: '1272323047' + , oauth_verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , oauth_version: '1.0' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA") + +console.log(accsign) +console.log('PUw/dHA4fnlJYM6RhXk5IU/0fCc=') +assert.equal(accsign, 'PUw/dHA4fnlJYM6RhXk5IU/0fCc=') + +var upsign = hmacsign('POST', 'http://api.twitter.com/1/statuses/update.json', + { oauth_consumer_key: "GDdmIQH6jhtmLUypg82g" + , oauth_nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , oauth_signature_method: "HMAC-SHA1" + , oauth_token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , oauth_timestamp: "1272325550" + , oauth_version: "1.0" + , status: 'setting up my twitter 私のさえずりを設定する' + }, "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98", "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA") + +console.log(upsign) +console.log('yOahq5m0YjDDjfjxHaXEsW9D+X0=') +assert.equal(upsign, 'yOahq5m0YjDDjfjxHaXEsW9D+X0=') + + +var r = request.post( + { url: 'https://api.twitter.com/oauth/request_token' + , oauth: + { callback: 'http://localhost:3005/the_dance/process_callback?service_provider_id=11' + , consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: 'QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk' + , timestamp: '1272323042' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + } + }) + +console.log(getsignature(r)) +assert.equal(reqsign, getsignature(r)) + +var r = request.post( + { url: 'https://api.twitter.com/oauth/access_token' + , oauth: + { consumer_key: 'GDdmIQH6jhtmLUypg82g' + , nonce: '9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8' + , signature_method: 'HMAC-SHA1' + , token: '8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc' + , timestamp: '1272323047' + , verifier: 'pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY' + , version: '1.0' + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA" + } + }) + +console.log(getsignature(r)) +assert.equal(accsign, getsignature(r)) + +var r = request.post( + { url: 'http://api.twitter.com/1/statuses/update.json' + , oauth: + { consumer_key: "GDdmIQH6jhtmLUypg82g" + , nonce: "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y" + , signature_method: "HMAC-SHA1" + , token: "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw" + , timestamp: "1272325550" + , version: "1.0" + , consumer_secret: "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98" + , token_secret: "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA" + } + , form: {status: 'setting up my twitter 私のさえずりを設定する'} + }) + +console.log(getsignature(r)) +assert.equal(upsign, getsignature(r)) + diff --git a/node_modules/request/tests/test-pipes.js b/node_modules/request/tests/test-pipes.js new file mode 100644 index 0000000..0774647 --- /dev/null +++ b/node_modules/request/tests/test-pipes.js @@ -0,0 +1,167 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var s = server.createServer(3453); + +function ValidationStream(str) { + this.str = str + this.buf = '' + this.on('data', function (data) { + this.buf += data + }) + this.on('end', function () { + assert.equal(this.str, this.buf) + }) + this.writable = true +} +util.inherits(ValidationStream, stream.Stream) +ValidationStream.prototype.write = function (chunk) { + this.emit('data', chunk) +} +ValidationStream.prototype.end = function (chunk) { + if (chunk) emit('data', chunk) + this.emit('end') +} + +s.listen(s.port, function () { + counter = 0; + + var check = function () { + counter = counter - 1 + if (counter === 0) { + console.log('All tests passed.') + setTimeout(function () { + process.exit(); + }, 500) + } + } + + // Test pipeing to a request object + s.once('/push', server.createPostValidator("mydata")); + + var mydata = new stream.Stream(); + mydata.readable = true + + counter++ + var r1 = request.put({url:'http://localhost:3453/push'}, function () { + check(); + }) + mydata.pipe(r1) + + mydata.emit('data', 'mydata'); + mydata.emit('end'); + + + // Test pipeing from a request object. + s.once('/pull', server.createGetResponse("mypulldata")); + + var mypulldata = new stream.Stream(); + mypulldata.writable = true + + counter++ + request({url:'http://localhost:3453/pull'}).pipe(mypulldata) + + var d = ''; + + mypulldata.write = function (chunk) { + d += chunk; + } + mypulldata.end = function () { + assert.equal(d, 'mypulldata'); + check(); + }; + + + s.on('/cat', function (req, resp) { + if (req.method === "GET") { + resp.writeHead(200, {'content-type':'text/plain-test', 'content-length':4}); + resp.end('asdf') + } else if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/plain-test'); + assert.equal(req.headers['content-length'], 4) + var validate = ''; + + req.on('data', function (chunk) {validate += chunk}) + req.on('end', function () { + resp.writeHead(201); + resp.end(); + assert.equal(validate, 'asdf'); + check(); + }) + } + }) + s.on('/pushjs', function (req, resp) { + if (req.method === "PUT") { + assert.equal(req.headers['content-type'], 'text/javascript'); + check(); + } + }) + s.on('/catresp', function (req, resp) { + request.get('http://localhost:3453/cat').pipe(resp) + }) + s.on('/doodle', function (req, resp) { + if (req.headers['x-oneline-proxy']) { + resp.setHeader('x-oneline-proxy', 'yup') + } + resp.writeHead('200', {'content-type':'image/png'}) + fs.createReadStream(path.join(__dirname, 'googledoodle.png')).pipe(resp) + }) + s.on('/onelineproxy', function (req, resp) { + var x = request('http://localhost:3453/doodle') + req.pipe(x) + x.pipe(resp) + }) + + counter++ + fs.createReadStream(__filename).pipe(request.put('http://localhost:3453/pushjs')) + + counter++ + request.get('http://localhost:3453/cat').pipe(request.put('http://localhost:3453/cat')) + + counter++ + request.get('http://localhost:3453/catresp', function (e, resp, body) { + assert.equal(resp.headers['content-type'], 'text/plain-test'); + assert.equal(resp.headers['content-length'], 4) + check(); + }) + + var doodleWrite = fs.createWriteStream(path.join(__dirname, 'test.png')) + + counter++ + request.get('http://localhost:3453/doodle').pipe(doodleWrite) + + doodleWrite.on('close', function () { + assert.deepEqual(fs.readFileSync(path.join(__dirname, 'googledoodle.png')), fs.readFileSync(path.join(__dirname, 'test.png'))) + check() + }) + + process.on('exit', function () { + fs.unlinkSync(path.join(__dirname, 'test.png')) + }) + + counter++ + request.get({uri:'http://localhost:3453/onelineproxy', headers:{'x-oneline-proxy':'nope'}}, function (err, resp, body) { + assert.equal(resp.headers['x-oneline-proxy'], 'yup') + check() + }) + + s.on('/afterresponse', function (req, resp) { + resp.write('d') + resp.end() + }) + + counter++ + var afterresp = request.post('http://localhost:3453/afterresponse').on('response', function () { + var v = new ValidationStream('d') + afterresp.pipe(v) + v.on('end', check) + }) + +}) diff --git a/node_modules/request/tests/test-proxy.js b/node_modules/request/tests/test-proxy.js new file mode 100644 index 0000000..647157c --- /dev/null +++ b/node_modules/request/tests/test-proxy.js @@ -0,0 +1,39 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , fs = require('fs') + , request = require('../main.js') + , path = require('path') + , util = require('util') + ; + +var port = 6768 + , called = false + , proxiedHost = 'google.com' + ; + +var s = server.createServer(port) +s.listen(port, function () { + s.on('http://google.com/', function (req, res) { + called = true + assert.equal(req.headers.host, proxiedHost) + res.writeHeader(200) + res.end() + }) + request ({ + url: 'http://'+proxiedHost, + proxy: 'http://localhost:'+port + /* + //should behave as if these arguments where passed: + url: 'http://localhost:'+port, + headers: {host: proxiedHost} + //*/ + }, function (err, res, body) { + s.close() + }) +}) + +process.on('exit', function () { + assert.ok(called, 'the request must be made to the proxy server') +}) diff --git a/node_modules/request/tests/test-timeout.js b/node_modules/request/tests/test-timeout.js new file mode 100644 index 0000000..673f8ad --- /dev/null +++ b/node_modules/request/tests/test-timeout.js @@ -0,0 +1,87 @@ +var server = require('./server') + , events = require('events') + , stream = require('stream') + , assert = require('assert') + , request = require('../main.js') + ; + +var s = server.createServer(); +var expectedBody = "waited"; +var remainingTests = 5; + +s.listen(s.port, function () { + // Request that waits for 200ms + s.on('/timeout', function (req, resp) { + setTimeout(function(){ + resp.writeHead(200, {'content-type':'text/plain'}) + resp.write(expectedBody) + resp.end() + }, 200); + }); + + // Scenario that should timeout + var shouldTimeout = { + url: s.url + "/timeout", + timeout:100 + } + + + request(shouldTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + + // Scenario that shouldn't timeout + var shouldntTimeout = { + url: s.url + "/timeout", + timeout:300 + } + + request(shouldntTimeout, function (err, resp, body) { + assert.equal(err, null); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with no timeout set, so shouldn't timeout + var noTimeout = { + url: s.url + "/timeout" + } + + request(noTimeout, function (err, resp, body) { + assert.equal(err); + assert.equal(expectedBody, body) + checkDone(); + }) + + // Scenario with a negative timeout value, should be treated a zero or the minimum delay + var negativeTimeout = { + url: s.url + "/timeout", + timeout:-1000 + } + + request(negativeTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + // Scenario with a float timeout value, should be rounded by setTimeout anyway + var floatTimeout = { + url: s.url + "/timeout", + timeout: 100.76 + } + + request(floatTimeout, function (err, resp, body) { + assert.equal(err.code, "ETIMEDOUT"); + checkDone(); + }) + + function checkDone() { + if(--remainingTests == 0) { + s.close(); + console.log("All tests passed."); + } + } +}) + diff --git a/node_modules/request/uuid.js b/node_modules/request/uuid.js new file mode 100644 index 0000000..1d83bd5 --- /dev/null +++ b/node_modules/request/uuid.js @@ -0,0 +1,19 @@ +module.exports = function () { + var s = [], itoh = '0123456789ABCDEF'; + + // Make array of random hex digits. The UUID only has 32 digits in it, but we + // allocate an extra items to make room for the '-'s we'll be inserting. + for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10); + + // Conform to RFC-4122, section 4.4 + s[14] = 4; // Set 4 high bits of time_high field to version + s[19] = (s[19] & 0x3) | 0x8; // Specify 2 high bits of clock sequence + + // Convert to hex chars + for (var i = 0; i <36; i++) s[i] = itoh[s[i]]; + + // Insert '-'s + s[8] = s[13] = s[18] = s[23] = '-'; + + return s.join(''); +} diff --git a/node_modules/request/vendor/cookie/index.js b/node_modules/request/vendor/cookie/index.js new file mode 100644 index 0000000..4ba20d6 --- /dev/null +++ b/node_modules/request/vendor/cookie/index.js @@ -0,0 +1,57 @@ +/*! + * Tobi - Cookie + * Copyright(c) 2010 LearnBoost + * MIT Licensed + */ + +/** + * Module dependencies. + */ + +var url = require('url'); + +/** + * Initialize a new `Cookie` with the given cookie `str` and `req`. + * + * @param {String} str + * @param {IncomingRequest} req + * @api private + */ + +var Cookie = exports = module.exports = function Cookie(str, req) { + this.str = str; + + // First key is the name + this.name = str.substr(0, str.indexOf('=')); + + // Map the key/val pairs + str.split(/ *; */).reduce(function(obj, pair){ + pair = pair.split(/ *= */); + obj[pair[0]] = pair[1] || true; + return obj; + }, this); + + // Assign value + this.value = this[this.name]; + + // Expires + this.expires = this.expires + ? new Date(this.expires) + : Infinity; + + // Default or trim path + this.path = this.path + ? this.path.trim() + : url.parse(req.url).pathname; +}; + +/** + * Return the original cookie string. + * + * @return {String} + * @api public + */ + +Cookie.prototype.toString = function(){ + return this.str; +}; diff --git a/node_modules/request/vendor/cookie/jar.js b/node_modules/request/vendor/cookie/jar.js new file mode 100644 index 0000000..34920e0 --- /dev/null +++ b/node_modules/request/vendor/cookie/jar.js @@ -0,0 +1,72 @@ +/*! +* Tobi - CookieJar +* Copyright(c) 2010 LearnBoost +* MIT Licensed +*/ + +/** +* Module dependencies. +*/ + +var url = require('url'); + +/** +* Initialize a new `CookieJar`. +* +* @api private +*/ + +var CookieJar = exports = module.exports = function CookieJar() { + this.cookies = []; +}; + +/** +* Add the given `cookie` to the jar. +* +* @param {Cookie} cookie +* @api private +*/ + +CookieJar.prototype.add = function(cookie){ + this.cookies = this.cookies.filter(function(c){ + // Avoid duplication (same path, same name) + return !(c.name == cookie.name && c.path == cookie.path); + }); + this.cookies.push(cookie); +}; + +/** +* Get cookies for the given `req`. +* +* @param {IncomingRequest} req +* @return {Array} +* @api private +*/ + +CookieJar.prototype.get = function(req){ + var path = url.parse(req.url).pathname + , now = new Date + , specificity = {}; + return this.cookies.filter(function(cookie){ + if (0 == path.indexOf(cookie.path) && now < cookie.expires + && cookie.path.length > (specificity[cookie.name] || 0)) + return specificity[cookie.name] = cookie.path.length; + }); +}; + +/** +* Return Cookie string for the given `req`. +* +* @param {IncomingRequest} req +* @return {String} +* @api private +*/ + +CookieJar.prototype.cookieString = function(req){ + var cookies = this.get(req); + if (cookies.length) { + return cookies.map(function(cookie){ + return cookie.name + '=' + cookie.value; + }).join('; '); + } +}; diff --git a/node_modules/sardines b/node_modules/sardines new file mode 120000 index 0000000..6bcbfd5 --- /dev/null +++ b/node_modules/sardines @@ -0,0 +1 @@ +/usr/local/lib/node_modules/sardines \ No newline at end of file diff --git a/node_modules/sk b/node_modules/sk new file mode 120000 index 0000000..b9da99e --- /dev/null +++ b/node_modules/sk @@ -0,0 +1 @@ +/usr/local/lib/node_modules/sk \ No newline at end of file diff --git a/node_modules/tar-async/header.js b/node_modules/tar-async/header.js new file mode 100644 index 0000000..1cdddff --- /dev/null +++ b/node_modules/tar-async/header.js @@ -0,0 +1,124 @@ +(function () { + "use strict"; + +/* +struct posix_header { // byte offset + char name[100]; // 0 + char mode[8]; // 100 + char uid[8]; // 108 + char gid[8]; // 116 + char size[12]; // 124 + char mtime[12]; // 136 + char chksum[8]; // 148 + char typeflag; // 156 + char linkname[100]; // 157 + char magic[6]; // 257 + char version[2]; // 263 + char uname[32]; // 265 + char gname[32]; // 297 + char devmajor[8]; // 329 + char devminor[8]; // 337 + char prefix[155]; // 345 + // 500 +}; +*/ + + var utils = require("./utils"), + headerFormat; + + headerFormat = [ + { + 'field': 'filename', + 'length': 100, + 'type': 'string' + }, + { + 'field': 'mode', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'uid', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'gid', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'size', + 'length': 12, + 'type': 'number' + }, + { + 'field': 'mtime', + 'length': 12, + 'type': 'number' + }, + { + 'field': 'checksum', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'type', + 'length': 1, + 'type': 'number' + }, + { + 'field': 'linkName', + 'length': 100, + 'type': 'string' + }, + { + 'field': 'ustar', + 'length': 8, + 'type': 'string' + }, + { + 'field': 'owner', + 'length': 32, + 'type': 'string' + }, + { + 'field': 'group', + 'length': 32, + 'type': 'string' + }, + { + 'field': 'majorNumber', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'minorNumber', + 'length': 8, + 'type': 'number' + }, + { + 'field': 'filenamePrefix', + 'length': 155, + 'type': 'string' + }, + { + 'field': 'padding', + 'length': 12 + } + ]; + + function formatHeader(data) { + var buffer = utils.clean(512), + offset = 0; + + headerFormat.forEach(function (value) { + buffer.write(data[value.field] || "", offset); + offset += value.length; + }); + return buffer; + } + + module.exports.structure = headerFormat; + module.exports.format = formatHeader; +}()); diff --git a/node_modules/tar-async/index.js b/node_modules/tar-async/index.js new file mode 100644 index 0000000..4f440c2 --- /dev/null +++ b/node_modules/tar-async/index.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + module.exports = require('./tar'); + + module.exports.Tar = require('./tar'); + module.exports.Untar = require('./untar'); +}()); diff --git a/node_modules/tar-async/package.json b/node_modules/tar-async/package.json new file mode 100644 index 0000000..199d160 --- /dev/null +++ b/node_modules/tar-async/package.json @@ -0,0 +1,20 @@ +{ + "author": "T. Jameson Little ", + "name": "tar-async", + "description": "Asynchronous tar and untar", + "keywords": ["tar", "untar", "asynchronous", "stream", "async", "chunk", "chunked"], + "version": "1.1.1", + "repository": { + "type": "git", + "url": "git://github.com/beatgammit/tar-async.git" + }, + "main": "index.js", + "directories": { + "lib": "." + }, + "engines": { + "node": ">=0.1.90" + }, + "dependencies": {}, + "devDependencies": {} +} diff --git a/node_modules/tar-async/tar.js b/node_modules/tar-async/tar.js new file mode 100644 index 0000000..e4952ca --- /dev/null +++ b/node_modules/tar-async/tar.js @@ -0,0 +1,156 @@ +(function () { + "use strict"; + + var path = require('path'), + Stream = require('stream').Stream, + header = require("./header"), + utils = require("./utils"), + recordSize = 512, + blockSize, + queue = []; + + function Tar(opt) { + var tape; + + opt = opt || {}; + + blockSize = (opt.recordsPerBlock ? opt.recordsPerBlock : 20) * recordSize; + + Stream.apply(this, arguments); + + tape = this; + + this.written = 0; + + this.consolidate = 'consolidate' in opt ? opt.consolidate : false; + this.normalize = 'normalize' in opt ? opt.normalize : true; + + this.on('end', function () { + tape.emit('data', utils.clean(blockSize - (tape.written % blockSize))); + }); + + if (opt && opt.output) { + this.pipe(opt.output); + } + } + + Tar.prototype = Object.create(Stream.prototype, { + constructor: { value: Tar } + }); + + Tar.prototype.close = function () { + this.emit('end'); + }; + + Tar.prototype.append = function (filepath, input, opts, callback) { + var data, + checksum, + mode, + mtime, + uid, + gid, + size, + tape = this, + extraBytes, + headerBuf; + + if (typeof opts === 'function') { + callback = opts; + opts = {}; + } + + if (this.processing || queue.length) { + queue.push({ + filepath: filepath, + input: input, + opts: opts, + cb: callback + }); + return; + } + + opts = opts || {}; + + mode = opts.mode || parseInt('777', 8) & 0xfff; + mtime = opts.mtime || parseInt(+new Date() / 1000); + uid = opts.uid || 0; + gid = opts.gid || 0; + size = opts.size || input.length; + + data = { + filename: this.consolidate ? path.basename(filepath) : filepath, + mode: utils.pad(mode, 7), + uid: utils.pad(uid, 7), + gid: utils.pad(gid, 7), + size: utils.pad(size, 11), + mtime: utils.pad(mtime, 11), + checksum: ' ', + type: '0', // just a file + ustar: 'ustar ', + owner: '', + group: '' + }; + + if (this.normalize && !this.consolidate) { + data.filename = path.normalize(data.filename); + } + + // calculate the checksum + checksum = 0; + Object.keys(data).forEach(function (key) { + var i, value = data[key], length; + + for (i = 0, length = value.length; i < length; i += 1) { + checksum += value.charCodeAt(i); + } + }); + + data.checksum = utils.pad(checksum, 6) + "\u0000 "; + + headerBuf = header.format(data); + this.emit('data', header.format(data)); + this.written += headerBuf.length; + + if (typeof input === 'string') { + this.emit('data', input); + this.written += input.length; + + extraBytes = recordSize - (size % recordSize || recordSize); + this.emit('data', utils.clean(recordSize - (size % recordSize))); + this.written += extraBytes; + + if (typeof callback === 'function') { + callback(); + } + } else { + this.processing = true; + + input.on('data', function (chunk) { + tape.emit('data', chunk); + tape.written += chunk.length; + }); + + input.on('end', function () { + extraBytes = recordSize - (size % recordSize || recordSize); + tape.emit('data', utils.clean(extraBytes)); + tape.written += extraBytes; + + if (queue.length) { + setTimeout(function () { + var elem = queue.splice(0, 1)[0]; + + tape.append(elem.filepath, elem.input, elem.opts, elem.cb); + }, 0); + + tape.processing = false; + } + + if (typeof callback === 'function') { + callback(); + } + }); + } + }; + + module.exports = Tar; +}()); diff --git a/node_modules/tar-async/untar.js b/node_modules/tar-async/untar.js new file mode 100644 index 0000000..5c608b4 --- /dev/null +++ b/node_modules/tar-async/untar.js @@ -0,0 +1,244 @@ +(function () { + "use strict"; + + var Stream = require('stream').Stream, + headerFormat = require('./header').structure, + buffer, + totalRead = 0, + recordSize = 512, + fileStream, + leftToRead, + fileTypes = [ + 'normal', 'hard-link', 'symbolic-link', 'character-special', 'block-special', 'directory', 'fifo', 'contiguous-file' + ]; + + function filterDecoder(input) { + var filter = []; + if (!input) { + return [0, 7]; + } + + if (typeof input === 'string') { + input = [].push(input); + } + + if (!(input instanceof Array)) { + console.error('Invalid fileType. Only Arrays or strings are accepted'); + return; + } + + input.forEach(function (i) { + var index = fileTypes.indexOf(i); + if (index < 0) { + console.error('Filetype not valid. Ignoring input:', i); + return; + } + + filter.push(i); + }); + + return filter; + } + + function readInt(value) { + return parseInt(value.replace(/^0*/, ''), 8) || 0; + } + + function readString(buf) { + var i, length; + for (i = 0, length = buf.length; i < buf.length; i += 1) { + if (buf[i] === 0) { + return buf.toString('utf8', 0, i); + } + } + } + + function doHeader(buf, cb) { + var data = {}, offset = 0, checksum = 0; + + function updateChecksum(value) { + var i, length; + + for (i = 0, length = value.length; i < length; i += 1) { + checksum += value.charCodeAt(i); + } + } + + headerFormat.some(function (field) { + var tBuf = buf.slice(offset, offset + field.length), + tString = tBuf.toString(); + + offset += field.length; + + if (field.field === 'ustar' && !/ustar/.test(tString)) { + // end the loop if not using the extended header + return true; + } else if (field.field === 'checksum') { + updateChecksum(' '); + } else { + updateChecksum(tString); + } + + if (field.type === 'string') { + data[field.field] = readString(tBuf); + } else if (field.type === 'number') { + data[field.field] = readInt(tString); + } + }); + + if (typeof cb === 'function') { + if (checksum !== data.checksum) { + return cb.call(this, 'Checksum not equal', checksum, data.checksum); + } + cb.call(this, null, data, recordSize); + } + } + + /* + * Extract data from an input. + * + * @param opts- object of options + * @param cb- callback for each file + */ + function Untar(opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + + // I should probably actually add some options... + opts = opts || {}; + + this.fileTypes = filterDecoder(opts.filter); + + this.cb = cb; + } + + Untar.prototype = Object.create(Stream.prototype, { + constructor: { + value: Untar + } + }); + + Untar.prototype.end = function (data, encoding) { + if (data) { + this.write(data, encoding); + } + }; + + Untar.prototype.write = function write(data, encoding) { + var buf, tBuf, bytesBuffer; + + // get a Buffer object + if (typeof data === 'string') { + buf = new Buffer(data, encoding); + } else if (typeof data === 'array') { + buf = new Buffer(data); + } else { + buf = data; + } + + if (!buf) { + tBuf = buffer; + } else if (buffer) { + // create new buffer with old and new data + tBuf = new Buffer(buffer.length + buf.length); + buffer.copy(tBuf); + buf.copy(tBuf, buffer.length); + } else { + tBuf = buf; + } + + // clear old buffer + buffer = undefined; + + // nothing to do, just give up ='( + if (!tBuf || tBuf.length === 0) { + return; + } + + // stream the file + if (fileStream) { + if (tBuf.length >= leftToRead) { + fileStream.emit('data', tBuf.slice(0, leftToRead)); + fileStream.emit('end'); + fileStream = undefined; + + buffer = tBuf.slice(leftToRead); + totalRead += leftToRead; + leftToRead = 0; + return; + } + + fileStream.emit('data', tBuf); + leftToRead -= tBuf.length; + totalRead += tBuf.length; + return; + } + + // no file to read, so let's try reading a header + + // if we're not an even multiple, account for trailing nulls + if (totalRead % recordSize) { + bytesBuffer = recordSize - (totalRead % recordSize); + + // if we don't have enough bytes to account for the nulls + if (tBuf.length < bytesBuffer) { + totalRead += bytesBuffer; + return; + } + + // throw away trailing nulls + tBuf = tBuf.slice(bytesBuffer); + totalRead += bytesBuffer; + } + + // if we don't have enough for a full header, wait 'til we do... + if (tBuf.length < recordSize) { + buffer = tBuf; + return; + } + + doHeader.call(this, tBuf, function (err, data, rOffset) { + if (err) { + if (rOffset === 0) { + return; + } + return this.cb(err); + } + + // update total; rOffset should always be 512 + totalRead += rOffset; + buffer = tBuf.slice(rOffset); + + fileStream = new Stream(); + + if (this.fileTypes.indexOf(data.type) >= 0) { + // we'll let the user know if they want this type of file + this.cb(err, data, fileStream); + } + + if (buffer.length >= data.size) { + fileStream.emit('data', buffer.slice(0, data.size)); + fileStream.emit('end'); + totalRead += data.size; + buffer = buffer.slice(data.size); + + fileStream = undefined; + + // recurse, we still have data + return write.call(this); + } + + leftToRead = data.size - buffer.length; + fileStream.emit('data', buffer); + totalRead += buffer.length; + + buffer = undefined; + }); + }; + + Untar.prototype.writable = true; + + module.exports = Untar; +}()); diff --git a/node_modules/tar-async/utils.js b/node_modules/tar-async/utils.js new file mode 100644 index 0000000..e3647aa --- /dev/null +++ b/node_modules/tar-async/utils.js @@ -0,0 +1,19 @@ +(function () { + "use strict"; + + function clean(length) { + var i, buffer = new Buffer(length); + for (i = 0; i < length; i += 1) { + buffer[i] = 0; + } + return buffer; + } + + function pad(num, bytes, base) { + num = num.toString(base || 8); + return "000000000000".substr(num.length + 12 - bytes) + num; + } + + module.exports.clean = clean; + module.exports.pad = pad; +}()); diff --git a/node_modules/tar/.gitignore b/node_modules/tar/.gitignore new file mode 100644 index 0000000..f96c7db --- /dev/null +++ b/node_modules/tar/.gitignore @@ -0,0 +1,4 @@ +.*.swp +node_modules +examples/extract/ +test/tmp/ diff --git a/node_modules/tar/README.md b/node_modules/tar/README.md new file mode 100644 index 0000000..7cfe3bb --- /dev/null +++ b/node_modules/tar/README.md @@ -0,0 +1,50 @@ +# node-tar + +Tar for Node.js. + +## Goals of this project + +1. Be able to parse and reasonably extract the contents of any tar file + created by any program that creates tar files, period. + + At least, this includes every version of: + + * bsdtar + * gnutar + * solaris posix tar + * Joerg Schilling's star ("Schilly tar") + +2. Create tar files that can be extracted by any of the following tar + programs: + + * bsdtar/libarchive version 2.6.2 + * gnutar 1.15 and above + * SunOS Posix tar + * Joerg Schilling's star ("Schilly tar") + +3. 100% test coverage. Speed is important. Correctness is slightly + more important. + +4. Create the kind of tar interface that Node users would want to use. + +5. Satisfy npm's needs for a portable tar implementation with a + JavaScript interface. + +6. No excuses. No complaining. No tolerance for failure. + +## But isn't there already a tar.js? + +Yes, there are a few. This one is going to be better, and it will be +fanatically maintained, because npm will depend on it. + +That's why I need to write it from scratch. Creating and extracting +tarballs is such a large part of what npm does, I simply can't have it +be a black box any longer. + +## Didn't you have something already? Where'd it go? + +It's in the "old" folder. It's not functional. Don't use it. + +It was a useful exploration to learn the issues involved, but like most +software of any reasonable complexity, node-tar won't be useful until +it's been written at least 3 times. diff --git a/node_modules/tar/examples/extracter.js b/node_modules/tar/examples/extracter.js new file mode 100644 index 0000000..e150abf --- /dev/null +++ b/node_modules/tar/examples/extracter.js @@ -0,0 +1,11 @@ +var tar = require("../tar.js") + , fs = require("fs") + +fs.createReadStream(__dirname + "/../test/fixtures/c.tar") + .pipe(tar.Extract({ path: __dirname + "/extract" })) + .on("error", function (er) { + console.error("error here") + }) + .on("end", function () { + console.error("done") + }) diff --git a/node_modules/tar/examples/reader.js b/node_modules/tar/examples/reader.js new file mode 100644 index 0000000..c2584d3 --- /dev/null +++ b/node_modules/tar/examples/reader.js @@ -0,0 +1,36 @@ +var tar = require("../tar.js") + , fs = require("fs") + +fs.createReadStream(__dirname + "/../test/fixtures/c.tar") + .pipe(tar.Reader()) + .on("extendedHeader", function (e) { + console.error("extended pax header", e.props) + e.on("end", function () { + console.error("extended pax fields:", e.fields) + }) + }) + .on("ignoredEntry", function (e) { + console.error("ignoredEntry?!?", e.props) + }) + .on("longLinkpath", function (e) { + console.error("longLinkpath entry", e.props) + e.on("end", function () { + console.error("value=%j", e.body.toString()) + }) + }) + .on("longPath", function (e) { + console.error("longPath entry", e.props) + e.on("end", function () { + console.error("value=%j", e.body.toString()) + }) + }) + .on("entry", function (e) { + console.error("entry", e.props) + e.on("data", function (c) { + console.error(" >>>" + c.toString().replace(/\n/g, "\\n")) + }) + e.on("end", function () { + console.error(" << 0 + return !this._needDrain +} + +EntryWriter.prototype.end = function (c) { + // console.error(".. ew end") + if (c) this._buffer.push(c) + this._buffer.push(EOF) + this._ended = true + this._process() + this._needDrain = this._buffer.length > 0 +} + +EntryWriter.prototype.pause = function () { + // console.error(".. ew pause") + this._paused = true + this.emit("pause") +} + +EntryWriter.prototype.resume = function () { + // console.error(".. ew resume") + this._paused = false + this.emit("resume") + this._process() +} + +EntryWriter.prototype.add = function (entry) { + // console.error(".. ew add") + if (!this.parent) return this.emit("error", new Error("no parent")) + + // make sure that the _header and such is emitted, and clear out + // the _currentEntry link on the parent. + if (!this._ended) this.end() + + return this.parent.add(entry) +} + +EntryWriter.prototype._header = function () { + // console.error(".. ew header") + if (this._didHeader) return + this._didHeader = true + + var headerBlock = TarHeader.encode(this.props) + + if (this.props.needExtended && !this._meta) { + var me = this + + ExtendedHeaderWriter = ExtendedHeaderWriter || + require("./extended-header-writer.js") + + ExtendedHeaderWriter(this.props) + .on("data", function (c) { + me.emit("data", c) + }) + .on("error", function (er) { + me.emit("error", er) + }) + .end() + } + + // console.error(".. .. ew headerBlock emitting") + this.emit("data", headerBlock) + this.emit("header") +} + +EntryWriter.prototype._process = function () { + // console.error(".. .. ew process") + if (!this._didHeader && !this._meta) { + this._header() + } + + if (this._paused || this._processing) { + // console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing) + return + } + + this._processing = true + + var buf = this._buffer + for (var i = 0; i < buf.length; i ++) { + // console.error(".. .. .. i=%d", i) + + var c = buf[i] + + if (c === EOF) this._stream.end() + else this._stream.write(c) + + if (this._paused) { + // console.error(".. .. .. paused mid-emission") + this._processing = false + if (i < buf.length) { + this._needDrain = true + this._buffer = buf.slice(i + 1) + } + return + } + } + + // console.error(".. .. .. emitted") + this._buffer.length = 0 + this._processing = false + + // console.error(".. .. .. emitting drain") + this.emit("drain") +} + +EntryWriter.prototype.destroy = function () {} diff --git a/node_modules/tar/lib/entry.js b/node_modules/tar/lib/entry.js new file mode 100644 index 0000000..4fc331e --- /dev/null +++ b/node_modules/tar/lib/entry.js @@ -0,0 +1,212 @@ +// A passthrough read/write stream that sets its properties +// based on a header, extendedHeader, and globalHeader +// +// Can be either a file system object of some sort, or +// a pax/ustar metadata entry. + +module.exports = Entry + +var TarHeader = require("./header.js") + , tar = require("../tar") + , assert = require("assert").ok + , Stream = require("stream").Stream + , inherits = require("inherits") + , fstream = require("fstream").Abstract + +function Entry (header, extended, global) { + Stream.call(this) + this.readable = true + this.writable = true + + this._needDrain = false + this._paused = false + this._reading = false + this._ending = false + this._ended = false + this._remaining = 0 + this._queue = [] + this._index = 0 + this._queueLen = 0 + + this._read = this._read.bind(this) + + this.props = {} + this._header = header + this._extended = extended || {} + + // globals can change throughout the course of + // a file parse operation. Freeze it at its current state. + this._global = {} + var me = this + Object.keys(global || {}).forEach(function (g) { + me._global[g] = global[g] + }) + + this._setProps() +} + +inherits(Entry, Stream, +{ write: function (c) { + if (this._ending) this.error("write() after end()", null, true) + if (this._remaining === 0) { + this.error("invalid bytes past eof") + } + + // often we'll get a bunch of \0 at the end of the last write, + // since chunks will always be 512 bytes when reading a tarball. + if (c.length > this._remaining) { + c = c.slice(0, this._remaining) + } + this._remaining -= c.length + + // put it on the stack. + var ql = this._queueLen + this._queue.push(c) + this._queueLen ++ + + this._read() + + // either paused, or buffered + if (this._paused || ql > 0) { + this._needDrain = true + return false + } + + return true + } + +, end: function (c) { + if (c) this.write(c) + this._ending = true + this._read() + } + +, pause: function () { + this._paused = true + this.emit("pause") + } + +, resume: function () { + // console.error(" Tar Entry resume", this.path) + this.emit("resume") + this._paused = false + this._read() + return this._queueLen - this._index > 1 + } + + // This is bound to the instance +, _read: function () { + // console.error(" Tar Entry _read", this.path) + + if (this._paused || this._reading || this._ended) return + + // set this flag so that event handlers don't inadvertently + // get multiple _read() calls running. + this._reading = true + + // have any data to emit? + if (this._index < this._queueLen) { + var chunk = this._queue[this._index ++] + this.emit("data", chunk) + } + + // check if we're drained + if (this._index >= this._queueLen) { + this._queue.length = this._queueLen = this._index = 0 + if (this._needDrain) { + this._needDrain = false + this.emit("drain") + } + if (this._ending) { + this._ended = true + this.emit("end") + } + } + + // if the queue gets too big, then pluck off whatever we can. + // this should be fairly rare. + var mql = this._maxQueueLen + if (this._queueLen > mql && this._index > 0) { + mql = Math.min(this._index, mql) + this._index -= mql + this._queueLen -= mql + this._queue = this._queue.slice(mql) + } + + this._reading = false + } + +, _setProps: function () { + // props = extended->global->header->{} + var header = this._header + , extended = this._extended + , global = this._global + , props = this.props + + // first get the values from the normal header. + var fields = tar.fields + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , val = header[field] + if (typeof val !== "undefined") props[field] = val + } + + // next, the global header for this file. + // numeric values, etc, will have already been parsed. + ;[global, extended].forEach(function (p) { + Object.keys(p).forEach(function (f) { + if (typeof p[f] !== "undefined") props[f] = p[f] + }) + }) + + // no nulls allowed in path or linkpath + ;["path", "linkpath"].forEach(function (p) { + if (props.hasOwnProperty(p)) { + props[p] = props[p].split("\0")[0] + } + }) + + + // set date fields to be a proper date + ;["mtime", "ctime", "atime"].forEach(function (p) { + if (props.hasOwnProperty(p)) { + props[p] = new Date(props[p] * 1000) + } + }) + + // set the type so that we know what kind of file to create + var type + switch (tar.types[props.type]) { + case "OldFile": + case "ContiguousFile": + type = "File" + break + + case "GNUDumpDir": + type = "Directory" + break + + case undefined: + type = "Unknown" + break + + case "Link": + case "SymbolicLink": + case "CharacterDevice": + case "BlockDevice": + case "Directory": + case "FIFO": + default: + type = tar.types[props.type] + } + + this.type = type + this.path = props.path + this.size = props.size + + // size is special, since it signals when the file needs to end. + this._remaining = props.size + } +, warn: fstream.warn +, error: fstream.error +}) diff --git a/node_modules/tar/lib/extended-header-writer.js b/node_modules/tar/lib/extended-header-writer.js new file mode 100644 index 0000000..f28d530 --- /dev/null +++ b/node_modules/tar/lib/extended-header-writer.js @@ -0,0 +1,179 @@ + +module.exports = ExtendedHeaderWriter + +var inherits = require("inherits") + , EntryWriter = require("./entry-writer.js") + +inherits(ExtendedHeaderWriter, EntryWriter) + +var tar = require("../tar.js") + , path = require("path") + , inherits = require("inherits") + , TarHeader = require("./header.js") + +// props is the props of the thing we need to write an +// extended header for. +// Don't be shy with it. Just encode everything. +function ExtendedHeaderWriter (props) { + // console.error(">> ehw ctor") + var me = this + + if (!(me instanceof ExtendedHeaderWriter)) { + return new ExtendedHeaderWriter(props) + } + + me.fields = props + + var p = + { path : ("PaxHeader" + path.join("/", props.path || "")) + .replace(/\\/g, "/").substr(0, 100) + , mode : props.mode || 0666 + , uid : props.uid || 0 + , gid : props.gid || 0 + , size : 0 // will be set later + , mtime : props.mtime || Date.now() / 1000 + , type : "x" + , linkpath : "" + , ustar : "ustar\0" + , ustarver : "00" + , uname : props.uname || "" + , gname : props.gname || "" + , devmaj : props.devmaj || 0 + , devmin : props.devmin || 0 + } + + + EntryWriter.call(me, p) + // console.error(">> ehw props", me.props) + me.props = p + + me._meta = true +} + +ExtendedHeaderWriter.prototype.end = function () { + // console.error(">> ehw end") + var me = this + + if (me._ended) return + me._ended = true + + me._encodeFields() + me._stream.write(TarHeader.encode(me.props)) + me.body.forEach(function (l) { + me._stream.write(l) + }) + me._ready = true + + // console.error(">> ehw _process calling end()", me.props) + this._stream.end() +} + +ExtendedHeaderWriter.prototype._encodeFields = function () { + // console.error(">> ehw _encodeFields") + this.body = [] + if (this.fields.prefix) { + this.fields.path = this.fields.prefix + "/" + this.fields.path + this.fields.prefix = "" + } + encodeFields(this.fields, "", this.body) + var me = this + this.body.forEach(function (l) { + me.props.size += l.length + }) +} + +function encodeFields (fields, prefix, body) { + // console.error(">> >> ehw encodeFields") + // "%d %s=%s\n", , , + // The length is a decimal number, and includes itself and the \n + // Numeric values are decimal strings. + + Object.keys(fields).forEach(function (k) { + var val = fields[k] + , numeric = tar.numeric[k] + + if (prefix) k = prefix + "." + k + + // already including NODETAR.type, don't need File=true also + if (k === fields.type && val === true) return + + switch (k) { + // don't include anything that's always handled just fine + // in the normal header, or only meaningful in the context + // of nodetar + case "mode": + case "cksum": + case "ustar": + case "ustarver": + case "prefix": + case "basename": + case "dirname": + case "needExtended": + case "block": + case "filter": + return + + case "rdev": + if (val === 0) return + break + + case "nlink": + case "dev": // Truly a hero among men, Creator of Star! + case "ino": // Speak his name with reverent awe! It is: + k = "SCHILY." + k + break + + default: break + } + + if (val && typeof val === "object" && + !Buffer.isBuffer(val)) encodeFields(val, k, body) + else if (val === null || val === undefined) return + else body.push.apply(body, encodeField(k, val)) + }) + + return body +} + +function encodeField (k, v) { + // lowercase keys must be valid, otherwise prefix with + // "NODETAR." + if (k.charAt(0) === k.charAt(0).toLowerCase()) { + var m = k.split(".")[0] + if (!tar.knownExtended[m]) k = "NODETAR." + k + } + + if (typeof val === "number") val = val.toString(10) + + var s = new Buffer(" " + k + "=" + v + "\n") + , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1 + + // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) + + // if adding that many digits will make it go over that length, + // then add one to it. For example, if the string is: + // " foo=bar\n" + // then that's 9 characters. With the "9", that bumps the length + // up to 10. However, this is invalid: + // "10 foo=bar\n" + // but, since that's actually 11 characters, since 10 adds another + // character to the length, and the length includes the number + // itself. In that case, just bump it up again. + if (s.length + digits >= Math.pow(10, digits)) digits += 1 + // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) + + var len = digits + s.length + // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len) + var lenBuf = new Buffer("" + len) + if (lenBuf.length + s.length !== len) { + throw new Error("Bad length calculation\n"+ + "len="+len+"\n"+ + "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+ + "lenBuf.length="+lenBuf.length+"\n"+ + "digits="+digits+"\n"+ + "s="+JSON.stringify(s.toString())+"\n"+ + "s.length="+s.length) + } + + return [lenBuf, s] +} diff --git a/node_modules/tar/lib/extended-header.js b/node_modules/tar/lib/extended-header.js new file mode 100644 index 0000000..4346d6c --- /dev/null +++ b/node_modules/tar/lib/extended-header.js @@ -0,0 +1,139 @@ +// An Entry consisting of: +// +// "%d %s=%s\n", , , +// +// The length is a decimal number, and includes itself and the \n +// \0 does not terminate anything. Only the length terminates the string. +// Numeric values are decimal strings. + +module.exports = ExtendedHeader + +var Entry = require("./entry.js") + , inherits = require("inherits") + , tar = require("../tar.js") + , numeric = tar.numeric + , keyTrans = { "SCHILY.dev": "dev" + , "SCHILY.ino": "ino" + , "SCHILY.nlink": "nlink" } + +function ExtendedHeader () { + Entry.apply(this, arguments) + this.on("data", this._parse) + this.fields = {} + this._position = 0 + this._fieldPos = 0 + this._state = SIZE + this._sizeBuf = [] + this._keyBuf = [] + this._valBuf = [] + this._size = -1 + this._key = "" +} + +inherits(ExtendedHeader, Entry, { _parse: parse }) + +var s = 0 + , states = ExtendedHeader.states = {} + , SIZE = states.SIZE = s++ + , KEY = states.KEY = s++ + , VAL = states.VAL = s++ + , ERR = states.ERR = s++ + +Object.keys(states).forEach(function (s) { + states[states[s]] = states[s] +}) + +states[s] = null + +// char code values for comparison +var _0 = "0".charCodeAt(0) + , _9 = "9".charCodeAt(0) + , point = ".".charCodeAt(0) + , a = "a".charCodeAt(0) + , Z = "Z".charCodeAt(0) + , a = "a".charCodeAt(0) + , z = "z".charCodeAt(0) + , space = " ".charCodeAt(0) + , eq = "=".charCodeAt(0) + , cr = "\n".charCodeAt(0) + +function parse (c) { + if (this._state === ERR) return + + for ( var i = 0, l = c.length + ; i < l + ; this._position++, this._fieldPos++, i++) { + // console.error("top of loop, size="+this._size) + + var b = c[i] + + if (this._size >= 0 && this._fieldPos > this._size) { + error(this, "field exceeds length="+this._size) + return + } + + switch (this._state) { + case ERR: return + + case SIZE: + // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString()) + if (b === space) { + this._state = KEY + // this._fieldPos = this._sizeBuf.length + this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10) + this._sizeBuf.length = 0 + continue + } + if (b < _0 || b > _9) { + error(this, "expected [" + _0 + ".." + _9 + "], got " + b) + return + } + this._sizeBuf.push(b) + continue + + case KEY: + // can be any char except =, not > size. + if (b === eq) { + this._state = VAL + this._key = new Buffer(this._keyBuf).toString() + if (keyTrans[this._key]) this._key = keyTrans[this._key] + this._keyBuf.length = 0 + continue + } + this._keyBuf.push(b) + continue + + case VAL: + // field must end with cr + if (this._fieldPos === this._size - 1) { + // console.error("finished with "+this._key) + if (b !== cr) { + error(this, "expected \\n at end of field") + return + } + var val = new Buffer(this._valBuf).toString() + if (numeric[this._key]) { + val = parseFloat(val) + } + this.fields[this._key] = val + + this._valBuf.length = 0 + this._state = SIZE + this._size = -1 + this._fieldPos = -1 + continue + } + this._valBuf.push(b) + continue + } + } +} + +function error (me, msg) { + msg = "invalid header: " + msg + + "\nposition=" + me._position + + "\nfield position=" + me._fieldPos + + me.error(msg) + me.state = ERR +} diff --git a/node_modules/tar/lib/extract.js b/node_modules/tar/lib/extract.js new file mode 100644 index 0000000..e45974c --- /dev/null +++ b/node_modules/tar/lib/extract.js @@ -0,0 +1,64 @@ +// give it a tarball and a path, and it'll dump the contents + +module.exports = Extract + +var tar = require("../tar.js") + , fstream = require("fstream") + , inherits = require("inherits") + , path = require("path") + +function Extract (opts) { + if (!(this instanceof Extract)) return new Extract(opts) + tar.Parse.apply(this) + + // have to dump into a directory + opts.type = "Directory" + opts.Directory = true + + if (typeof opts !== "object") { + opts = { path: opts } + } + + // better to drop in cwd? seems more standard. + opts.path = opts.path || path.resolve("node-tar-extract") + opts.type = "Directory" + opts.Directory = true + + this._fst = fstream.Writer(opts) + + this.pause() + var me = this + + // Hardlinks in tarballs are relative to the root + // of the tarball. So, they need to be resolved against + // the target directory in order to be created properly. + me.on("entry", function (entry) { + if (entry.type !== "Link") return + entry.linkpath = entry.props.linkpath = + path.join(opts.path, path.join("/", entry.props.linkpath)) + }) + + this._fst.on("ready", function () { + me.pipe(me._fst, { end: false }) + me.resume() + }) + + // this._fst.on("end", function () { + // console.error("\nEEEE Extract End", me._fst.path) + // }) + + this._fst.on("close", function () { + // console.error("\nEEEE Extract End", me._fst.path) + me.emit("end") + me.emit("close") + }) +} + +inherits(Extract, tar.Parse) + +Extract.prototype._streamEnd = function () { + var me = this + if (!me._ended) me.error("unexpected eof") + me._fst.end() + // my .end() is coming later. +} diff --git a/node_modules/tar/lib/global-header-writer.js b/node_modules/tar/lib/global-header-writer.js new file mode 100644 index 0000000..0bfc7b8 --- /dev/null +++ b/node_modules/tar/lib/global-header-writer.js @@ -0,0 +1,14 @@ +module.exports = GlobalHeaderWriter + +var ExtendedHeaderWriter = require("./extended-header-writer.js") + , inherits = require("inherits") + +inherits(GlobalHeaderWriter, ExtendedHeaderWriter) + +function GlobalHeaderWriter (props) { + if (!(this instanceof GlobalHeaderWriter)) { + return new GlobalHeaderWriter(props) + } + ExtendedHeaderWriter.call(this, props) + this.props.type = "g" +} diff --git a/node_modules/tar/lib/header.js b/node_modules/tar/lib/header.js new file mode 100644 index 0000000..05b237c --- /dev/null +++ b/node_modules/tar/lib/header.js @@ -0,0 +1,385 @@ +// parse a 512-byte header block to a data object, or vice-versa +// If the data won't fit nicely in a simple header, then generate +// the appropriate extended header file, and return that. + +module.exports = TarHeader + +var tar = require("../tar.js") + , fields = tar.fields + , fieldOffs = tar.fieldOffs + , fieldEnds = tar.fieldEnds + , fieldSize = tar.fieldSize + , numeric = tar.numeric + , assert = require("assert").ok + , space = " ".charCodeAt(0) + , slash = "/".charCodeAt(0) + , bslash = process.platform === "win32" ? "\\".charCodeAt(0) : null + +function TarHeader (block) { + if (!(this instanceof TarHeader)) return new TarHeader(block) + if (block) this.decode(block) +} + +TarHeader.prototype = + { decode : decode + , encode: encode + , calcSum: calcSum + , checkSum: checkSum + } + +TarHeader.parseNumeric = parseNumeric +TarHeader.encode = encode +TarHeader.decode = decode + +// note that this will only do the normal ustar header, not any kind +// of extended posix header file. If something doesn't fit comfortably, +// then it will set obj.needExtended = true, and set the block to +// the closest approximation. +function encode (obj) { + if (!obj && !(this instanceof TarHeader)) throw new Error( + "encode must be called on a TarHeader, or supplied an object") + + obj = obj || this + var block = obj.block = new Buffer(512) + + // if the object has a "prefix", then that's actually an extension of + // the path field. + if (obj.prefix) { + // console.error("%% header encoding, got a prefix", obj.prefix) + obj.path = obj.prefix + "/" + obj.path + // console.error("%% header encoding, prefixed path", obj.path) + obj.prefix = "" + } + + obj.needExtended = false + + if (obj.mode) { + if (typeof obj.mode === "string") obj.mode = parseInt(obj.mode, 8) + obj.mode = obj.mode & 0777 + } + + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , off = fieldOffs[f] + , end = fieldEnds[f] + , ret + + switch (field) { + case "cksum": + // special, done below, after all the others + break + + case "prefix": + // special, this is an extension of the "path" field. + // console.error("%% header encoding, skip prefix later") + break + + case "type": + // convert from long name to a single char. + var type = obj.type || "0" + if (type.length > 1) { + type = tar.types[obj.type] + if (!type) type = "0" + } + writeText(block, off, end, type) + break + + case "path": + // uses the "prefix" field if > 100 bytes, but <= 255 + var pathLen = Buffer.byteLength(obj.path) + , pathFSize = fieldSize[fields.path] + , prefFSize = fieldSize[fields.prefix] + + // paths between 100 and 255 should use the prefix field. + // longer than 255 + if (pathLen > pathFSize && + pathLen <= pathFSize + prefFSize) { + // need to find a slash somewhere in the middle so that + // path and prefix both fit in their respective fields + var searchStart = pathLen - 1 - pathFSize + , searchEnd = prefFSize + , found = false + , pathBuf = new Buffer(obj.path) + + for ( var s = searchStart + ; (s <= searchEnd) + ; s ++ ) { + if (pathBuf[s] === slash || pathBuf[s] === bslash) { + found = s + break + } + } + + if (found !== false) { + prefix = pathBuf.slice(0, found).toString("utf8") + path = pathBuf.slice(found + 1).toString("utf8") + + ret = writeText(block, off, end, path) + off = fieldOffs[fields.prefix] + end = fieldEnds[fields.prefix] + // console.error("%% header writing prefix", off, end, prefix) + ret = writeText(block, off, end, prefix) || ret + break + } + } + + // paths less than 100 chars don't need a prefix + // and paths longer than 255 need an extended header and will fail + // on old implementations no matter what we do here. + // Null out the prefix, and fallthrough to default. + // console.error("%% header writing no prefix") + var poff = fieldOffs[fields.prefix] + , pend = fieldEnds[fields.prefix] + writeText(block, poff, pend, "") + // fallthrough + + // all other fields are numeric or text + default: + ret = numeric[field] + ? writeNumeric(block, off, end, obj[field]) + : writeText(block, off, end, obj[field] || "") + break + } + obj.needExtended = obj.needExtended || ret + } + + var off = fieldOffs[fields.cksum] + , end = fieldEnds[fields.cksum] + + writeNumeric(block, off, end, calcSum.call(this, block)) + + return block +} + +// if it's a negative number, or greater than will fit, +// then use write256. +var MAXNUM = { 12: 077777777777 + , 11: 07777777777 + , 8 : 07777777 + , 7 : 0777777 } +function writeNumeric (block, off, end, num) { + var writeLen = end - off + , maxNum = MAXNUM[writeLen] || 0 + + num = num || 0 + // console.error(" numeric", num) + + if (num instanceof Date || + Object.prototype.toString.call(num) === "[object Date]") { + num = num.getTime() / 1000 + } + + if (num > maxNum || num < 0) { + write256(block, off, end, num) + // need an extended header if negative or too big. + return true + } + + // god, tar is so annoying + // if the string is small enough, you should put a space + // between the octal string and the \0, but if it doesn't + // fit, then don't. + var numStr = Math.floor(num).toString(8) + if (num < MAXNUM[writeLen - 1]) numStr += " " + + // pad with "0" chars + if (numStr.length < writeLen) { + numStr = (new Array(writeLen - numStr.length).join("0")) + numStr + } + + if (numStr.length !== writeLen - 1) { + throw new Error("invalid length: " + JSON.stringify(numStr) + "\n" + + "expected: "+writeLen) + } + block.write(numStr, off, writeLen, "utf8") + block[end - 1] = 0 +} + +function write256 (block, off, end, num) { + var buf = block.slice(off, end) + var positive = num >= 0 + buf[0] = positive ? 0x80 : 0xFF + + // get the number as a base-256 tuple + if (!positive) num *= -1 + var tuple = [] + do { + var n = num % 256 + tuple.push(n) + num = (num - n) / 256 + } while (num) + + var bytes = tuple.length + + var fill = buf.length - bytes + for (var i = 1; i < fill; i ++) { + buf[i] = positive ? 0 : 0xFF + } + + // tuple is a base256 number, with [0] as the *least* significant byte + // if it's negative, then we need to flip all the bits once we hit the + // first non-zero bit. The 2's-complement is (0x100 - n), and the 1's- + // complement is (0xFF - n). + var zero = true + for (i = bytes; i > 0; i --) { + var byte = tuple[bytes - i] + if (positive) buf[fill + i] = byte + else if (zero && byte === 0) buf[fill + i] = 0 + else if (zero) { + zero = false + buf[fill + i] = 0x100 - byte + } else buf[fill + i] = 0xFF - byte + } +} + +function writeText (block, off, end, str) { + // strings are written as utf8, then padded with \0 + var strLen = Buffer.byteLength(str) + , writeLen = Math.min(strLen, end - off) + // non-ascii fields need extended headers + // long fields get truncated + , needExtended = strLen !== str.length || strLen > writeLen + + // write the string, and null-pad + if (writeLen > 0) block.write(str, off, writeLen, "utf8") + for (var i = off + writeLen; i < end; i ++) block[i] = 0 + + return needExtended +} + +function calcSum (block) { + block = block || this.block + assert(Buffer.isBuffer(block) && block.length === 512) + + if (!block) throw new Error("Need block to checksum") + + // now figure out what it would be if the cksum was " " + var sum = 0 + , start = fieldOffs[fields.cksum] + , end = fieldEnds[fields.cksum] + + for (var i = 0; i < fieldOffs[fields.cksum]; i ++) { + sum += block[i] + } + + for (var i = start; i < end; i ++) { + sum += space + } + + for (var i = end; i < 512; i ++) { + sum += block[i] + } + + return sum +} + + +function checkSum (block) { + var sum = calcSum.call(this, block) + block = block || this.block + + var cksum = block.slice(fieldOffs[fields.cksum], fieldEnds[fields.cksum]) + cksum = parseNumeric(cksum) + + return cksum === sum +} + +function decode (block) { + block = block || this.block + assert(Buffer.isBuffer(block) && block.length === 512) + + this.block = block + this.cksumValid = this.checkSum() + + var prefix = null + + // slice off each field. + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , val = block.slice(fieldOffs[f], fieldEnds[f]) + + switch (field) { + case "ustar": + // if not ustar, then everything after that is just padding. + if (val.toString() !== "ustar\0") { + this.ustar = false + return + } else { + // console.error("ustar:", val, val.toString()) + this.ustar = val.toString() + } + break + + // prefix is special, since it might signal the xstar header + case "prefix": + var atime = parseNumeric(val.slice(131, 131 + 12)) + , ctime = parseNumeric(val.slice(131 + 12, 131 + 12 + 12)) + if ((val[130] === 0 || val[130] === space) && + typeof atime === "number" && + typeof ctime === "number" && + val[131 + 12] === space && + val[131 + 12 + 12] === space) { + this.atime = atime + this.ctime = ctime + val = val.slice(0, 130) + } + prefix = val.toString("utf8").replace(/\0+$/, "") + // console.error("%% header reading prefix", prefix) + break + + // all other fields are null-padding text + // or a number. + default: + if (numeric[field]) { + this[field] = parseNumeric(val) + } else { + this[field] = val.toString("utf8").replace(/\0+$/, "") + } + break + } + } + + // if we got a prefix, then prepend it to the path. + if (prefix) { + this.path = prefix + "/" + this.path + // console.error("%% header got a prefix", this.path) + } +} + +function parse256 (buf) { + // first byte MUST be either 80 or FF + // 80 for positive, FF for 2's comp + var positive + if (buf[0] === 0x80) positive = true + else if (buf[0] === 0xFF) positive = false + else return null + + // build up a base-256 tuple from the least sig to the highest + var zero = false + , tuple = [] + for (var i = buf.length - 1; i > 0; i --) { + var byte = buf[i] + if (positive) tuple.push(byte) + else if (zero && byte === 0) tuple.push(0) + else if (zero) { + zero = false + tuple.push(0x100 - byte) + } else tuple.push(0xFF - byte) + } + + for (var sum = 0, i = 0, l = tuple.length; i < l; i ++) { + sum += tuple[i] * Math.pow(256, i) + } + + return positive ? sum : -1 * sum +} + +function parseNumeric (f) { + if (f[0] & 0x80) return parse256(f) + + var str = f.toString("utf8").split("\0")[0].trim() + , res = parseInt(str, 8) + + return isNaN(res) ? null : res +} + diff --git a/node_modules/tar/lib/pack.js b/node_modules/tar/lib/pack.js new file mode 100644 index 0000000..411b8b6 --- /dev/null +++ b/node_modules/tar/lib/pack.js @@ -0,0 +1,212 @@ +// pipe in an fstream, and it'll make a tarball. +// key-value pair argument is global extended header props. + +module.exports = Pack + +var EntryWriter = require("./entry-writer.js") + , Stream = require("stream").Stream + , path = require("path") + , inherits = require("inherits") + , GlobalHeaderWriter = require("./global-header-writer.js") + , collect = require("fstream").collect + , eof = new Buffer(512) + +for (var i = 0; i < 512; i ++) eof[i] = 0 + +inherits(Pack, Stream) + +function Pack (props) { + // console.error("-- p ctor") + var me = this + if (!(me instanceof Pack)) return new Pack(props) + + me._global = props + + me.readable = true + me.writable = true + me._buffer = [] + // console.error("-- -- set current to null in ctor") + me._currentEntry = null + me._processing = false + + me._pipeRoot = null + me.on("pipe", function (src) { + if (src.root === me._pipeRoot) return + me._pipeRoot = src + src.on("end", function () { + me._pipeRoot = null + }) + me.add(src) + }) +} + +Pack.prototype.addGlobal = function (props) { + // console.error("-- p addGlobal") + if (this._didGlobal) return + this._didGlobal = true + + var me = this + GlobalHeaderWriter(props) + .on("data", function (c) { + me.emit("data", c) + }) + .end() +} + +Pack.prototype.add = function (stream) { + if (this._global && !this._didGlobal) this.addGlobal(this._global) + + if (this._ended) return this.emit("error", new Error("add after end")) + + collect(stream) + this._buffer.push(stream) + this._process() + this._needDrain = this._buffer.length > 0 + return !this._needDrain +} + +Pack.prototype.pause = function () { + this._paused = true + if (this._currentEntry) this._currentEntry.pause() + this.emit("pause") +} + +Pack.prototype.resume = function () { + this._paused = false + if (this._currentEntry) this._currentEntry.resume() + this.emit("resume") + this._process() +} + +Pack.prototype.end = function () { + this._ended = true + this._buffer.push(eof) + this._process() +} + +Pack.prototype._process = function () { + var me = this + if (me._paused || me._processing) { + return + } + + var entry = me._buffer.shift() + + if (!entry) { + if (me._needDrain) { + me.emit("drain") + } + return + } + + if (entry.ready === false) { + // console.error("-- entry is not ready", entry) + me._buffer.unshift(entry) + entry.on("ready", function () { + // console.error("-- -- ready!", entry) + me._process() + }) + return + } + + me._processing = true + + if (entry === eof) { + // need 2 ending null blocks. + me.emit("data", eof) + me.emit("data", eof) + me.emit("end") + me.emit("close") + return + } + + // Change the path to be relative to the root dir that was + // added to the tarball. + // + // XXX This should be more like how -C works, so you can + // explicitly set a root dir, and also explicitly set a pathname + // in the tarball to use. That way we can skip a lot of extra + // work when resolving symlinks for bundled dependencies in npm. + + var root = path.dirname((entry.root || entry).path) + var wprops = {} + + Object.keys(entry.props).forEach(function (k) { + wprops[k] = entry.props[k] + }) + + wprops.path = path.relative(root, entry.path) + + switch (wprops.type) { + case "Directory": + wprops.path += "/" + wprops.size = 0 + break + case "Link": + var lp = path.resolve(path.dirname(entry.path), entry.linkpath) + wprops.linkpath = path.relative(root, lp) + wprops.size = 0 + break + case "SymbolicLink": + var lp = path.resolve(path.dirname(entry.path), entry.linkpath) + wprops.linkpath = path.relative(path.dirname(entry.path), lp) + wprops.size = 0 + break + } + + // console.error("-- new writer", wprops) + // if (!wprops.type) { + // // console.error("-- no type?", entry.constructor.name, entry) + // } + + // console.error("-- -- set current to new writer", wprops.path) + var writer = me._currentEntry = EntryWriter(wprops) + + writer.parent = me + + // writer.on("end", function () { + // // console.error("-- -- writer end", writer.path) + // }) + + writer.on("data", function (c) { + me.emit("data", c) + }) + + writer.on("header", function () { + Buffer.prototype.toJSON = function () { + return this.toString().split(/\0/).join(".") + } + // console.error("-- -- writer header %j", writer.props) + if (writer.props.size === 0) nextEntry() + }) + writer.on("close", nextEntry) + + var ended = false + function nextEntry () { + if (ended) return + ended = true + + // console.error("-- -- writer close", writer.path) + // console.error("-- -- set current to null", wprops.path) + me._currentEntry = null + me._processing = false + me._process() + } + + writer.on("error", function (er) { + // console.error("-- -- writer error", writer.path) + me.emit("error", er) + }) + + // if it's the root, then there's no need to add its entries, + // or data, since they'll be added directly. + if (entry === me._pipeRoot) { + // console.error("-- is the root, don't auto-add") + writer.add = null + } + + entry.pipe(writer) +} + +Pack.prototype.destroy = function () {} +Pack.prototype.write = function () {} diff --git a/node_modules/tar/lib/parse.js b/node_modules/tar/lib/parse.js new file mode 100644 index 0000000..d9784b5 --- /dev/null +++ b/node_modules/tar/lib/parse.js @@ -0,0 +1,253 @@ + +// A writable stream. +// It emits "entry" events, which provide a readable stream that has +// header info attached. + +module.exports = Parse.create = Parse + +var stream = require("stream") + , Stream = stream.Stream + , BlockStream = require("block-stream") + , tar = require("../tar.js") + , TarHeader = require("./header.js") + , Entry = require("./entry.js") + , BufferEntry = require("./buffer-entry.js") + , ExtendedHeader = require("./extended-header.js") + , assert = require("assert").ok + , inherits = require("inherits") + , fstream = require("fstream") + +// reading a tar is a lot like reading a directory +// However, we're actually not going to run the ctor, +// since it does a stat and various other stuff. +// This inheritance gives us the pause/resume/pipe +// behavior that is desired. +inherits(Parse, fstream.Reader) + +function Parse () { + var me = this + if (!(me instanceof Parse)) return new Parse() + + // doesn't apply fstream.Reader ctor? + // no, becasue we don't want to stat/etc, we just + // want to get the entry/add logic from .pipe() + Stream.apply(me) + + me.writable = true + me.readable = true + me._stream = new BlockStream(512) + + me._stream.on("error", function (e) { + me.emit("error", e) + }) + + me._stream.on("data", function (c) { + me._process(c) + }) + + me._stream.on("end", function () { + me._streamEnd() + }) + + me._stream.on("drain", function () { + me.emit("drain") + }) +} + +// overridden in Extract class, since it needs to +// wait for its DirWriter part to finish before +// emitting "end" +Parse.prototype._streamEnd = function () { + var me = this + if (!me._ended) me.error("unexpected eof") + me.emit("end") +} + +// a tar reader is actually a filter, not just a readable stream. +// So, you should pipe a tarball stream into it, and it needs these +// write/end methods to do that. +Parse.prototype.write = function (c) { + if (this._ended) { + return this.error("write() after end()") + } + return this._stream.write(c) +} + +Parse.prototype.end = function (c) { + this._ended = true + return this._stream.end(c) +} + +// don't need to do anything, since we're just +// proxying the data up from the _stream. +// Just need to override the parent's "Not Implemented" +// error-thrower. +Parse.prototype._read = function () {} + +Parse.prototype._process = function (c) { + assert(c && c.length === 512, "block size should be 512") + + // one of three cases. + // 1. A new header + // 2. A part of a file/extended header + // 3. One of two or more EOF null blocks + + if (this._entry) { + var entry = this._entry + entry.write(c) + if (entry._remaining === 0) { + entry.end() + this._entry = null + } + } else { + // either zeroes or a header + var zero = true + for (var i = 0; i < 512 && zero; i ++) { + zero = c[i] === 0 + } + + // eof is *at least* 2 blocks of nulls, and then the end of the + // file. you can put blocks of nulls between entries anywhere, + // so appending one tarball to another is technically valid. + // ending without the eof null blocks is not allowed, however. + if (zero) { + this._ended = this._eofStarted + this._eofStarted = true + } else { + this._ended = this._eofStarted = false + this._startEntry(c) + } + + } +} + +// take a header chunk, start the right kind of entry. +Parse.prototype._startEntry = function (c) { + var header = new TarHeader(c) + , self = this + , entry + , ev + , EntryType + , onend + , meta = false + + switch (tar.types[header.type]) { + case "File": + case "OldFile": + case "Link": + case "SymbolicLink": + case "CharacterDevice": + case "BlockDevice": + case "Directory": + case "FIFO": + case "ContiguousFile": + case "GNUDumpDir": + // start a file. + // pass in any extended headers + // These ones consumers are typically most interested in. + EntryType = Entry + ev = "entry" + break + + case "GlobalExtendedHeader": + // extended headers that apply to the rest of the tarball + EntryType = ExtendedHeader + onend = function () { + self._global = self._global || {} + Object.keys(entry.fields).forEach(function (k) { + self._global[k] = entry.fields[k] + }) + } + ev = "globalExtendedHeader" + meta = true + break + + case "ExtendedHeader": + case "OldExtendedHeader": + // extended headers that apply to the next entry + EntryType = ExtendedHeader + onend = function () { + self._extended = entry.fields + } + ev = "extendedHeader" + meta = true + break + + case "NextFileHasLongLinkpath": + // set linkpath= in extended header + EntryType = BufferEntry + onend = function () { + self._extended = self._extended || {} + self._extended.linkpath = entry.body + } + ev = "longLinkpath" + meta = true + break + + case "NextFileHasLongPath": + case "OldGnuLongPath": + // set path= in file-extended header + EntryType = BufferEntry + onend = function () { + self._extended = self._extended || {} + self._extended.path = entry.body + } + ev = "longPath" + meta = true + break + + default: + // all the rest we skip, but still set the _entry + // member, so that we can skip over their data appropriately. + // emit an event to say that this is an ignored entry type? + EntryType = Entry + ev = "ignoredEntry" + break + } + + var global, extended + if (meta) { + global = extended = null + } else { + var global = this._global + var extended = this._extended + + // extendedHeader only applies to one entry, so once we start + // an entry, it's over. + this._extended = null + } + entry = new EntryType(header, extended, global) + entry.meta = meta + + // only proxy data events of normal files. + if (!meta) { + entry.on("data", function (c) { + me.emit("data", c) + }) + } + + if (onend) entry.on("end", onend) + + this._entry = entry + var me = this + + entry.on("pause", function () { + me.pause() + }) + + entry.on("resume", function () { + me.resume() + }) + + if (this.listeners("*").length) { + this.emit("*", ev, entry) + } + + this.emit(ev, entry) + + // Zero-byte entry. End immediately. + if (entry.props.size === 0) { + entry.end() + this._entry = null + } +} diff --git a/node_modules/tar/old/README.md b/node_modules/tar/old/README.md new file mode 100644 index 0000000..aef9844 --- /dev/null +++ b/node_modules/tar/old/README.md @@ -0,0 +1 @@ +tar for node diff --git a/node_modules/tar/old/doc/example.js b/node_modules/tar/old/doc/example.js new file mode 100644 index 0000000..d29517e --- /dev/null +++ b/node_modules/tar/old/doc/example.js @@ -0,0 +1,24 @@ +// request a tar file, and then write it +require("http").request({...}, function (resp) { + resp.pipe(tar.createParser(function (file) { + if (file.isDirectory()) { + this.pause() + return fs.mkdir(file.name, function (er) { + if (er) return this.emit("error", er) + this.resume() + }) + } else if (file.isSymbolicLink()) { + this.pause() + return fs.symlink(file.link, file.name, function (er) { + if (er) return this.emit("error", er) + this.resume() + }) + } else if (file.isFile()) { + file.pipe(fs.createWriteStream(file.name)) + } + })) + // or maybe just have it do all that internally? + resp.pipe(tar.createParser(function (file) { + this.create("/extract/target/path", file) + })) +}) diff --git a/node_modules/tar/old/generator.js b/node_modules/tar/old/generator.js new file mode 100644 index 0000000..c2506c4 --- /dev/null +++ b/node_modules/tar/old/generator.js @@ -0,0 +1,387 @@ +module.exports = Generator +Generator.create = create + +var tar = require("./tar") + , Stream = require("stream").Stream + , Parser = require("./parser") + , fs = require("fs") + +function create (opts) { + return new Generator(opts) +} + +function Generator (opts) { + this.readable = true + this.currentFile = null + + this._paused = false + this._ended = false + this._queue = [] + + this.options = { cwd: process.cwd() } + Object.keys(opts).forEach(function (o) { + this.options[o] = opts[o] + }, this) + if (this.options.cwd.slice(-1) !== "/") { + this.options.cwd += "/" + } + + Stream.apply(this) +} + +Generator.prototype = Object.create(Stream.prototype) + +Generator.prototype.pause = function () { + if (this.currentFile) this.currentFile.pause() + this.paused = true + this.emit("pause") +} + +Generator.prototype.resume = function () { + this.paused = false + if (this.currentFile) this.currentFile.resume() + this.emit("resume") + this._processQueue() +} + +Generator.prototype.end = function () { + this._ended = true + this._processQueue() +} + +Generator.prototype.append = function (f, st) { + if (this._ended) return this.emit("error", new Error( + "Cannot append after ending")) + + // if it's a string, then treat it as a filename. + // if it's a number, then treat it as a fd + // if it's a Stats, then treat it as a stat object + // if it's a Stream, then stream it in. + var s = toFileStream(f, st) + if (!s) return this.emit("error", new TypeError( + "Invalid argument: "+f)) + + // make sure it's in the folder being added. + if (s.name.indexOf(this.options.cwd) !== 0) { + this.emit("error", new Error( + "Invalid argument: "+s.name+"\nOutside of "+this.options.cwd)) + } + + s.name = s.name.substr(this.options.cwd.length) + s.pause() + this._queue.push(s) + + if (!s._needStat) return this._processQueue() + + var self = this + fs.lstat(s.name, function (er, st) { + if (er) return self.emit("error", new Error( + "invalid file "+s.name+"\n"+er.message)) + s.mode = st.mode & 0777 + s.uid = st.uid + s.gid = st.gid + s.size = st.size + s.mtime = +st.mtime / 1000 + s.type = st.isFile() ? "0" + : st.isSymbolicLink() ? "2" + : st.isCharacterDevice() ? "3" + : st.isBlockDevice() ? "4" + : st.isDirectory() ? "5" + : st.isFIFO() ? "6" + : null + + // TODO: handle all the types in + // http://cdrecord.berlios.de/private/man/star/star.4.html + // for now, skip over unknown ones. + if (s.type === null) { + console.error("Unknown file type: " + s.name) + // kick out of the queue + var i = self._queue.indexOf(s) + if (i !== -1) self._queue.splice(i, 1) + self._processQueue() + return + } + + if (s.type === "2") return fs.readlink(s.name, function (er, n) { + if (er) return self.emit("error", new Error( + "error reading link value "+s.name+"\n"+er.message)) + s.linkname = n + s._needStat = false + self._processQueue() + }) + s._needStat = false + self._processQueue() + }) + return false +} + +function toFileStream (thing) { + if (typeof thing === "string") { + return toFileStream(fs.createReadStream(thing)) + } + + if (thing && typeof thing === "object") { + if (thing instanceof (Parser.File)) return thing + + if (thing instanceof Stream) { + if (thing.hasOwnProperty("name") && + thing.hasOwnProperty("mode") && + thing.hasOwnProperty("uid") && + thing.hasOwnProperty("gid") && + thing.hasOwnProperty("size") && + thing.hasOwnProperty("mtime") && + thing.hasOwnProperty("type")) return thing + + if (thing instanceof (fs.ReadStream)) { + thing.name = thing.path + } + + if (thing.name) { + thing._needStat = true + return thing + } + } + } + + return null +} + +Generator.prototype._processQueue = function processQueue () { + console.error("processQueue", this._queue[0]) + if (this._paused) return false + + if (this.currentFile || + this._queue.length && this._queue[0]._needStat) { + // either already processing one, or waiting on something. + return + } + + var f = this.currentFile = this._queue.shift() + if (!f) { + if (this._ended) { + // close it off with 2 blocks of nulls. + this.emit("data", new Buffer(new Array(512 * 2))) + this.emit("end") + this.emit("close") + } + return true + } + + if (f.type === Parser.File.types.Directory && + f.name.slice(-1) !== "/") { + f.name += "/" + } + + // write out a Pax header if the file isn't kosher. + if (this._needPax(f)) this._emitPax(f) + + // write out the header + f.ustar = true + this._emitHeader(f) + var fpos = 0 + , self = this + console.error("about to read body data", f) + f.on("data", function (c) { + self.emit("data", c) + self.fpos += c.length + }) + f.on("error", function (er) { self.emit("error", er) }) + f.on("end", function $END () { + // pad with \0 out to an even multiple of 512 bytes. + // this ensures that every file starts on a block. + var b = new Buffer(fpos % 512 || 512) + + for (var i = 0, l = b.length; i < l; i ++) b[i] = 0 + //console.log(b.length, b) + self.emit("data", b) + self.currentFile = null + self._processQueue() + }) + f.resume() +} + +Generator.prototype._needPax = function (f) { + // meh. why not? + return true + + return oddTextField(f.name, "NAME") || + oddTextField(f.link, "LINK") || + oddTextField(f.gname, "GNAME") || + oddTextField(f.uname, "UNAME") || + oddTextField(f.prefix, "PREFIX") +} + +// check if a text field is too long or non-ascii +function oddTextField (val, field) { + var nl = Buffer.byteLength(val) + , len = tar.fieldSize[field] + if (nl > len || nl !== val.length) return true +} + +// emit a Pax header of "key = val" for any file with +// odd or too-long field values. +Generator.prototype._emitPax = function (f) { + // since these tend to be relatively small, just go ahead + // and emit it all in-band. That saves having to keep + // track of the pax state in the generator, and we can + // go right back to emitting the file in the same tick. + var dir = f.name.replace(/[^\/]+\/?$/, "") + , base = f.name.substr(dir.length) + var pax = { name: dir + "PaxHeader/" +base + , mode: 0644 + , uid: f.uid + , gid: f.gid + , mtime: +f.mtime + // don't know size yet. + , size: -1 + , type: "x" // extended header + , ustar: true + , ustarVersion: "00" + , user: f.user || f.uname || "" + , group: f.group || f.gname || "" + , dev: { major: f.dev && f.dev.major || 0 + , minor: f.dev && f.dev.minor || 0 } + , prefix: f.prefix + , linkname: "" } + + // generate the Pax body + var kv = { path: (f.prefix ? f.prefix + "/" : "") + f.name + , atime: f.atime + , mtime: f.mtime + , ctime: f.ctime + , charset: "UTF-8" + , gid: f.gid + , uid: f.uid + , uname: f.user || f.uname || "" + , gname: f.group || f.gname || "" + , linkpath: f.linkpath || "" + , size: f.size + } + // "%d %s=%s\n", , , + // length includes the length of the length number, + // the key=val, and the \n. + var body = new Buffer(Object.keys(kv).map(function (key) { + if (!kv[key]) return ["", ""] + + var s = new Buffer(" " + key + "=" + kv[key]+"\n") + , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1 + + // if adding that many digits will make it go over that length, + // then add one to it + if (s.length > Math.pow(10, digits) - digits) digits ++ + + return [s.length + digits, s] + }).reduce(function (l, r) { + return l + r[0] + r[1] + }, "")) + + pax.size = body.length + this._emitHeader(pax) + this.emit("data", body) + // now the trailing buffer to make it an even number of 512 blocks + var b = new Buffer(512 + (body.length % 512 || 512)) + for (var i = 0, l = b.length; i < l; i ++) b[i] = 0 + this.emit("data", b) +} + +Generator.prototype._emitHeader = function (f) { + var header = new Buffer(new Array(512)) + , fields = tar.fields + , offs = tar.fieldOffs + , sz = tar.fieldSize + + addField(header, "NAME", f.name) + addField(header, "MODE", f.mode) + addField(header, "UID", f.uid) + addField(header, "GID", f.gid) + addField(header, "SIZE", f.size) + addField(header, "MTIME", +f.mtime) + // checksum is generated based on it being spaces + // then it's written as: "######\0 " + // where ### is a zero-lead 6-digit octal number + addField(header, "CKSUM", " ") + + addField(header, "TYPE", f.type) + addField(header, "LINKNAME", f.linkname || "") + if (f.ustar) { + console.error(">>> ustar!!") + addField(header, "USTAR", tar.ustar) + addField(header, "USTARVER", 0) + addField(header, "UNAME", f.user || "") + addField(header, "GNAME", f.group || "") + if (f.dev) { + addField(header, "DEVMAJ", f.dev.major || 0) + addField(header, "DEVMIN", f.dev.minor || 0) + } + addField(header, "PREFIX", f.prefix) + } else { + console.error(">>> no ustar!") + } + + // now the header is written except for checksum. + var ck = 0 + for (var i = 0; i < 512; i ++) ck += header[i] + addField(header, "CKSUM", nF(ck, 7)) + header[ offs[fields.CKSUM] + 7 ] = 0 + + this.emit("data", header) +} + +function addField (buf, field, val) { + var f = tar.fields[field] + console.error("Adding field", field, val) + val = typeof val === "number" + ? nF(val, tar.fieldSize[f]) + : new Buffer(val || "") + val.copy(buf, tar.fieldOffs[f]) +} + +function toBase256 (num, len) { + console.error("toBase256", num, len) + var positive = num > 0 + , buf = new Buffer(len) + if (!positive) { + // rare and slow + var b = num.toString(2).substr(1) + , padTo = (len - 1) * 8 + b = new Array(padTo - b.length + 1).join("0") + b + + // take the 2's complement + var ht = b.match(/^([01]*)(10*)?$/) + , head = ht[1] + , tail = ht[2] + head = head.split("1").join("2") + .split("0").join("1") + .split("2").join("0") + b = head + tail + + buf[0] = 0xFF + for (var i = 1; i < len; i ++) { + buf[i] = parseInt(buf.substr(i * 8, 8), 2) + } + return buf + } + + buf[0] = 0x80 + for (var i = 1, l = len, p = l - 1; i < l; i ++, p --) { + buf[p] = num % 256 + num = Math.floor(num / 256) + } + return buf +} + +function nF (num, size) { + var ns = num.toString(8) + + if (num < 0 || ns.length >= size) { + // make a base 256 buffer + // then return it + return toBase256(num, size) + } + + var buf = new Buffer(size) + ns = new Array(size - ns.length - 1).join("0") + ns + " " + buf[size - 1] = 0 + buf.asciiWrite(ns) + return buf +} diff --git a/node_modules/tar/old/parser.js b/node_modules/tar/old/parser.js new file mode 100644 index 0000000..1582ee7 --- /dev/null +++ b/node_modules/tar/old/parser.js @@ -0,0 +1,344 @@ +module.exports = Parser +Parser.create = create +Parser.File = File + +var tar = require("./tar") + , Stream = require("stream").Stream + , fs = require("fs") + +function create (cb) { + return new Parser(cb) +} + +var s = 0 + , HEADER = s ++ + , BODY = s ++ + , PAD = s ++ + +function Parser (cb) { + this.fields = tar.fields + this.fieldSize = tar.fieldSize + this.state = HEADER + this.position = 0 + this.currentFile = null + this._header = [] + this._headerPosition = 0 + this._bodyPosition = 0 + this.writable = true + Stream.apply(this) + if (cb) this.on("file", cb) +} + +Parser.prototype = Object.create(Stream.prototype) + +Parser.prototype.write = function (chunk) { + switch (this.state) { + case HEADER: + // buffer up to 512 bytes in memory, and then + // parse it, emit a "file" event, and stream the rest + this._header.push(chunk) + this._headerPosition += chunk.length + if (this._headerPosition >= tar.headerSize) { + return this._parseHeader() + } + return true + + case BODY: + // stream it through until the end of the file is reached, + // and then step over any \0 byte padding. + var cl = chunk.length + , bp = this._bodyPosition + , np = cl + bp + , s = this.currentFile.size + if (np < s) { + this._bodyPosition = np + return this.currentFile.write(chunk) + } + var c = chunk.slice(0, (s - bp)) + this.currentFile.write(c) + this._closeFile() + return this.write(chunk.slice(s - bp)) + + case PAD: + for (var i = 0, l = chunk.length; i < l; i ++) { + if (chunk[i] !== 0) { + this.state = HEADER + return this.write(chunk.slice(i)) + } + } + } + return true +} + +Parser.prototype.end = function (chunk) { + if (chunk) this.write(chunk) + if (this.currentFile) this._closeFile() + this.emit("end") + this.emit("close") +} + +// at this point, we have at least 512 bytes of header chunks +Parser.prototype._parseHeader = function () { + var hp = this._headerPosition + , last = this._header.pop() + , rem + + if (hp < 512) return this.emit("error", new Error( + "Trying to parse header before finished")) + + if (hp > 512) { + var ll = last.length + , llIntend = 512 - hp + ll + rem = last.slice(llIntend) + last = last.slice(0, llIntend) + } + this._header.push(last) + + var fields = tar.fields + , pos = 0 + , field = 0 + , fieldEnds = tar.fieldEnds + , fieldSize = tar.fieldSize + , set = {} + , fpos = 0 + + Object.keys(fieldSize).forEach(function (f) { + set[ fields[f] ] = new Buffer(fieldSize[f]) + }) + + this._header.forEach(function (chunk) { + for (var i = 0, l = chunk.length; i < l; i ++, pos ++, fpos ++) { + if (pos >= fieldEnds[field]) { + field ++ + fpos = 0 + } + // header is null-padded, so when the fields run out, + // just finish. + if (null === fields[field]) return + set[fields[field]][fpos] = chunk[i] + } + }) + + this._header.length = 0 + + // type definitions here: + // http://cdrecord.berlios.de/private/man/star/star.4.html + var type = set.TYPE.toString() + , file = this.currentFile = new File(set) + if (type === "\0" || + type >= "0" && type <= "7") { + this._addExtended(file) + this.emit("file", file) + } else if (type === "g") { + this._global = this._global || {} + readPax(this, file, this._global) + } else if (type === "h" || type === "x" || type === "X") { + this._extended = this._extended || {} + readPax(this, file, this._extended) + } else if (type === "K") { + this._readLongField(file, "linkname") + } else if (type === "L") { + this._readLongField(file, "name") + } + + this.state = BODY + if (rem) return this.write(rem) + return true +} + +function readPax (self, file, obj) { + var buf = "" + file.on("data", function (c) { + buf += c + var lines = buf.split(/\r?\n/) + buf = lines.pop() + lines.forEach(function (line) { + line = line.match(/^[0-9]+ ([^=]+)=(.*)/) + if (!line) return + obj[line[1]] = line[2] + }) + }) +} + +Parser.prototype._readLongField = function (f, field) { + var self = this + this._longFields[field] = "" + f.on("data", function (c) { + self._longFields[field] += c + }) +} + +Parser.prototype._addExtended = function (file) { + var g = this._global || {} + , e = this._extended || {} + file.extended = {} + ;[g, e].forEach(function (h) { + Object.keys(h).forEach(function (k) { + file.extended[k] = h[k] + // handle known fields + switch (k) { + case "path": file.name = h[k]; break + case "ctime": file.ctime = new Date(1000 * h[k]); break + case "mtime": file.mtime = new Date(1000 * h[k]); break + case "gid": file.gid = parseInt(h[k], 10); break + case "uid": file.uid = parseInt(h[k], 10); break + case "charset": file.charset = h[k]; break + case "gname": file.group = h[k]; break + case "uname": file.user = h[k]; break + case "linkpath": file.linkname = h[k]; break + case "size": file.size = parseInt(h[k], 10); break + case "SCHILY.devmajor": file.dev.major = parseInt(h[k], 10); break + case "SCHILY.devminor": file.dev.minor = parseInt(h[k], 10); break + } + }) + }) + var lf = this._longFields || {} + Object.keys(lf).forEach(function (f) { + file[f] = lf[f] + }) + this._extended = {} + this._longFields = {} +} + +Parser.prototype._closeFile = function () { + if (!this.currentFile) return this.emit("error", new Error( + "Trying to close without current file")) + + this._headerPosition = this._bodyPosition = 0 + this.currentFile.end() + this.currentFile = null + this.state = PAD +} + + +// file stuff + +function strF (f) { + return f.toString("ascii").split("\0").shift() || "" +} + +function parse256 (buf) { + // first byte MUST be either 80 or FF + // 80 for positive, FF for 2's comp + var positive + if (buf[0] === 0x80) positive = true + else if (buf[0] === 0xFF) positive = false + else return 0 + + if (!positive) { + // this is rare enough that the string slowness + // is not a big deal. You need *very* old files + // to ever hit this path. + var s = "" + for (var i = 1, l = buf.length; i < l; i ++) { + var byte = buf[i].toString(2) + if (byte.length < 8) { + byte = new Array(byte.length - 8 + 1).join("1") + byte + } + s += byte + } + var ht = s.match(/^([01]*)(10*)$/) + , head = ht[1] + , tail = ht[2] + head = head.split("1").join("2") + .split("0").join("1") + .split("2").join("0") + return -1 * parseInt(head + tail, 2) + } + + var sum = 0 + for (var i = 1, l = buf.length, p = l - 1; i < l; i ++, p--) { + sum += buf[i] * Math.pow(256, p) + } + return sum +} + +function nF (f) { + if (f[0] & 128 === 128) { + return parse256(f) + } + return parseInt(f.toString("ascii").replace(/\0+/g, "").trim(), 8) || 0 +} + +function bufferMatch (a, b) { + if (a.length != b.length) return false + for (var i = 0, l = a.length; i < l; i ++) { + if (a[i] !== b[i]) return false + } + return true +} + +function File (fields) { + this._raw = fields + this.name = strF(fields.NAME) + this.mode = nF(fields.MODE) + this.uid = nF(fields.UID) + this.gid = nF(fields.GID) + this.size = nF(fields.SIZE) + this.mtime = new Date(nF(fields.MTIME) * 1000) + this.cksum = nF(fields.CKSUM) + this.type = strF(fields.TYPE) + this.linkname = strF(fields.LINKNAME) + + this.ustar = bufferMatch(fields.USTAR, tar.ustar) + + if (this.ustar) { + this.ustarVersion = nF(fields.USTARVER) + this.user = strF(fields.UNAME) + this.group = strF(fields.GNAME) + this.dev = { major: nF(fields.DEVMAJ) + , minor: nF(fields.DEVMIN) } + this.prefix = strF(fields.PREFIX) + if (this.prefix) { + this.name = this.prefix + "/" + this.name + } + } + + this.writable = true + this.readable = true + Stream.apply(this) +} + +File.prototype = Object.create(Stream.prototype) + +File.types = { File: "0" + , HardLink: "1" + , SymbolicLink: "2" + , CharacterDevice: "3" + , BlockDevice: "4" + , Directory: "5" + , FIFO: "6" + , ContiguousFile: "7" } + +Object.keys(File.types).forEach(function (t) { + File.prototype["is"+t] = function () { + return File.types[t] === this.type + } + File.types[ File.types[t] ] = File.types[t] +}) + +// contiguous files are treated as regular files for most purposes. +File.prototype.isFile = function () { + return this.type === "0" && this.name.slice(-1) !== "/" + || this.type === "7" +} + +File.prototype.isDirectory = function () { + return this.type === "5" + || this.type === "0" && this.name.slice(-1) === "/" +} + +File.prototype.write = function (c) { + this.emit("data", c) + return true +} + +File.prototype.end = function (c) { + if (c) this.write(c) + this.emit("end") + this.emit("close") +} + +File.prototype.pause = function () { this.emit("pause") } + +File.prototype.resume = function () { this.emit("resume") } diff --git a/node_modules/tar/old/tar.js b/node_modules/tar/old/tar.js new file mode 100644 index 0000000..f70c081 --- /dev/null +++ b/node_modules/tar/old/tar.js @@ -0,0 +1,74 @@ +// field names that every tar file must have. +// header is padded to 512 bytes. +var f = 0 + , fields = {} + , NAME = fields.NAME = f++ + , MODE = fields.MODE = f++ + , UID = fields.UID = f++ + , GID = fields.GID = f++ + , SIZE = fields.SIZE = f++ + , MTIME = fields.MTIME = f++ + , CKSUM = fields.CKSUM = f++ + , TYPE = fields.TYPE = f++ + , LINKNAME = fields.LINKNAME = f++ + , headerSize = 512 + , fieldSize = [] + +fieldSize[NAME] = 100 +fieldSize[MODE] = 8 +fieldSize[UID] = 8 +fieldSize[GID] = 8 +fieldSize[SIZE] = 12 +fieldSize[MTIME] = 12 +fieldSize[CKSUM] = 8 +fieldSize[TYPE] = 1 +fieldSize[LINKNAME] = 100 + +// "ustar\0" may introduce another bunch of headers. +// these are optional, and will be nulled out if not present. +var ustar = new Buffer(6) +ustar.asciiWrite("ustar\0") + +var USTAR = fields.USTAR = f++ + , USTARVER = fields.USTARVER = f++ + , UNAME = fields.UNAME = f++ + , GNAME = fields.GNAME = f++ + , DEVMAJ = fields.DEVMAJ = f++ + , DEVMIN = fields.DEVMIN = f++ + , PREFIX = fields.PREFIX = f++ +// terminate fields. +fields[f] = null + +fieldSize[USTAR] = 6 +fieldSize[USTARVER] = 2 +fieldSize[UNAME] = 32 +fieldSize[GNAME] = 32 +fieldSize[DEVMAJ] = 8 +fieldSize[DEVMIN] = 8 +fieldSize[PREFIX] = 155 + +var fieldEnds = {} + , fieldOffs = {} + , fe = 0 +for (var i = 0; i < f; i ++) { + fieldOffs[i] = fe + fieldEnds[i] = (fe += fieldSize[i]) +} + +// build a translation table of field names. +Object.keys(fields).forEach(function (f) { + fields[fields[f]] = f +}) + +exports.ustar = ustar +exports.fields = fields +exports.fieldSize = fieldSize +exports.fieldOffs = fieldOffs +exports.fieldEnds = fieldEnds +exports.headerSize = headerSize + +var Parser = exports.Parser = require("./parser") +exports.createParser = Parser.create + +var Generator = exports.Generator = require("./generator") +exports.createGenerator = Generator.create diff --git a/node_modules/tar/old/test/test-generator.js b/node_modules/tar/old/test/test-generator.js new file mode 100644 index 0000000..dea2732 --- /dev/null +++ b/node_modules/tar/old/test/test-generator.js @@ -0,0 +1,13 @@ +// pipe this file to tar vt + +var Generator = require("../generator") + , fs = require("fs") + , path = require("path") + , ohm = fs.createReadStream(path.resolve(__dirname, "tar-files/Ω.txt")) + , foo = path.resolve(__dirname, "tar-files/foo.js") + , gen = Generator.create({cwd: __dirname}) + +gen.pipe(process.stdout) +gen.append(ohm) +//gen.append(foo) +gen.end() diff --git a/node_modules/tar/old/test/test-generator.tar b/node_modules/tar/old/test/test-generator.tar new file mode 100644 index 0000000..6752aa5 Binary files /dev/null and b/node_modules/tar/old/test/test-generator.tar differ diff --git a/node_modules/tar/old/test/test-generator.txt b/node_modules/tar/old/test/test-generator.txt new file mode 100644 index 0000000..349757b Binary files /dev/null and b/node_modules/tar/old/test/test-generator.txt differ diff --git a/node_modules/tar/old/test/test-parser.js b/node_modules/tar/old/test/test-parser.js new file mode 100644 index 0000000..ffc87a1 --- /dev/null +++ b/node_modules/tar/old/test/test-parser.js @@ -0,0 +1,28 @@ +var p = require("../tar").createParser() + , fs = require("fs") + , tar = require("../tar") + +p.on("file", function (file) { + console.error("file start", file.name, file.size, file.extended) + console.error(file) + Object.keys(file._raw).forEach(function (f) { + console.log(f, file._raw[f].toString().replace(/\0+$/, "")) + }) + file.on("data", function (c) { + console.error("data", c.toString().replace(/\0+$/, "")) + }) + file.on("end", function () { + console.error("end", file.name) + }) +}) + + +var s = fs.createReadStream(__dirname + "/test-generator.tar") +s.on("data", function (c) { + console.error("stream data", c.toString()) +}) +s.on("end", function () { console.error("stream end") }) +s.on("close", function () { console.error("stream close") }) +p.on("end", function () { console.error("parser end") }) + +s.pipe(p) diff --git a/node_modules/tar/old/test/test-tar.tar b/node_modules/tar/old/test/test-tar.tar new file mode 100644 index 0000000..e4fab49 Binary files /dev/null and b/node_modules/tar/old/test/test-tar.tar differ diff --git a/node_modules/tar/old/test/test-tar.txt b/node_modules/tar/old/test/test-tar.txt new file mode 100644 index 0000000..d9ac62c Binary files /dev/null and b/node_modules/tar/old/test/test-tar.txt differ diff --git a/node_modules/tar/package.json b/node_modules/tar/package.json new file mode 100644 index 0000000..c072867 --- /dev/null +++ b/node_modules/tar/package.json @@ -0,0 +1,26 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "name": "tar", + "description": "tar for node", + "version": "0.1.3", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-tar.git" + }, + "main": "tar.js", + "scripts": { + "test": "rm -rf test/tmp; tap test/*.js" + }, + "engines": { + "node": "~0.5.9 || 0.6 || 0.7 || 0.8" + }, + "dependencies": { + "inherits": "1.x", + "block-stream": "*", + "fstream": "0.1" + }, + "devDependencies": { + "tap": "0.x", + "rimraf": "1.x" + } +} diff --git a/node_modules/tar/tar.js b/node_modules/tar/tar.js new file mode 100644 index 0000000..b9dbca4 --- /dev/null +++ b/node_modules/tar/tar.js @@ -0,0 +1,172 @@ +// field paths that every tar file must have. +// header is padded to 512 bytes. +var f = 0 + , fields = {} + , path = fields.path = f++ + , mode = fields.mode = f++ + , uid = fields.uid = f++ + , gid = fields.gid = f++ + , size = fields.size = f++ + , mtime = fields.mtime = f++ + , cksum = fields.cksum = f++ + , type = fields.type = f++ + , linkpath = fields.linkpath = f++ + , headerSize = 512 + , blockSize = 512 + , fieldSize = [] + +fieldSize[path] = 100 +fieldSize[mode] = 8 +fieldSize[uid] = 8 +fieldSize[gid] = 8 +fieldSize[size] = 12 +fieldSize[mtime] = 12 +fieldSize[cksum] = 8 +fieldSize[type] = 1 +fieldSize[linkpath] = 100 + +// "ustar\0" may introduce another bunch of headers. +// these are optional, and will be nulled out if not present. + +var ustar = fields.ustar = f++ + , ustarver = fields.ustarver = f++ + , uname = fields.uname = f++ + , gname = fields.gname = f++ + , devmaj = fields.devmaj = f++ + , devmin = fields.devmin = f++ + , prefix = fields.prefix = f++ + , fill = fields.fill = f++ + +// terminate fields. +fields[f] = null + +fieldSize[ustar] = 6 +fieldSize[ustarver] = 2 +fieldSize[uname] = 32 +fieldSize[gname] = 32 +fieldSize[devmaj] = 8 +fieldSize[devmin] = 8 +fieldSize[prefix] = 155 +fieldSize[fill] = 12 + +// nb: prefix field may in fact be 130 bytes of prefix, +// a null char, 12 bytes for atime, 12 bytes for ctime. +// +// To recognize this format: +// 1. prefix[130] === ' ' or '\0' +// 2. atime and ctime are octal numeric values +// 3. atime and ctime have ' ' in their last byte + +var fieldEnds = {} + , fieldOffs = {} + , fe = 0 +for (var i = 0; i < f; i ++) { + fieldOffs[i] = fe + fieldEnds[i] = (fe += fieldSize[i]) +} + +// build a translation table of field paths. +Object.keys(fields).forEach(function (f) { + if (fields[f] !== null) fields[fields[f]] = f +}) + +// different values of the 'type' field +// paths match the values of Stats.isX() functions, where appropriate +var types = + { 0: "File" + , "\0": "OldFile" // like 0 + , 1: "Link" + , 2: "SymbolicLink" + , 3: "CharacterDevice" + , 4: "BlockDevice" + , 5: "Directory" + , 6: "FIFO" + , 7: "ContiguousFile" // like 0 + // posix headers + , g: "GlobalExtendedHeader" // k=v for the rest of the archive + , x: "ExtendedHeader" // k=v for the next file + // vendor-specific stuff + , A: "SolarisACL" // skip + , D: "GNUDumpDir" // like 5, but with data, which should be skipped + , I: "Inode" // metadata only, skip + , K: "NextFileHasLongLinkpath" // data = link path of next file + , L: "NextFileHasLongPath" // data = path of next file + , M: "ContinuationFile" // skip + , N: "OldGnuLongPath" // like L + , S: "SparseFile" // skip + , V: "TapeVolumeHeader" // skip + , X: "OldExtendedHeader" // like x + } + +Object.keys(types).forEach(function (t) { + types[types[t]] = types[types[t]] || t +}) + +// values for the mode field +var modes = + { suid: 04000 // set uid on extraction + , sgid: 02000 // set gid on extraction + , svtx: 01000 // set restricted deletion flag on dirs on extraction + , uread: 0400 + , uwrite: 0200 + , uexec: 0100 + , gread: 040 + , gwrite: 020 + , gexec: 010 + , oread: 4 + , owrite: 2 + , oexec: 1 + , all: 07777 + } + +var numeric = + { mode: true + , uid: true + , gid: true + , size: true + , mtime: true + , devmaj: true + , devmin: true + , cksum: true + , atime: true + , ctime: true + , dev: true + , ino: true + , nlink: true + } + +Object.keys(modes).forEach(function (t) { + modes[modes[t]] = modes[modes[t]] || t +}) + +var knownExtended = + { atime: true + , charset: true + , comment: true + , ctime: true + , gid: true + , gname: true + , linkpath: true + , mtime: true + , path: true + , realtime: true + , security: true + , size: true + , uid: true + , uname: true } + + +exports.fields = fields +exports.fieldSize = fieldSize +exports.fieldOffs = fieldOffs +exports.fieldEnds = fieldEnds +exports.types = types +exports.modes = modes +exports.numeric = numeric +exports.headerSize = headerSize +exports.blockSize = blockSize +exports.knownExtended = knownExtended + +exports.Pack = require("./lib/pack.js") +exports.Parse = require("./lib/parse.js") +exports.Extract = require("./lib/extract.js") diff --git a/node_modules/tar/test/extract.js b/node_modules/tar/test/extract.js new file mode 100644 index 0000000..e2dea5c --- /dev/null +++ b/node_modules/tar/test/extract.js @@ -0,0 +1,406 @@ +var tap = require("tap") + , tar = require("../tar.js") + , fs = require("fs") + , path = require("path") + , file = path.resolve(__dirname, "fixtures/c.tar") + , target = path.resolve(__dirname, "tmp/extract-test") + , index = 0 + , fstream = require("fstream") + + , ee = 0 + , expectEntries = +[ { path: 'c.txt', + mode: '644', + type: '0', + depth: undefined, + size: 513, + linkpath: '', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: 'cc.txt', + mode: '644', + type: '0', + depth: undefined, + size: 513, + linkpath: '', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '644', + type: '0', + depth: undefined, + size: 100, + linkpath: '', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: 'Ω.txt', + mode: '644', + type: '0', + depth: undefined, + size: 2, + linkpath: '', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: 'Ω.txt', + mode: '644', + type: '0', + depth: undefined, + size: 2, + linkpath: '', + nlink: 1, + dev: 234881026, + ino: 51693379 }, + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '644', + type: '0', + depth: undefined, + size: 200, + linkpath: '', + nlink: 1, + dev: 234881026, + ino: 51681874 }, + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '644', + type: '0', + depth: undefined, + size: 201, + linkpath: '', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', + mode: '777', + type: '2', + depth: undefined, + size: 0, + linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + nlink: undefined, + dev: undefined, + ino: undefined }, + { path: '200-hard', + mode: '644', + type: '0', + depth: undefined, + size: 200, + linkpath: '', + nlink: 2, + dev: 234881026, + ino: 51681874 }, + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '644', + type: '1', + depth: undefined, + size: 0, + linkpath: path.resolve(target, '200-hard'), + nlink: 2, + dev: 234881026, + ino: 51681874 } ] + + , ef = 0 + , expectFiles = +[ { path: '', + mode: '40755', + type: 'Directory', + depth: 0, + size: 306, + linkpath: undefined, + nlink: 9 }, + { path: '/200-hard', + mode: '100644', + type: 'File', + depth: 1, + size: 200, + linkpath: undefined, + nlink: 2 }, + { path: '/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '100644', + type: 'Link', + depth: 1, + size: 200, + linkpath: '/Users/isaacs/dev-src/js/node-tar/test/tmp/extract-test/200-hard', + nlink: 2 }, + { path: '/200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', + mode: '120777', + type: 'SymbolicLink', + depth: 1, + size: 200, + linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + nlink: 1 }, + { path: '/c.txt', + mode: '100644', + type: 'File', + depth: 1, + size: 513, + linkpath: undefined, + nlink: 1 }, + { path: '/cc.txt', + mode: '100644', + type: 'File', + depth: 1, + size: 513, + linkpath: undefined, + nlink: 1 }, + { path: '/r', + mode: '40755', + type: 'Directory', + depth: 1, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e', + mode: '40755', + type: 'Directory', + depth: 2, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a', + mode: '40755', + type: 'Directory', + depth: 3, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l', + mode: '40755', + type: 'Directory', + depth: 4, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l', + mode: '40755', + type: 'Directory', + depth: 5, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y', + mode: '40755', + type: 'Directory', + depth: 6, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-', + mode: '40755', + type: 'Directory', + depth: 7, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d', + mode: '40755', + type: 'Directory', + depth: 8, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e', + mode: '40755', + type: 'Directory', + depth: 9, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e', + mode: '40755', + type: 'Directory', + depth: 10, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p', + mode: '40755', + type: 'Directory', + depth: 11, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-', + mode: '40755', + type: 'Directory', + depth: 12, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f', + mode: '40755', + type: 'Directory', + depth: 13, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o', + mode: '40755', + type: 'Directory', + depth: 14, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l', + mode: '40755', + type: 'Directory', + depth: 15, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d', + mode: '40755', + type: 'Directory', + depth: 16, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e', + mode: '40755', + type: 'Directory', + depth: 17, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r', + mode: '40755', + type: 'Directory', + depth: 18, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-', + mode: '40755', + type: 'Directory', + depth: 19, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p', + mode: '40755', + type: 'Directory', + depth: 20, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a', + mode: '40755', + type: 'Directory', + depth: 21, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t', + mode: '40755', + type: 'Directory', + depth: 22, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h', + mode: '40755', + type: 'Directory', + depth: 23, + size: 102, + linkpath: undefined, + nlink: 3 }, + { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: '100644', + type: 'File', + depth: 24, + size: 100, + linkpath: undefined, + nlink: 1 }, + { path: '/Ω.txt', + mode: '100644', + type: 'File', + depth: 1, + size: 2, + linkpath: undefined, + nlink: 1 } ] + + + +// The extract class basically just pipes the input +// to a Reader, and then to a fstream.DirWriter + +// So, this is as much a test of fstream.Reader and fstream.Writer +// as it is of tar.Extract, but it sort of makes sense. + +tap.test("extract test", function (t) { + var extract = tar.Extract(target) + var inp = fs.createReadStream(file) + + // give it a weird buffer size to try to break in odd places + inp.bufferSize = 1234 + + inp.pipe(extract) + + extract.on("end", function () { + t.equal(ee, expectEntries.length, "should see "+ee+" entries") + + // should get no more entries after end + extract.removeAllListeners("entry") + extract.on("entry", function (e) { + t.fail("Should not get entries after end!") + }) + + next() + }) + + extract.on("entry", function (entry) { + var found = + { path: entry.path + , mode: entry.props.mode.toString(8) + , type: entry.props.type + , depth: entry.props.depth + , size: entry.props.size + , linkpath: entry.props.linkpath + , nlink: entry.props.nlink + , dev: entry.props.dev + , ino: entry.props.ino + } + + var wanted = expectEntries[ee ++] + + t.equivalent(found, wanted, "tar entry " + ee + " " + wanted.path) + }) + + function next () { + var r = fstream.Reader({ path: target + , type: "Directory" + // this is just to encourage consistency + , sort: "alpha" }) + + r.on("ready", function () { + foundEntry(r) + }) + + r.on("end", finish) + + function foundEntry (entry) { + var p = entry.path.substr(target.length) + var found = + { path: p + , mode: entry.props.mode.toString(8) + , type: entry.props.type + , depth: entry.props.depth + , size: entry.props.size + , linkpath: entry.props.linkpath + , nlink: entry.props.nlink + } + + var wanted = expectFiles[ef ++] + + t.equivalent(found, wanted, "unpacked file " + ef + " " + wanted.path) + + entry.on("entry", foundEntry) + } + + function finish () { + t.equal(ef, expectFiles.length, "should have "+ef+" items") + t.end() + } + } +}) diff --git a/node_modules/tar/test/fixtures/200.tar b/node_modules/tar/test/fixtures/200.tar new file mode 100644 index 0000000..7e3a8f3 Binary files /dev/null and b/node_modules/tar/test/fixtures/200.tar differ diff --git a/node_modules/tar/test/fixtures/200L.hex b/node_modules/tar/test/fixtures/200L.hex new file mode 100644 index 0000000..106fce3 --- /dev/null +++ b/node_modules/tar/test/fixtures/200L.hex @@ -0,0 +1,50 @@ +# longpath header +2e2f2e2f404c6f6e674c696e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303030303030003030303030303000303030303030300030303030303030303331310030303030303030303030300030313135363000204c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ././@LongLink.......................................................................................0000000.0000000.0000000.00000000311.00000000000.011560..L................................................................................................... +007573746172202000726f6f7400000000000000000000000000000000000000000000000000000000726f6f7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar...root............................root................................................................................................................................................................................................................... + +# longpath data +32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc........................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +# longpath file - note truncated path +32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363303030303634340030303031373530003030303137353000303030303030303033313100313136353233353435373600303333343036002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc0000644.0001750.0001750.00000000311.11652354576.033406..0................................................................................................... +00757374617220200069736161637300000000000000000000000000000000000000000000000000006973616163730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar...isaacs..........................isaacs................................................................................................................................................................................................................. + +# longpath file contents +32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc........................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +# tar eof +0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc b/node_modules/tar/test/fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc new file mode 100644 index 0000000..c2b6e50 --- /dev/null +++ b/node_modules/tar/test/fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc @@ -0,0 +1 @@ +200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/200longlink.tar b/node_modules/tar/test/fixtures/200longlink.tar new file mode 100644 index 0000000..bff94ee Binary files /dev/null and b/node_modules/tar/test/fixtures/200longlink.tar differ diff --git a/node_modules/tar/test/fixtures/200longname.tar b/node_modules/tar/test/fixtures/200longname.tar new file mode 100644 index 0000000..5556567 Binary files /dev/null and b/node_modules/tar/test/fixtures/200longname.tar differ diff --git a/node_modules/tar/test/fixtures/a.hex b/node_modules/tar/test/fixtures/a.hex new file mode 100644 index 0000000..529e9cb --- /dev/null +++ b/node_modules/tar/test/fixtures/a.hex @@ -0,0 +1,14 @@ +-- header -- +612e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303034303120313136353133363033333320303132343531002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 a.txt...............................................................................................000644..057761..000024..00000000401.11651360333.012451..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- file contents -- +61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 a............................................................................................................................................................................................................................................................... + +-- tar eof -- +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/a.tar b/node_modules/tar/test/fixtures/a.tar new file mode 100644 index 0000000..27604d7 Binary files /dev/null and b/node_modules/tar/test/fixtures/a.tar differ diff --git a/node_modules/tar/test/fixtures/a.txt b/node_modules/tar/test/fixtures/a.txt new file mode 100644 index 0000000..a6c4069 --- /dev/null +++ b/node_modules/tar/test/fixtures/a.txt @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/b.hex b/node_modules/tar/test/fixtures/b.hex new file mode 100644 index 0000000..cf36eb6 --- /dev/null +++ b/node_modules/tar/test/fixtures/b.hex @@ -0,0 +1,14 @@ +-- normal header -- +622e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303130303020313136353133363036373720303132343631002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 b.txt...............................................................................................000644..057761..000024..00000001000.11651360677.012461..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- file contents - exactly 512 bytes, no null padding -- +62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + +-- tar eof blocks -- +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/b.tar b/node_modules/tar/test/fixtures/b.tar new file mode 100644 index 0000000..2d8e7b3 Binary files /dev/null and b/node_modules/tar/test/fixtures/b.tar differ diff --git a/node_modules/tar/test/fixtures/b.txt b/node_modules/tar/test/fixtures/b.txt new file mode 100644 index 0000000..d6d6f17 --- /dev/null +++ b/node_modules/tar/test/fixtures/b.txt @@ -0,0 +1 @@ +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/c.hex b/node_modules/tar/test/fixtures/c.hex new file mode 100644 index 0000000..2391bd2 --- /dev/null +++ b/node_modules/tar/test/fixtures/c.hex @@ -0,0 +1,74 @@ +-- c.txt header +632e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303130303120313136353136353730343220303132343536002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 c.txt...............................................................................................000644..057761..000024..00000001001.11651657042.012456..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- c.txt data +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- cc.txt header +63632e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303130303120313136353136353730343620303132363235002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 cc.txt..............................................................................................000644..057761..000024..00000001001.11651657046.012625..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- cc.txt data +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/ccc.... header +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363303030363434200030353737363120003030303032342000303030303030303031343420313136353231353135333320303433333134002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc000644..057761..000024..00000000144.11652151533.043314..0................................................................................................... +0075737461720030306973616163730000000000000000000000000000000000000000000000000000737461666600000000000000000000000000000000000000000000000000000030303030303020003030303030302000722f652f612f6c2f6c2f792f2d2f642f652f652f702f2d2f662f6f2f6c2f642f652f722f2d2f702f612f742f680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000..r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h.......................................................................................................................... + +-- r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/ccc.... contents +63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc............................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- omega header, no pax +cea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303030303220313136353233313530363520303133303737002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.txt..............................................................................................000644..057761..000024..00000000002.11652315065.013077..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- omega contents +cea90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.............................................................................................................................................................................................................................................................. +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- paxheader for omega +5061784865616465722fcea92e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303031373020313136353233313530363520303135303536002078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 PaxHeader/Ω.txt....................................................................................000644..057761..000024..00000000170.11652315065.015056..x................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- paxheader content +313520706174683dcea92e7478740a3230206374696d653d313331393733373930390a3230206174696d653d313331393733393036310a323420534348494c592e6465763d3233343838313032360a323320534348494c592e696e6f3d35313639333337390a313820534348494c592e6e6c696e6b3d310a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 15.path=Ω.txt.20.ctime=1319737909.20.atime=1319739061.24.SCHILY.dev=234881026.23.SCHILY.ino=51693379.18.SCHILY.nlink=1......................................................................................................................................... +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- header for omega +cea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303030303220313136353233313530363520303133303737002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.txt..............................................................................................000644..057761..000024..00000000002.11652315065.013077..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- omega data +cea90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.............................................................................................................................................................................................................................................................. +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- paxheader for 200char filename +5061784865616465722f323030636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630000303030363434200030353737363120003030303032342000303030303030303035343120313136353231353133323420303334323330002078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc..000644..057761..000024..00000000541.11652151324.034230..x................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- paxheader content +32313020706174683d32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630a3230206374696d653d313331393638363836380a3230206174696d653d313331393734313235340a3338204c4942 210.path=200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.20.ctime=1319686868.20.atime=1319741254.38.LIB +415243484956452e6372656174696f6e74696d653d313331393638363835320a323420534348494c592e6465763d3233343838313032360a323320534348494c592e696e6f3d35313638313837340a313820534348494c592e6e6c696e6b3d310a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ARCHIVE.creationtime=1319686852.24.SCHILY.dev=234881026.23.SCHILY.ino=51681874.18.SCHILY.nlink=1................................................................................................................................................................ + +-- header for 200char filename (note truncated path) +32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636300303030363434200030353737363120003030303032342000303030303030303033313020313136353231353133323420303334333532002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.000644..057761..000024..00000000310.11652151324.034352..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- 200char data +32303063636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc........................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- tar eof +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/c.tar b/node_modules/tar/test/fixtures/c.tar new file mode 100644 index 0000000..f37a40a Binary files /dev/null and b/node_modules/tar/test/fixtures/c.tar differ diff --git a/node_modules/tar/test/fixtures/c.txt b/node_modules/tar/test/fixtures/c.txt new file mode 100644 index 0000000..943d92e --- /dev/null +++ b/node_modules/tar/test/fixtures/c.txt @@ -0,0 +1 @@ +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc diff --git a/node_modules/tar/test/fixtures/cc.txt b/node_modules/tar/test/fixtures/cc.txt new file mode 100644 index 0000000..943d92e --- /dev/null +++ b/node_modules/tar/test/fixtures/cc.txt @@ -0,0 +1 @@ +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc diff --git a/node_modules/tar/test/fixtures/foo.hex b/node_modules/tar/test/fixtures/foo.hex new file mode 100644 index 0000000..5a1b165 --- /dev/null +++ b/node_modules/tar/test/fixtures/foo.hex @@ -0,0 +1,14 @@ +-- normal header -- +666f6f2e6a7300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303030303420313135343336373037343120303132363137002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 foo.js..............................................................................................000644..057761..000024..00000000004.11543670741.012617..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- file contents -- +6261720a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 bar............................................................................................................................................................................................................................................................. +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- tar eof -- +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/foo.js b/node_modules/tar/test/fixtures/foo.js new file mode 100644 index 0000000..5716ca5 --- /dev/null +++ b/node_modules/tar/test/fixtures/foo.js @@ -0,0 +1 @@ +bar diff --git a/node_modules/tar/test/fixtures/foo.tar b/node_modules/tar/test/fixtures/foo.tar new file mode 100644 index 0000000..0f69f98 Binary files /dev/null and b/node_modules/tar/test/fixtures/foo.tar differ diff --git a/node_modules/tar/test/fixtures/hardlink-1 b/node_modules/tar/test/fixtures/hardlink-1 new file mode 100644 index 0000000..c2b6e50 --- /dev/null +++ b/node_modules/tar/test/fixtures/hardlink-1 @@ -0,0 +1 @@ +200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/hardlink-2 b/node_modules/tar/test/fixtures/hardlink-2 new file mode 100644 index 0000000..c2b6e50 --- /dev/null +++ b/node_modules/tar/test/fixtures/hardlink-2 @@ -0,0 +1 @@ +200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/omega.hex b/node_modules/tar/test/fixtures/omega.hex new file mode 100644 index 0000000..eef8796 --- /dev/null +++ b/node_modules/tar/test/fixtures/omega.hex @@ -0,0 +1,22 @@ +-- pax header -- +5061784865616465722fcea92e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303031373020313135343337313036313120303135303531002078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 PaxHeader/Ω.txt....................................................................................000644..057761..000024..00000000170.11543710611.015051..x................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- pax header contents -- +313520706174683dcea92e7478740a3230206374696d653d313330313435393237380a3230206174696d653d313330313431353738330a323420534348494c592e6465763d3233343838313032360a323320534348494c592e696e6f3d32333737323936360a313820534348494c592e6e6c696e6b3d310a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 15.path=Ω.txt.20.ctime=1301459278.20.atime=1301415783.24.SCHILY.dev=234881026.23.SCHILY.ino=23772966.18.SCHILY.nlink=1......................................................................................................................................... +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- normal header -- +cea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303030303220313135343337313036313120303133303732002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.txt..............................................................................................000644..057761..000024..00000000002.11543710611.013072..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- file contents -- +cea90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Ω.............................................................................................................................................................................................................................................................. +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + +-- tar eof marker -- +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ................................................................................................................................................................................................................................................................ + diff --git a/node_modules/tar/test/fixtures/omega.tar b/node_modules/tar/test/fixtures/omega.tar new file mode 100644 index 0000000..6590e58 Binary files /dev/null and b/node_modules/tar/test/fixtures/omega.tar differ diff --git a/node_modules/tar/test/fixtures/omega.txt b/node_modules/tar/test/fixtures/omega.txt new file mode 100644 index 0000000..1ca042f --- /dev/null +++ b/node_modules/tar/test/fixtures/omega.txt @@ -0,0 +1 @@ +Ω \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/omegapax.tar b/node_modules/tar/test/fixtures/omegapax.tar new file mode 100644 index 0000000..59bbd08 Binary files /dev/null and b/node_modules/tar/test/fixtures/omegapax.tar differ diff --git a/node_modules/tar/test/fixtures/packtest/omega.txt b/node_modules/tar/test/fixtures/packtest/omega.txt new file mode 100644 index 0000000..1ca042f --- /dev/null +++ b/node_modules/tar/test/fixtures/packtest/omega.txt @@ -0,0 +1 @@ +Ω \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/packtest/star.4.html b/node_modules/tar/test/fixtures/packtest/star.4.html new file mode 100644 index 0000000..b600d77 --- /dev/null +++ b/node_modules/tar/test/fixtures/packtest/star.4.html @@ -0,0 +1,1184 @@ + + +Manpage for star.4 + + + + +
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+
+
+

NAME

+     star - tape archive file format
+
+
+
+

DESCRIPTION

+     Tar Archives are layered archives.  The basic  structure  is
+     defined by the POSIX.1-1988 archive format and documented in
+     the BASIC TAR HEADER DESCRIPTION section below.  The  higher
+     level  structure  is  defined  by  the POSIX.1-2001 extended
+     headers and documented in  the  EXTENDED  TAR  (PAX)  HEADER
+     STRUCTURE  section below.  POSIX.1-2001 extended headers are
+     pseudo files that contain an unlimited  number  of  extended
+     header  keywords  and associated values. The header keywords
+     are documented in the EXTENDED  TAR  (PAX)  HEADER  KEYWORDS
+     section below.
+
+
+
+

BASIC TAR HEADER DESCRIPTION

+     Physically, a POSIX.1-1988 tar archive consists of a  series
+     of  fixed  sized blocks of TBLOCK (512) characters.  It con-
+     tains a series of  file  entries  terminated  by  a  logical
+     end-of-archive  marker,  which consists of two blocks of 512
+     bytes of binary zeroes.  Each file entry is represented by a
+     header block that describes the file followed by one or more
+     blocks with the content of the file. The length of each file
+     is rounded up to a multiple of 512 bytes.
+
+     A number of TBLOCK sizes blocks are grouped  together  to  a
+     tape  record  for  physical I/O operations. Each record of n
+     blocks is written with a single write(2) operation.  On mag-
+     netic tapes, this results in a single tape record.
+
+     The header block is defined in star.h as follows:
+     /*
+      * POSIX.1-1988 field size values and magic.
+      */
+     #define   TBLOCK         512
+     #define   NAMSIZ         100
+     #define   PFXSIZ         155
+
+     #define   TMODLEN        8
+     #define   TUIDLEN        8
+     #define   TGIDLEN        8
+     #define   TSIZLEN        12
+     #define   TMTMLEN        12
+     #define   TCKSLEN        8
+
+     #define   TMAGIC         "ustar"   /* ustar magic 6 chars + '\0' */
+     #define   TMAGLEN        6         /* "ustar" including '\0' */
+     #define   TVERSION       "00"
+     #define   TVERSLEN       2
+     #define   TUNMLEN        32
+     #define   TGNMLEN        32
+     #define   TDEVLEN        8
+
+Joerg Schilling       Last change: 05/10/19                     1
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     /*
+      * POSIX.1-1988 typeflag values
+      */
+     #define   REGTYPE        '0'  /* Regular File          */
+     #define   AREGTYPE       '\0' /* Regular File (outdated) */
+     #define   LNKTYPE        '1'  /* Hard Link             */
+     #define   SYMTYPE        '2'  /* Symbolic Link         */
+     #define   CHRTYPE        '3'  /* Character Special     */
+     #define   BLKTYPE        '4'  /* Block Special         */
+     #define   DIRTYPE        '5'  /* Directory             */
+     #define   FIFOTYPE       '6'  /* FIFO (named pipe)     */
+     #define   CONTTYPE       '7'  /* Contiguous File       */
+
+     /*
+      * POSIX.1-2001 typeflag extensions.
+      * POSIX.1-2001 calls the extended USTAR format PAX although it is
+      * definitely derived from and based on USTAR. The reason may be that
+      * POSIX.1-2001 calls the tar program outdated and lists the
+      * pax program as the successor.
+      */
+     #define   LF_GHDR        'g'  /* POSIX.1-2001 global extended header */
+     #define   LF_XHDR        'x'  /* POSIX.1-2001 extended header */
+
+     See section EXTENDED TAR  (PAX)  HEADER  KEYWORDS  for  more
+     information about the structure of a POSIX.1-2001 header.
+
+     /*
+      * star/gnu/Sun tar extensions:
+      *
+      * Note that the standards committee allows only capital A through
+      * capital Z for user-defined expansion.  This means that defining
+      * something as, say '8' is a *bad* idea.
+      */
+
+     #define   LF_ACL         'A'  /* Solaris Access Control List     */
+     #define   LF_DUMPDIR     'D'  /* GNU dump dir                    */
+     #define   LF_EXTATTR     'E'  /* Solaris Extended Attribute File */
+     #define   LF_META        'I'  /* Inode (metadata only) no file content */
+     #define   LF_LONGLINK    'K'  /* NEXT file has a long linkname   */
+     #define   LF_LONGNAME    'L'  /* NEXT file has a long name       */
+     #define   LF_MULTIVOL    'M'  /* Continuation file rest to be skipped */
+     #define   LF_NAMES       'N'  /* OLD GNU for names > 100 characters*/
+     #define   LF_SPARSE      'S'  /* This is for sparse files        */
+     #define   LF_VOLHDR      'V'  /* tape/volume header Ignore on extraction */
+     #define   LF_VU_XHDR     'X'  /* POSIX.1-2001 xtended (Sun VU version) */
+
+     /*
+      * Definitions for the t_mode field
+      */
+     #define   TSUID     04000     /* Set UID on execution  */
+     #define   TSGID     02000     /* Set GID on execution  */
+     #define   TSVTX     01000     /* On directories, restricted deletion flag */
+
+Joerg Schilling       Last change: 05/10/19                     2
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     #define   TUREAD    00400     /* Read by owner         */
+     #define   TUWRITE   00200     /* Write by owner special */
+     #define   TUEXEC    00100     /* Execute/search by owner */
+     #define   TGREAD    00040     /* Read by group         */
+     #define   TGWRITE   00020     /* Write by group        */
+     #define   TGEXEC    00010     /* Execute/search by group */
+     #define   TOREAD    00004     /* Read by other         */
+     #define   TOWRITE   00002     /* Write by other        */
+     #define   TOEXEC    00001     /* Execute/search by other */
+
+     #define   TALLMODES 07777     /* The low 12 bits       */
+
+     /*
+      * This is the ustar (Posix 1003.1) header.
+      */
+     struct header {
+          char t_name[NAMSIZ];     /*   0 Filename               */
+          char t_mode[8];          /* 100 Permissions            */
+          char t_uid[8];           /* 108 Numerical User ID      */
+          char t_gid[8];           /* 116 Numerical Group ID     */
+          char t_size[12];         /* 124 Filesize               */
+          char t_mtime[12];        /* 136 st_mtime               */
+          char t_chksum[8];        /* 148 Checksum               */
+          char t_typeflag;         /* 156 Typ of File            */
+          char t_linkname[NAMSIZ]; /* 157 Target of Links        */
+          char t_magic[TMAGLEN];   /* 257 "ustar"                */
+          char t_version[TVERSLEN]; /* 263 Version fixed to 00   */
+          char t_uname[TUNMLEN];   /* 265 User Name              */
+          char t_gname[TGNMLEN];   /* 297 Group Name             */
+          char t_devmajor[8];      /* 329 Major for devices      */
+          char t_devminor[8];      /* 337 Minor for devices      */
+          char t_prefix[PFXSIZ];   /* 345 Prefix for t_name      */
+                                   /* 500 End                    */
+          char t_mfill[12];        /* 500 Filler up to 512       */
+     };
+
+     /*
+      * star header specific definitions
+      */
+     #define   STMAGIC        "tar"     /* star magic */
+     #define   STMAGLEN       4         /* "tar" including '\0' */
+
+     /*
+      * This is the new (post Posix 1003.1-1988) xstar header
+      * defined in 1994.
+      *
+      * t_prefix[130]    is guaranteed to be ' ' to prevent ustar
+      *                  compliant implementations from failing.
+      * t_mfill & t_xmagic need to be zero for a 100% ustar compliant
+      *                  implementation, so setting t_xmagic to
+      *                  "tar" should be avoided in the future.
+      *
+
+Joerg Schilling       Last change: 05/10/19                     3
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+      * A different method to recognize this format is to verify that
+      * t_prefix[130]              is equal to ' ' and
+      * t_atime[0]/t_ctime[0]      is an octal number and
+      * t_atime[11]                is equal to ' ' and
+      * t_ctime[11]                is equal to ' '.
+      *
+      * Note that t_atime[11]/t_ctime[11] may be changed in future.
+      */
+     struct xstar_header {
+          char t_name[NAMSIZ];     /*   0 Filename               */
+          char t_mode[8];          /* 100 Permissions            */
+          char t_uid[8];           /* 108 Numerical User ID      */
+          char t_gid[8];           /* 116 Numerical Group ID     */
+          char t_size[12];         /* 124 Filesize               */
+          char t_mtime[12];        /* 136 st_mtime               */
+          char t_chksum[8];        /* 148 Checksum               */
+          char t_typeflag;         /* 156 Typ of File            */
+          char t_linkname[NAMSIZ]; /* 157 Target of Links        */
+          char t_magic[TMAGLEN];   /* 257 "ustar"                */
+          char t_version[TVERSLEN]; /* 263 Version fixed to 00   */
+          char t_uname[TUNMLEN];   /* 265 User Name              */
+          char t_gname[TGNMLEN];   /* 297 Group Name             */
+          char t_devmajor[8];      /* 329 Major for devices      */
+          char t_devminor[8];      /* 337 Minor for devices      */
+          char t_prefix[131];      /* 345 Prefix for t_name      */
+          char t_atime[12];        /* 476 st_atime               */
+          char t_ctime[12];        /* 488 st_ctime               */
+          char t_mfill[8];         /* 500 Filler up to star magic     */
+          char t_xmagic[4];        /* 508 "tar"                  */
+     };
+
+     struct sparse {
+          char t_offset[12];
+          char t_numbytes[12];
+     };
+
+     #define   SPARSE_EXT_HDR  21
+
+     struct xstar_ext_header {
+          struct sparse t_sp[21];
+          char t_isextended;
+     };
+
+     typedef union hblock {
+          char dummy[TBLOCK];
+          long ldummy[TBLOCK/sizeof (long)]; /* force long alignment */
+          struct header            dbuf;
+          struct xstar_header      xstar_dbuf;
+          struct xstar_ext_header  xstar_ext_dbuf;
+     } TCB;
+
+Joerg Schilling       Last change: 05/10/19                     4
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     For maximum portability, all fields that  contain  character
+     strings should be limited to use the low 7 bits of a charac-
+     ter.
+
+     The  name,  linkname  and  prefix  field  contain  character
+     strings.  The  strings  are null terminated except when they
+     use the full space of 100 characters for the name  or  link-
+     name field or 155 characters for the prefix field.
+
+     If the prefix does not start with  a  null  character,  then
+     prefix and name need to be concatenated by using the prefix,
+     followed a slash character followed by the name field.  If a
+     null  character appears in name or prefix before the maximum
+     size is reached, the field in question is terminated.   This
+     way  file  names  up to 256 characters may be archived.  The
+     prefix is not used together with the linkname field, so  the
+     maximum length of a link name is 100 characters.
+
+     The fields magic, uname and gname  contain  null  terminated
+     character strings.
+
+     The version field contains the string "00" without a  trail-
+     ing  zero.  It cannot be set to different values as POSIX.1-
+     1988 did not specify  a  way  to  handle  different  version
+     strings.  The typeflag field contains a single character.
+
+     All  numeric  fields  contain  size-1  leading   zero-filled
+     numbers  using  octal  digits.   They are followed by one or
+     more space or null characters.  All  recent  implementations
+     only use one space or null character at the end of a numeri-
+     cal field to get maximum space for the octal  number.   Star
+     always uses a space character as terminator.  Numeric fields
+     with 8 characters may hold up to 7  octal  digits  (7777777)
+     which results is a maximum value of 2097151.  Numeric fields
+     with  12  characters  may  hold  up  to  11   octal   digits
+     (77777777777)   which   results   is   a  maximum  value  of
+     8589934591.
+
+     Star implements  a  vendor  specific  (and  thus  non-POSIX)
+     extension  to  put  bigger  numbers into the numeric fields.
+     This is done by using a base 256 coding.  The top bit of the
+     first character in the appropriate 8 character or 12 charac-
+     ter field is set to flag non octal coding.  If base 256 cod-
+     ing  is  in  use,  then all remaining characters are used to
+     code the number. This results in 7  base  256  digits  in  8
+     character  fields  and in 11 base 256 digits in 12 character
+     fields.  All base 256 numbers are two's complement  numbers.
+     A base 256 number in a 8 character field may hold 56 bits, a
+     base 256 number in a 12 character field may  hold  88  bits.
+     This  may  extended to 64 bits for 8 character fields and to
+     95 bits for 12 character fields. For a negative  number  the
+     first  character  currently  is set to a value of 255 (all 8
+
+Joerg Schilling       Last change: 05/10/19                     5
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     bits are set).  The rightmost character in a 8 or 12 charac-
+     ter  field  contains  the least significant base 256 number.
+     Recent GNU tar versions implement the same extension.
+
+     While the POSIX standard makes obvious that the fields mode,
+     uid,  gid,    size,  chksum, devmajor and devminor should be
+     treated as unsigned numbers, there is no such definition for
+     the time field.
+
+     The mode field contains 12  bits  holding  permissions,  see
+     above for the definitions for each of the permission bits.
+
+     The uid and gid fields contain the numerical user id of  the
+     file.
+
+     The size field contains the size of the file in  characters.
+     If  the tar header is followed by file data, then the amount
+     of data that follows is computed by (size + 511) / 512.
+
+     The mtime filed contains the number of seconds since Jan 1st
+     1970 00:00 UTC as retrived via stat(2) in st_mtime.
+
+     The chksum field contains a simple checksum over  all  bytes
+     of  the header.  To compute the value, all characters in the
+     header are treated as unsigned integers and  the  characters
+     in  the chksum field are treated as if they were all spaces.
+     When the computation starts, the checksum value is  initial-
+     ized to 0.
+
+     The typeflag field specifies the type of the  file  that  is
+     archived.  If a specific tar implementation does not include
+     support for a specific typeflag value,  this  implementation
+     will  extract  the  unknown file types as if they were plain
+     files.
+
+     '0' REGTYPE
+          A regular file.  If the size field is  non  zero,  then
+          file data follows the header.
+
+     '\0' AREGTYPE
+          For backwards compatibility with pre  POSIX.1-1988  tar
+          implementations,  a nul character is also recognized as
+          marker for plain files.  It is not generated by  recent
+          tar  implementations.   If  the size field is non zero,
+          then file data follows the header.
+
+     '1' LNKTYPE
+          The file is a hard link to another file.  The  name  of
+          the  file that the file is linked to is in the linkname
+          part of the header.  For tar archives  written  by  pre
+          POSIX.1-1988  implementations,  the  size field usually
+          contains the size of the file and needs to  be  ignored
+
+Joerg Schilling       Last change: 05/10/19                     6
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          as  no  data may follow this header type.  For POSIX.1-
+          1988 compliant archives, the size field needs to be  0.
+          For POSIX.1-2001 compliant archives, the size field may
+          be non zero, indicating that file data is  included  in
+          the archive.
+
+     '2' SYMTYPE
+          The file is a symbolic link to another file.  The  name
+          of  the file that the file is linked to is in the link-
+          name part of the header.  The size field needs to be 0.
+          No file data may follow the header.
+
+     '3' CHRTYPE
+          A character special file.  The fields devmajor and dev-
+          minor  contain  information that defines the file.  The
+          meaning of the size field is unspecified by  the  POSIX
+          standard.  No file data may follow the header.
+
+     '4' BLKTYPE
+          A block special file.  The fields devmajor and devminor
+          contain information that defines the file.  The meaning
+          of the size field is unspecified by the POSIX standard.
+          No file data may follow the header.
+
+     '5' DIRTYPE
+          A directory or sub directory.  Old  (pre  POSIX.1-1988)
+          tar  implementations did use the same typeflag value as
+          for plain files and added a slash to the name.  If  the
+          size  field  is  non zero then it indicates the maximum
+          size in characters the system  may  allocate  for  this
+          directory.  If  the  size  field  is 0, then the system
+          shall not limit the size of the directory. On operating
+          systems  where  the  disk  allocation  is not done on a
+          directory base, the size field is  ignored  on  extrac-
+          tion.  No file data may follow the header.
+
+     '6' FIFOTYPE
+          A named  pipe.   The  meaning  of  the  size  field  is
+          unspecified by the POSIX standard.  The size field must
+          be ignored on extraction.  No file data may follow  the
+          header.
+
+     '7' CONTTYPE
+          A contiguous file.  This is a file that  gives  special
+          performance  attributes.   Operating systems that don't
+          support this file type extract this file type as  plain
+          files.   If  the size field is non zero, then file data
+          follows the header.
+
+     'g' GLOBAL POSIX.1-2001 HEADER
+          With POSIX.1-2001 pax archives,  this  type  defines  a
+          global  extended  header.   The size is always non zero
+
+Joerg Schilling       Last change: 05/10/19                     7
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          and denotes  the  sum  of  the  length  fields  in  the
+          extended header data.  The data that follows the header
+          is in the pax extended  header  format.   The  extended
+          header records in this header type affect all following
+          files in the archive unless they are overwritten by new
+          values.   See  EXTENDED TAR (PAX) HEADER FORMAT section
+          below.
+
+     'x' EXTENDED POSIX.1-2001 HEADER
+          With POSIX.1-2001 pax archives, this  type  defines  an
+          extended  header.   The  size  is  always  non zero and
+          denotes the sum of the length fields  in  the  extended
+          header  data.   The  data that follows the header is in
+          the pax extended header format.   The  extended  header
+          records  in  this header type only affect the following
+          file in the archive.  See  EXTENDED  TAR  (PAX)  HEADER
+          FORMAT section below.
+
+     'A' - 'Z'
+          Reserved for vendor specific implementations.
+
+     'A'  A Solaris ACL entry as used by the  tar  implementation
+          from  Sun.  The size is always non zero and denotes the
+          length of the  data  that  follows  the  header.   Star
+          currently is not able to handle this header type.
+
+     'D'  A GNU dump directory.  This header type is not  created
+          by  star and handled like a directory during an extract
+          operation, so the content is ignored by star.  The size
+          field  denotes  the length of the data that follows the
+          header.
+
+     'E'  A Solaris Extended  Attribute  File.   The  size  field
+          denotes the length of the data that follows the header.
+          Star currently is not able to handle this header type.
+
+     'I'  A inode metadata entry.  This header type  is  used  by
+          star  to archive inode meta data only.  To archive more
+          inode meta data than possible with a  POSIX-1.1988  tar
+          header, a header with type 'I' is usually preceded by a
+          'x' header.  It is used with incremental backups.   The
+          size  field holds the length of the file.  No file data
+          follows this header.
+
+     'K'  A long link name.  Star is able to read and write  this
+          type  of  header.  With the xustar and exustar formats,
+          star  prefers  to  store  long  link  names  using  the
+          POSIX.1-2001  method.   The size is always non zero and
+          denotes the length of the long link name including  the
+          trailing  null  byte. The link name is in the data that
+          follows the header.
+
+Joerg Schilling       Last change: 05/10/19                     8
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     'L'  A long file name.  Star is able to read and write  this
+          type  of  header.  With the xustar and exustar formats,
+          star  prefers  to  store  long  file  names  using  the
+          POSIX.1-2001  method.   The size is always non zero and
+          denotes the length of the long file name including  the
+          trailing  null  byte. The file name is in the data that
+          follows the header.
+
+     'M'  A multi volume continuation entry.  It is used by  star
+          to  tell the extraction program via the size field when
+          the next regular  archive  header  will  follow.   This
+          allows to start extracting multi volume archives with a
+          volume number greater than one.  It is used by GNU  tar
+          to  verify  multi  volume  continuation volumes.  Other
+          fields in the GNU multi volume continuation header  are
+          a  result  of  a  GNU tar miss conception and cannot be
+          used.  If the size field is non zero the data following
+          the header is skipped by star if the volume that starts
+          with it is mounted as the first volume.  This header is
+          ignored if the volume that starts with it is mounted as
+          continuation volume.
+
+     'N'  An outdated linktype used by old GNU  tar  versions  to
+          store  long  file  names.   This type is unsupported by
+          star.
+
+     'S'  A sparse file.  This header type is used  by  star  and
+          GNU  tar.   A  sparse header is uses instead of a plain
+          file header to  denote  a  sparse  file  that  follows.
+          Directly  after  the  header,  a  list  of  sparse hole
+          descriptors follows  followed  by  the  compacted  file
+          data.   With  star formats, the size field holds a size
+          that represents the sum of the sparse hole  descriptors
+          plus  the  size of the compacted file data. This allows
+          other tar implementations to correctly skip to the next
+          tar header.  With GNU tar, up to 4 sparse hole descrip-
+          tors fit  into  the  sparse  header.   Additional  hole
+          descriptors  are not needed if the file has less than 4
+          holes.  With GNU tar, the size field breaks general tar
+          header rules and is meaningless because the size of the
+          sparse hole descriptors does not count.
+
+     'V'  A volume header.  The name field is is used to hold the
+          volume  name.   Star  uses  the atime field to hold the
+          volume number in case there is no POSIX.1-2001 extended
+          header.   This header type is used by star and GNU tar.
+          If the size field is non zero the  data  following  the
+          header is skipped by star.
+
+     'X'  A vendor unique variant of  the  POSIX.1-2001  extended
+          header type.  It has been implemented by Sun many years
+          before the POSIX.1-2001  standard  has  been  approved.
+
+Joerg Schilling       Last change: 05/10/19                     9
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          See also the typeflag 'x' header type.  Star is able to
+          read and write this type of header.
+
+
+
+

EXTENDED TAR (PAX) HEADER STRUCTURE

+     Block type                            Description
+
+     Ustar Header [typeflag='g']      Global Extended Header
+     Global Extended Data
+     Ustar Header [typeflag='h']         Extended Header
+     Extended Data
+     Ustar header [typeflag='0']    File with Extended Header
+     Data for File #1
+     Ustar header [typeflag='0']   File without Extended Header
+     Data for File #2
+     Block of binary zeroes              First EOF Block
+     Block of binary zeroes              Second EOF Block
+
+
+
+

EXTENDED TAR (PAX) HEADER FORMAT

+     The data block  that  follows  a  tar  archive  header  with
+     typeflag 'g' or 'x' contains one or more records in the fol-
+     lowing format:
+
+          "%d %s=%s\n", <length>, <keyword>, <value>
+
+     Each record starts with a a decimal length field. The length
+     includes  the  total  size  of a record including the length
+     field itself and the trailing new line.
+
+     The keyword may not include an  equal  sign.   All  keywords
+     beginning  with  lower  case letters and digits are reserved
+     for future use by the POSIX standard.
+
+     If the value field is of zero length, it deletes any  header
+     field  of  the  same  name  that  is in effect from the same
+     extended header or from a previous global header.
+
+     Null characters do not delimit any value. The value is  only
+     limited by its implicit length.
+
+
+
+

EXTENDED TAR (PAX) HEADER KEYWORDS

+     POSIX.1-2001 extended pax  header  keywords.  All  numerical
+     values  are  represented  as decimal strings.  All texts are
+     represented as 7-bit ascii or UTF-8:
+
+     atime
+          The time from st_atime in sub second granularity.  Star
+          currently supports a nanosecond granularity.
+
+     charset
+          The name of the character set used to encode  the  data
+          in  the  following  file(s).  This keyword is currently
+
+Joerg Schilling       Last change: 05/10/19                    10
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          ignored by star.
+
+     comment
+          Any number of characters that  should  be  treated  as
+          comment.  Star ignores the comment as documented by the
+          POSIX standard.
+
+     ctime
+          The time from st_ctime in sub second granularity.  Star
+          currently supports a nanosecond granularity.
+
+     gid  The group ID of the group  that  owns  the  file.   The
+          argument  is  a  decimal number.  This field is used if
+          the group ID of a file is greater than  2097151  (octal
+          7777777).
+
+     gname
+          The group name of the following file(s) coded in  UTF-8
+          if  the  group name does not fit into 323 characters or
+          cannot be expressed in 7-Bit ASCII.
+
+     linkpath
+          The name of the linkpath coded in UTF-8 if it is longer
+          than  100  characters  or  cannot be expressed in 7-Bit
+          ASCII.
+
+     mtime
+          The time from st_mtime in sub second granularity.  Star
+          currently supports a nanosecond granularity.
+
+     path The name of the linkpath coded in UTF-8 if it does  not
+          fit into 100 characters + 155 characters prefix or can-
+          not be expressed in 7-Bit ASCII.
+
+     realtime.any
+          The keywords prefixed by  realtime.  are  reserved  for
+          future standardization.
+
+     security.any
+          The keywords prefixed by  security.  are  reserved  for
+          future standardization.
+
+     size The size of the file as decimal number if the file size
+          is  greater  than  8589934591  (octal 77777777777). The
+          size keyword may not refer to the real file size but is
+          related  to  the  size if the file in the archive.  See
+          also SCHILY.realsize for more information.
+
+     uid  The uid ID of the group that owns the file.  The  argu-
+          ment  is  a  decimal number.  This field is used if the
+          uid ID  of  a  file  is  greater  than  2097151  (octal
+          7777777).
+
+Joerg Schilling       Last change: 05/10/19                    11
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     uname
+          The user name of the following file(s) coded  in  UTF-8
+          if  the  user  name does not fit into 323 characters or
+          cannot be expressed in 7-Bit ASCII.
+
+     VENDOR.keyword
+          Any keyword that starts with a vendor name  in  capital
+          letters  is  reserved for vendor specific extensions by
+          the standard.  Star uses a lot of these vendor specific
+          extension. See below for more informations.
+
+
+
+

SCHILY PAX EXTENSION KEYWORDS

+     Star uses own vendor specific extensions. The SCHILY  vendor
+     specific extended pax header keywords are:
+
+     SCHILY.acl.access
+          The ACL for a file.
+
+          Since no official backup format for POSIX  access  con-
+          trol  lists  has  been  defined,  star  uses the vendor
+          defined      attributes      SCHILY.acl.access      and
+          SCHILY.acl.default  for storing the ACL and Default ACL
+          of a file, respectively.  The access control lists  are
+          stored  in  the  short  text  form  as defined in POSIX
+          1003.1e draft standard 17.
+
+          To each named user ACL entry a fourth  colon  separated
+          field field containing the user identifier (UID) of the
+          associated user is appended.  To each named group entry
+          a  fourth  colon  separated  field containing the group
+          identifier (GID) of the associated group  is  appended.
+          (POSIX  1003.1e  draft standard 17 allows to add fields
+          to ACL entries.)
+
+          This  is  an   example   of   the   format   used   for
+          SCHILY.acl.access  (a space has been inserted after the
+          equal sign and lines are broken [marked with '\' ]  for
+          readability, additional fields in bold):
+
+          SCHILY.acl.access= user::rwx,user:lisa:r-x:502, \
+                             group::r-x,group:toolies:rwx:102, \
+                             mask::rwx,other::r--x
+
+          The numerical user and group identifiers are  essential
+          when  restoring  a  system completely from a backup, as
+          initially the name-to-identifier mappings  may  not  be
+          available,  and  then  file ownership restoration would
+          not work.
+
+          As the archive format  that  is  used  for  backing  up
+          access control lists is compatible with the pax archive
+          format, archives created that way can  be  restored  by
+
+Joerg Schilling       Last change: 05/10/19                    12
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          star  or  a POSIX.1-2001 compliant pax.  Note that pro-
+          grams other than star will ignore the ACL information.
+
+     SCHILY.acl.default
+          The default ACL for a file. See  SCHILY.acl.access  for
+          more information.
+
+          This  is  an   example   of   the   format   used   for
+          SCHILY.acl.default (a space has been inserted after the
+          equal sign and lines are broken [marked with '\' ]  for
+          readability, additional fields in bold):
+
+          SCHILY.acl.default= user::rwx,user:lisa:r-x:502, \
+                              group::r-x,mask::r-x,other::r-x
+
+     SCHILY.ddev
+          The device ids for names used is  the  SCHILY.dir  dump
+          directory  list  from  st_dev  of  the  file as decimal
+          number.  The SCHILY.ddev keyword is followed by a space
+          separated  list  of device id numbers. Each corresponds
+          exactly to a name in the list found in SCHILY.dir.   If
+          a  specific  device  id number is repeated, a comma (,)
+          without a following space may be use to denote that the
+          current  device  id number is identical to the previous
+          number.  This keyword is used in dump mode.  This  key-
+          word is not yet implemented.
+
+          The value is a signed int.  An implementation should be
+          able  to  handle at least 64 bit values.  Note that the
+          value is signed because POSIX  does  not  specify  more
+          than the type should be an int.
+
+     SCHILY.dev
+          The device id  from  st_dev  of  the  file  as  decimal
+          number.  This keyword is used in dump mode.
+
+          The value is a signed int.  An implementation should be
+          able  to  handle at least 64 bit values.  Note that the
+          value is signed because POSIX  does  not  specify  more
+          than the type should be an int.
+
+     SCHILY.devmajor
+          The device major number of the file if it is a  charac-
+          ter  or  block special file.  The argument is a decimal
+          number.  This field is used if the device major of  the
+          file is greater than 2097151 (octal 7777777).
+
+          The value is a signed int.  An implementation should be
+          able  to  handle at least 64 bit values.  Note that the
+          value is signed because POSIX  does  not  specify  more
+          than the type should be an int.
+
+Joerg Schilling       Last change: 05/10/19                    13
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     SCHILY.devminor
+          The device minor number of the file if it is a  charac-
+          ter  or  block special file.  The argument is a decimal
+          number.  This field is used if the device minor of  the
+          file is greater than 2097151 (octal 7777777).
+
+          The value is a signed int.  An implementation should be
+          able  to  handle at least 64 bit values.  Note that the
+          value is signed because POSIX  does  not  specify  more
+          than the type should be an int.
+
+     SCHILY.dino
+          The inode numbers for names used is the SCHILY.dir dump
+          directory  list  from  st_ino  of  the  file as decimal
+          number.  The SCHILY.dino keyword is followed by a space
+          separated  list  of  inode  numbers.  Each  corresponds
+          exactly to a name in  the  list  found  in  SCHILY.dir.
+          This keyword is used in dump mode.
+
+          The values are unsigned int.  An implementation  should
+          be able to handle at least 64 bit unsigned values.
+
+     SCHILY.dir
+          A list of  filenames  (the  content)  for  the  current
+          directory.   The  names  are coded in UTF-8.  Each file
+          name is prefixed by a single character that is used  as
+          a flag.  Each file name is limited by a null character.
+          The null character is  directly  followed  by  he  flag
+          character  for  the  next file name in case the list is
+          not terminated by the  current  file  name.   The  flag
+          character  must not be a null character.  By default, a
+          ^A (octal  001)  is  used.   The  following  flags  are
+          defined:
+
+          \000 This is the list terminator character - the second
+               null byte, see below.
+
+          ^A   The default flag that is used in case the dump dir
+               features have not been active.
+
+          Y    A non  directory  file  that  is  in  the  current
+               (incremental) dump.
+
+          N    A non directory file that is not  in  the  current
+               (incremental) dump.
+
+          D    A directory that is in the  current  (incremental)
+               dump.
+
+          d    A directory that is not in the current  (incremen-
+               tal) dump.
+
+Joerg Schilling       Last change: 05/10/19                    14
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          The list is terminated by two  successive  null  bytes.
+          The first is the null byte for the last file name.  The
+          second null byte is at the position where a flag  char-
+          acter  would be expected, it acts ad a list terminator.
+          The length tag for the SCHILY.dir  data  includes  both
+          null bytes.
+
+          If a dump mode has been selected  that  writes  compact
+          complete  directory information to the beginning of the
+          archive, the flag character  may  contain  values  dif-
+          ferent from ^A.  Star implementations up to star-1.5 do
+          not include this  feature.   Tar  implementations  that
+          like  to read archives that use the SCHILY.dir keyword,
+          shall not rely on values other than \000 (^@)  or  \001
+          (^A).
+
+          This keyword is used in dump mode.
+
+     SCHILY.fflags
+          A textual version of the BSD  or  Linux  extended  file
+          flags.  As this tag has not yet been documented, please
+          look into the  star  source,  file  fflags.c  for  more
+          information.
+
+     SCHILY.filetype
+          A textual version of the real file type  of  the  file.
+          The following names are used:
+
+          unallocated             An unknown file type  that  may
+                                  be  a  result  of  a  unlink(2)
+                                  operation.  This  should  never
+                                  happen.
+
+          regular                 A regular file.
+
+          contiguous              A contiguous file. On operating
+                                  systems  or  file  systems that
+                                  don't support this  file  type,
+                                  it  is  handled  like a regular
+                                  file.
+
+          symlink                 A symbolic  link  to  any  file
+                                  type.
+
+          directory               A directory.
+
+          character special       A character special file.
+
+          block special           A block special file.
+
+          fifo                    A named pipe.
+
+Joerg Schilling       Last change: 05/10/19                    15
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          socket                  A UNIX domain socket.
+
+          mpx character special   A multiplexed character special
+                                  file.
+
+          mpx block special       A  multiplexed  block   special
+                                  file.
+
+          XENIX nsem              A XENIX named semaphore.
+
+          XENIX nshd              XENIX shared data.
+
+          door                    A Solaris door.
+
+          eventcount              A UNOS event count.
+
+          whiteout                A BSD whiteout directory entry.
+
+          sparse                  A sparse regular file.
+
+          volheader               A volume header.
+
+          unknown/bad             Any other  unknown  file  type.
+                                  This should never happen.
+
+     SCHILY.ino
+          The inode number from st_ino of  the  file  as  decimal
+          number.  This keyword is used in dump mode.
+
+          The value is an unsigned int.  An implementation should
+          be able to handle at least 64 bit unsigned values.
+
+     SCHILY.nlink
+          The link count of the file  as  decimal  number.   This
+          keyword is used in dump mode.
+
+          The value is an unsigned int.  An implementation should
+          be able to handle at least 32 bit unsigned values.
+
+     SCHILY.offset
+          The  offset  value  for  a  multi  volume  continuation
+          header.   This  keyword  is used with multi volume con-
+          tinuation headers.  Multi volume  continuation  headers
+          are  used  to  allow  to  start  reading a multi volume
+          archive past the first volume.
+
+          The value is an unsigned int.  An implementation should
+          be able to handle at least 64 bit unsigned values.
+
+     SCHILY.realsize
+          The real size of the  file  as  decimal  number.   This
+
+Joerg Schilling       Last change: 05/10/19                    16
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          keyword  is  used  if the real size of the file differs
+          from the visible size of the file in the archive.   The
+          real  file size differs from the size in the archive if
+          the file type is sparse or if the file is  a  continua-
+          tion  file  on  a  multi  volume  archive.  In case the
+          SCHILY.realsize keyword is needed, it must be past  any
+          size keyword in case a size keyword is also present.
+
+          The value is an unsigned int.  An implementation should
+          be able to handle at least 64 bit unsigned values.
+
+     SCHILY.tarfiletype
+          The  following  additional  file  types  are  used   in
+          SCHILY.tarfiletype:
+
+          hardlink
+               A hard link to any file type.
+
+          dumpdir
+               A directory with dump entries
+
+          multivol continuation
+               A multi volume continuation for any file type.
+
+          meta A meta entry (inode meta data only) for  any  file
+               type.
+
+     SCHILY.xattr.attr
+          A POSIX.1-2001 coded version of the Linux extended file
+          attributes.    Linux   extended   file  attributes  are
+          name/value pairs. Every attribute  name  results  in  a
+          SCHILY.xattr.name  tag  and  the  value of the extended
+          attribute is used as  the  value  of  the  POSIX.1-2001
+          header  tag.  Note that this way of coding is not port-
+          able across  platforms.   A  version  for  BSD  may  be
+          created  but  Solaris  includes  far more features with
+          extended attribute files than Linux does.
+
+          A future version  of  star  will  implement  a  similar
+          method  as  the  tar program on Solaris currently uses.
+          When    this    implementation    is     ready,     the
+          SCHILY.xattr.name  feature may be removed in favor of a
+          truly portable  implementation  that  supports  Solaris
+          also.
+
+
+
+

SCHILY 'G'LOBAL PAX EXTENSION KEYWORDS

+     The following star vendor unique extensions may only  appear
+     in 'g'lobal extended pax headers:
+
+     SCHILY.archtype
+          The textual version of  the  archive  type  used.   The
+
+Joerg Schilling       Last change: 05/10/19                    17
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          textual  values  used  for SCHILY.archtype are the same
+          names that are used in the star command line options to
+          set up a specific archive type.
+
+          In order to allow archive type  recognition  from  this
+          keyword,  the  minimum  tape  block  size must be 2x512
+          bytes (1024  bytes)  and  the  SCHILY.archtype  keyword
+          needs  to  be  in the first 512 bytes of the content of
+          the first 'g'lobal pax  header.  Then  the  first  tape
+          block may be scanned to recognize the archive type.
+
+     SCHILY.release
+          The textual version of the star version string and  the
+          platform  name  where this star has been compiled.  The
+          same text appears when calling star -version.
+
+     SCHILY.volhdr.blockoff
+          This keyword is used for  multi  volume  archives.   It
+          represents   the   offset   within  the  whole  archive
+          expressed in 512 byte units.
+
+          The value is an unsigned int with a valid range between
+          1  and  infinity.  An  implementation should be able to
+          handle at least 64 bit unsigned values.
+
+     SCHILY.volhdr.blocksize
+          The tape blocksize expressed in 512 byte units that was
+          used when writing the archive.
+
+          The value is an unsigned int with a valid range between
+          1  and  infinity.  An  implementation should be able to
+          handle at least 31 bit unsigned values.
+
+     SCHILY.volhdr.cwd
+          This keyword is used in dump mode.  It is only used  to
+          contain  the  real  backup  working  directory  if  the
+          fs-name= option  of  star  is  used  to  overwrite  the
+          SCHILY.volhdr.filesys         value.        Overwriting
+          SCHILY.volhdr.filesys is needed when backups are run on
+          file system snapshots rather than on the real file sys-
+          tem.
+
+     SCHILY.volhdr.device
+          This keyword is used in dump mode.  It  represents  the
+          name of the device that holds the file system data. For
+          disk based file systems, this is the device name of the
+          mounted device.
+
+          This keyword is optional. It helps to  correctly  iden-
+          tify  the  file  system  from  which this dump has been
+          made.
+
+Joerg Schilling       Last change: 05/10/19                    18
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+     SCHILY.volhdr.dumpdate
+          This keyword is used in dump mode.  It  represents  the
+          time the current dump did start.
+
+     SCHILY.volhdr.dumplevel
+          This keyword is used in dump mode.  It  represents  the
+          level  of  the  current  dump.   Dump  levels are small
+          numbers, the lowest possible number is 0.  Dump level 0
+          represents  a  full  backup.  Dump level 1 represents a
+          backup that contains all changes that did  occur  since
+          the  last  level  0  dump.   Dump  level 2 represents a
+          backup that contains all changes that did  occur  since
+          the last level 1 dump.  Star does not specify a maximum
+          allowed dump level but  you  should  try  to  keep  the
+          numbers less than 100.
+
+          The value is an unsigned int with a valid range between
+          0 and at least 100.
+
+     SCHILY.volhdr.dumptype
+          This keyword is used in dump mode.  If the  dump  is  a
+          complete  dump  of  a file system, then the argument is
+          the text full, else the argument is the text partial.
+
+     SCHILY.volhdr.filesys
+          This keyword is used in dump mode.  It  represents  the
+          top level directory for the file system from which this
+          dump has been made.  If the dump represents a dump that
+          has  an associated level, then the this directory needs
+          to be identical to the root directory of this file sys-
+          tem which is the mount point.
+
+     SCHILY.volhdr.hostname
+          This keyword is  used  in  dump  mode.   The  value  is
+          retrieved from gethostname(3) or uname(2).
+
+     SCHILY.volhdr.label
+          The textual volume label.  The  volume  label  must  be
+          identical within a set of multi volume archives.
+
+     SCHILY.volhdr.refdate
+          This keyword is used in dump mode if the  current  dump
+          is an incremental dump with a level > 0.  It represents
+          the time the related dump did start.
+
+     SCHILY.volhdr.reflevel
+          This keyword is used in dump mode if the  current  dump
+          is an incremental dump with a level > 0.  It represents
+          the level of the related dump.  The related dump is the
+          last  dump with a level that is lower that the level of
+          this dump.  If a dump with the  level  of  the  current
+          dump  -1  exists,  then this is the related dump level.
+
+Joerg Schilling       Last change: 05/10/19                    19
+
+
+Schily's USER COMMANDS                                   STAR(4L)
+
+          Otherwise, the dump level is decremented until a  valid
+          dump level could be found in the dump database.
+
+          The value is an unsigned int with a valid range between
+          0 and at least 100.
+
+     SCHILY.volhdr.tapesize
+          This keyword is used for multi volume archives and  may
+          be  used  to  verify  the volume size on read back.  It
+          represents the tape size expressed in 512  byte  units.
+          If  this  keyword is set in multi volume mode, the size
+          of the tape is not autodetected but set from a  command
+          line option.
+
+          The value is an unsigned int with a valid range between
+          1  and  infinity.  An  implementation should be able to
+          handle at least 64 bit unsigned values.
+
+     SCHILY.volhdr.volume
+          This keyword is used for  multi  volume  archives.   It
+          represents  the volume number within a volume set.  The
+          number used for the first volume is 1.
+
+          The value is an unsigned int with a valid range between
+          1  and  infinity.  An  implementation should be able to
+          handle at least 31 bit unsigned values.
+
+
+
+

MULTI VOLUME ARCHIVE HANDLING

+     To be documented in the future.
+
+
+
+

SEE ALSO

+
+
+

NOTES

+
+
+

BUGS

+
+
+

AUTHOR

+
+Joerg Schilling       Last change: 05/10/19                    20
+
+
+
+
+Man(1) output converted with +man2html +
+


+FhG +FhG FOKUS +BerliOS + +Schily +Schily's Home +VED powered + + + diff --git a/node_modules/tar/test/fixtures/packtest/Ω.txt b/node_modules/tar/test/fixtures/packtest/Ω.txt new file mode 100644 index 0000000..1ca042f --- /dev/null +++ b/node_modules/tar/test/fixtures/packtest/Ω.txt @@ -0,0 +1 @@ +Ω \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc b/node_modules/tar/test/fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc new file mode 100644 index 0000000..5a5d18e --- /dev/null +++ b/node_modules/tar/test/fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc @@ -0,0 +1 @@ +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/symlink b/node_modules/tar/test/fixtures/symlink new file mode 120000 index 0000000..218c28e --- /dev/null +++ b/node_modules/tar/test/fixtures/symlink @@ -0,0 +1 @@ +hardlink-1 \ No newline at end of file diff --git a/node_modules/tar/test/fixtures/Ω.txt b/node_modules/tar/test/fixtures/Ω.txt new file mode 100644 index 0000000..1ca042f --- /dev/null +++ b/node_modules/tar/test/fixtures/Ω.txt @@ -0,0 +1 @@ +Ω \ No newline at end of file diff --git a/node_modules/tar/test/header.js b/node_modules/tar/test/header.js new file mode 100644 index 0000000..8ea6f79 --- /dev/null +++ b/node_modules/tar/test/header.js @@ -0,0 +1,183 @@ +var tap = require("tap") +var TarHeader = require("../lib/header.js") +var tar = require("../tar.js") +var fs = require("fs") + + +var headers = + { "a.txt file header": + [ "612e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303430312031313635313336303333332030313234353100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true + , path: 'a.txt' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 257 + , mtime: 1319493851 + , cksum: 5417 + , type: '0' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } + ] + + , "omega pax": // the extended header from omega tar. + [ "5061784865616465722fcea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303137302031313534333731303631312030313530353100207800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true + , path: 'PaxHeader/Ω.txt' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 120 + , mtime: 1301254537 + , cksum: 6697 + , type: 'x' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } ] + + , "omega file header": + [ "cea92e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030322031313534333731303631312030313330373200203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true + , path: 'Ω.txt' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 2 + , mtime: 1301254537 + , cksum: 5690 + , type: '0' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } ] + + , "foo.js file header": + [ "666f6f2e6a730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030342031313534333637303734312030313236313700203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true + , path: 'foo.js' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 4 + , mtime: 1301246433 + , cksum: 5519 + , type: '0' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } + ] + + , "b.txt file header": + [ "622e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030313030302031313635313336303637372030313234363100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true + , path: 'b.txt' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 512 + , mtime: 1319494079 + , cksum: 5425 + , type: '0' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } + ] + + , "deep nested file": + [ "636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363633030303634342000303537373631200030303030323420003030303030303030313434203131363532313531353333203034333331340020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075737461720030306973616163730000000000000000000000000000000000000000000000000000737461666600000000000000000000000000000000000000000000000000000030303030303020003030303030302000722f652f612f6c2f6c2f792f2d2f642f652f652f702f2d2f662f6f2f6c2f642f652f722f2d2f702f612f742f680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + , { cksumValid: true, + path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' + , mode: 420 + , uid: 24561 + , gid: 20 + , size: 100 + , mtime: 1319687003 + , cksum: 18124 + , type: '0' + , linkpath: '' + , ustar: 'ustar\0' + , ustarver: '00' + , uname: 'isaacs' + , gname: 'staff' + , devmaj: 0 + , devmin: 0 + , fill: '' } + ] + } + +tap.test("parsing", function (t) { + Object.keys(headers).forEach(function (name) { + var h = headers[name] + , header = new Buffer(h[0], "hex") + , expect = h[1] + , parsed = new TarHeader(header) + + // console.error(parsed) + t.has(parsed, expect, "parse " + name) + }) + t.end() +}) + +tap.test("encoding", function (t) { + Object.keys(headers).forEach(function (name) { + var h = headers[name] + , expect = new Buffer(h[0], "hex") + , encoded = TarHeader.encode(h[1]) + + // might have slightly different bytes, since the standard + // isn't very strict, but should have the same semantics + // checkSum will be different, but cksumValid will be true + + var th = new TarHeader(encoded) + delete h[1].block + delete h[1].needExtended + delete h[1].cksum + t.has(th, h[1], "fields "+name) + }) + t.end() +}) + +// test these manually. they're a bit rare to find in the wild +tap.test("parseNumeric tests", function (t) { + var parseNumeric = TarHeader.parseNumeric + , numbers = + { "303737373737373700": 2097151 + , "30373737373737373737373700": 8589934591 + , "303030303036343400": 420 + , "800000ffffffffffff": 281474976710655 + , "ffffff000000000001": -281474976710654 + , "ffffff000000000000": -281474976710655 + , "800000000000200000": 2097152 + , "8000000000001544c5": 1393861 + , "ffffffffffff1544c5": -15383354 } + Object.keys(numbers).forEach(function (n) { + var b = new Buffer(n, "hex") + t.equal(parseNumeric(b), numbers[n], n + " === " + numbers[n]) + }) + t.end() +}) diff --git a/node_modules/tar/test/pack.js b/node_modules/tar/test/pack.js new file mode 100644 index 0000000..3fc808d --- /dev/null +++ b/node_modules/tar/test/pack.js @@ -0,0 +1,953 @@ +var tap = require("tap") + , tar = require("../tar.js") + , pkg = require("../package.json") + , Pack = tar.Pack + , fstream = require("fstream") + , Reader = fstream.Reader + , Writer = fstream.Writer + , path = require("path") + , input = path.resolve(__dirname, "fixtures/") + , target = path.resolve(__dirname, "tmp/pack.tar") + , uid = process.getuid ? process.getuid() : 0 + , gid = process.getgid ? process.getgid() : 0 + + , entries = + + // the global header and root fixtures/ dir are going to get + // a different date each time, so omit that bit. + // Also, dev/ino values differ across machines, so that's not + // included. Rather than use + [ [ 'globalExtendedHeader', + { path: 'PaxHeader/', + mode: 438, + uid: 0, + gid: 0, + type: 'g', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' }, + { "NODETAR.author": pkg.author, + "NODETAR.name": pkg.name, + "NODETAR.description": pkg.description, + "NODETAR.version": pkg.version, + "NODETAR.repository.type": pkg.repository.type, + "NODETAR.repository.url": pkg.repository.url, + "NODETAR.main": pkg.main, + "NODETAR.scripts.test": pkg.scripts.test, + "NODETAR.engines.node": pkg.engines.node } ] + + , [ 'entry', + { path: 'fixtures/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'extendedHeader', + { path: 'PaxHeader/fixtures/200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: uid, + gid: gid, + size: 402, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 13492, + type: 'x', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + 'NODETAR.depth': '1', + 'NODETAR.type': 'File', + nlink: 1, + uid: uid, + gid: gid, + size: 200, + 'NODETAR.blksize': '4096', + 'NODETAR.blocks': '8' } ] + + , [ 'entry', + { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: uid, + gid: gid, + size: 200, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 13475, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '', + 'NODETAR.depth': '1', + 'NODETAR.type': 'File', + nlink: 1, + 'NODETAR.blksize': '4096', + 'NODETAR.blocks': '8' } ] + + , [ 'entry', + { path: 'fixtures/a.txt', + mode: 420, + uid: uid, + gid: gid, + size: 257, + mtime: new Date('Mon, 24 Oct 2011 22:04:11 GMT'), + cksum: 5114, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/b.txt', + mode: 420, + uid: uid, + gid: gid, + size: 512, + mtime: new Date('Mon, 24 Oct 2011 22:07:59 GMT'), + cksum: 5122, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/c.txt', + mode: 420, + uid: uid, + gid: gid, + size: 513, + mtime: new Date('Wed, 26 Oct 2011 01:10:58 GMT'), + cksum: 5119, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/cc.txt', + mode: 420, + uid: uid, + gid: gid, + size: 513, + mtime: new Date('Wed, 26 Oct 2011 01:11:02 GMT'), + cksum: 5222, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/foo.js', + mode: 420, + uid: uid, + gid: gid, + size: 4, + mtime: new Date('Fri, 21 Oct 2011 21:19:29 GMT'), + cksum: 5211, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/hardlink-1', + mode: 420, + uid: uid, + gid: gid, + size: 200, + mtime: new Date('Tue, 15 Nov 2011 03:10:09 GMT'), + cksum: 5554, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/hardlink-2', + mode: 420, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Tue, 15 Nov 2011 03:10:09 GMT'), + cksum: 7428, + type: '1', + linkpath: 'fixtures/hardlink-1', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/omega.txt', + mode: 420, + uid: uid, + gid: gid, + size: 2, + mtime: new Date('Fri, 21 Oct 2011 21:19:29 GMT'), + cksum: 5537, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/packtest/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/packtest/omega.txt', + mode: 420, + uid: uid, + gid: gid, + size: 2, + mtime: new Date('Mon, 14 Nov 2011 21:42:24 GMT'), + cksum: 6440, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/packtest/star.4.html', + mode: 420, + uid: uid, + gid: gid, + size: 54081, + mtime: new Date("Sun, 06 May 2007 13:25:06 GMT"), + cksum: 6566, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'extendedHeader', + { path: 'PaxHeader/fixtures/packtest/Ω.txt', + mode: 420, + uid: uid, + gid: gid, + size: 213, + mtime: new Date('Mon, 14 Nov 2011 21:39:39 GMT'), + cksum: 7306, + type: 'x', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: 'fixtures/packtest/Ω.txt', + 'NODETAR.depth': '2', + 'NODETAR.type': 'File', + nlink: 1, + uid: uid, + gid: gid, + size: 2, + 'NODETAR.blksize': '4096', + 'NODETAR.blocks': '8' } ] + + , [ 'entry', + { path: 'fixtures/packtest/Ω.txt', + mode: 420, + uid: uid, + gid: gid, + size: 2, + mtime: new Date('Mon, 14 Nov 2011 21:39:39 GMT'), + cksum: 6297, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '', + 'NODETAR.depth': '2', + 'NODETAR.type': 'File', + nlink: 1, + 'NODETAR.blksize': '4096', + 'NODETAR.blocks': '8' } ] + + , [ 'entry', + { path: 'fixtures/r/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 4789, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 4937, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5081, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5236, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5391, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5559, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5651, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5798, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 5946, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6094, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6253, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6345, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6494, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6652, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6807, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 6954, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7102, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7263, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7355, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7514, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7658, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:42:46 GMT'), + cksum: 7821, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:43:23 GMT'), + cksum: 7967, + type: '5', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: uid, + gid: gid, + size: 100, + mtime: new Date('Thu, 27 Oct 2011 03:43:23 GMT'), + cksum: 17821, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'entry', + { path: 'fixtures/symlink', + mode: 493, + uid: uid, + gid: gid, + size: 0, + mtime: new Date('Tue, 15 Nov 2011 19:57:48 GMT'), + cksum: 6337, + type: '2', + linkpath: 'hardlink-1', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' } ] + + , [ 'extendedHeader', + { path: 'PaxHeader/fixtures/Ω.txt', + mode: 420, + uid: uid, + gid: gid, + size: 204, + mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + cksum: 6399, + type: 'x', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: "fixtures/Ω.txt" + , "NODETAR.depth": "1" + , "NODETAR.type": "File" + , nlink: 1 + , uid: uid + , gid: gid + , size: 2 + , "NODETAR.blksize": "4096" + , "NODETAR.blocks": "8" } ] + + , [ 'entry', + { path: 'fixtures/Ω.txt', + mode: 420, + uid: uid, + gid: gid, + size: 2, + mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + cksum: 5392, + type: '0', + linkpath: '', + ustar: 'ustar\u0000', + ustarver: '00', + uname: '', + gname: '', + devmaj: 0, + devmin: 0, + fill: '', + 'NODETAR.depth': '1', + 'NODETAR.type': 'File', + nlink: 1, + 'NODETAR.blksize': '4096', + 'NODETAR.blocks': '8' } ] + ] + + +// first, make sure that the hardlinks are actually hardlinks, or this +// won't work. Git has a way of replacing them with a copy. +var hard1 = path.resolve(__dirname, "fixtures/hardlink-1") + , hard2 = path.resolve(__dirname, "fixtures/hardlink-2") + , fs = require("fs") + +try { fs.unlinkSync(hard2) } catch (e) {} +fs.linkSync(hard1, hard2) + +tap.test("with global header", { timeout: 10000 }, function (t) { + runTest(t, true) +}) + +tap.test("without global header", { timeout: 10000 }, function (t) { + runTest(t, false) +}) + +function runTest (t, doGH) { + var reader = Reader({ path: input + , filter: function () { + return !this.path.match(/\.(tar|hex)$/) + } + }) + + var pack = Pack(doGH ? pkg : null) + var writer = Writer(target) + + // skip the global header if we're not doing that. + var entry = doGH ? 0 : 1 + + t.ok(reader, "reader ok") + t.ok(pack, "pack ok") + t.ok(writer, "writer ok") + + pack.pipe(writer) + + var parse = tar.Parse() + t.ok(parse, "parser should be ok") + + pack.on("data", function (c) { + // console.error("PACK DATA") + t.equal(c.length, 512, "parser should emit data in 512byte blocks") + parse.write(c) + }) + + pack.on("end", function () { + // console.error("PACK END") + t.pass("parser ends") + parse.end() + }) + + pack.on("error", function (er) { + t.fail("pack error", er) + }) + + parse.on("error", function (er) { + t.fail("parse error", er) + }) + + writer.on("error", function (er) { + t.fail("writer error", er) + }) + + reader.on("error", function (er) { + t.fail("reader error", er) + }) + + parse.on("*", function (ev, e) { + var wanted = entries[entry++] + if (!wanted) { + t.fail("unexpected event: "+ev) + return + } + t.equal(ev, wanted[0], "event type should be "+wanted[0]) + // if (ev !== wanted[0] || e.path !== wanted[1].path) { + // console.error(wanted) + // console.error([ev, e.props]) + // throw "break" + // } + t.has(e.props, wanted[1], "properties "+wanted[1].path) + if (wanted[2]) { + e.on("end", function () { + t.has(e.fields, wanted[2], "should get expected fields") + }) + } + }) + + reader.pipe(pack) + + writer.on("close", function () { + t.equal(entry, entries.length, "should get all expected entries") + t.pass("it finished") + t.end() + }) + +} diff --git a/node_modules/tar/test/parse.js b/node_modules/tar/test/parse.js new file mode 100644 index 0000000..f765a50 --- /dev/null +++ b/node_modules/tar/test/parse.js @@ -0,0 +1,359 @@ +var tap = require("tap") + , tar = require("../tar.js") + , fs = require("fs") + , path = require("path") + , file = path.resolve(__dirname, "fixtures/c.tar") + , index = 0 + + , expect = +[ [ 'entry', + { path: 'c.txt', + mode: 420, + uid: 24561, + gid: 20, + size: 513, + mtime: new Date('Wed, 26 Oct 2011 01:10:58 GMT'), + cksum: 5422, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + undefined ], + [ 'entry', + { path: 'cc.txt', + mode: 420, + uid: 24561, + gid: 20, + size: 513, + mtime: new Date('Wed, 26 Oct 2011 01:11:02 GMT'), + cksum: 5525, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + undefined ], + [ 'entry', + { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 24561, + gid: 20, + size: 100, + mtime: new Date('Thu, 27 Oct 2011 03:43:23 GMT'), + cksum: 18124, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + undefined ], + [ 'entry', + { path: 'Ω.txt', + mode: 420, + uid: 24561, + gid: 20, + size: 2, + mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + cksum: 5695, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + undefined ], + [ 'extendedHeader', + { path: 'PaxHeader/Ω.txt', + mode: 420, + uid: 24561, + gid: 20, + size: 120, + mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + cksum: 6702, + type: 'x', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: 'Ω.txt', + ctime: 1319737909, + atime: 1319739061, + dev: 234881026, + ino: 51693379, + nlink: 1 } ], + [ 'entry', + { path: 'Ω.txt', + mode: 420, + uid: 24561, + gid: 20, + size: 2, + mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + cksum: 5695, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '', + ctime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), + atime: new Date('Thu, 27 Oct 2011 18:11:01 GMT'), + dev: 234881026, + ino: 51693379, + nlink: 1 }, + undefined ], + [ 'extendedHeader', + { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 24561, + gid: 20, + size: 353, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 14488, + type: 'x', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + ctime: 1319686868, + atime: 1319741254, + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 1 } ], + [ 'entry', + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 24561, + gid: 20, + size: 200, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 14570, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '', + ctime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + atime: new Date('Thu, 27 Oct 2011 18:47:34 GMT'), + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 1 }, + undefined ], + [ 'longPath', + { path: '././@LongLink', + mode: 0, + uid: 0, + gid: 0, + size: 201, + mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), + cksum: 4976, + type: 'L', + linkpath: '', + ustar: false }, + '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ], + [ 'entry', + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 1000, + gid: 1000, + size: 201, + mtime: new Date('Thu, 27 Oct 2011 22:21:50 GMT'), + cksum: 14086, + type: '0', + linkpath: '', + ustar: false }, + undefined ], + [ 'longLinkpath', + { path: '././@LongLink', + mode: 0, + uid: 0, + gid: 0, + size: 201, + mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), + cksum: 4975, + type: 'K', + linkpath: '', + ustar: false }, + '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ], + [ 'longPath', + { path: '././@LongLink', + mode: 0, + uid: 0, + gid: 0, + size: 201, + mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), + cksum: 4976, + type: 'L', + linkpath: '', + ustar: false }, + '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' ], + [ 'entry', + { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', + mode: 511, + uid: 1000, + gid: 1000, + size: 0, + mtime: new Date('Fri, 28 Oct 2011 23:05:17 GMT'), + cksum: 21603, + type: '2', + linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + ustar: false }, + undefined ], + [ 'extendedHeader', + { path: 'PaxHeader/200-hard', + mode: 420, + uid: 24561, + gid: 20, + size: 143, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 6533, + type: 'x', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + { ctime: 1320617144, + atime: 1320617232, + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 2 } ], + [ 'entry', + { path: '200-hard', + mode: 420, + uid: 24561, + gid: 20, + size: 200, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 5526, + type: '0', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '', + ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'), + atime: new Date('Sun, 06 Nov 2011 22:07:12 GMT'), + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 2 }, + undefined ], + [ 'extendedHeader', + { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 24561, + gid: 20, + size: 353, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 14488, + type: 'x', + linkpath: '', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '' }, + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + ctime: 1320617144, + atime: 1320617406, + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 2 } ], + [ 'entry', + { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + mode: 420, + uid: 24561, + gid: 20, + size: 0, + mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), + cksum: 15173, + type: '1', + linkpath: '200-hard', + ustar: 'ustar\0', + ustarver: '00', + uname: 'isaacs', + gname: 'staff', + devmaj: 0, + devmin: 0, + fill: '', + ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'), + atime: new Date('Sun, 06 Nov 2011 22:10:06 GMT'), + 'LIBARCHIVE.creationtime': '1319686852', + dev: 234881026, + ino: 51681874, + nlink: 2 }, + undefined ] ] + + +tap.test("parser test", function (t) { + var parser = tar.Parse() + + parser.on("end", function () { + t.equal(index, expect.length, "saw all expected events") + t.end() + }) + + fs.createReadStream(file) + .pipe(parser) + .on("*", function (ev, entry) { + var wanted = expect[index] + if (!wanted) { + return t.fail("Unexpected event: " + ev) + } + var result = [ev, entry.props] + entry.on("end", function () { + result.push(entry.fields || entry.body) + + t.equal(ev, wanted[0], index + " event type") + t.equivalent(entry.props, wanted[1], wanted[1].path + " entry properties") + if (wanted[2]) { + t.equivalent(result[2], wanted[2], "metadata values") + } + index ++ + }) + }) +}) diff --git a/node_modules/vine b/node_modules/vine new file mode 120000 index 0000000..5c1d60b --- /dev/null +++ b/node_modules/vine @@ -0,0 +1 @@ +/usr/local/lib/node_modules/vine \ No newline at end of file diff --git a/package.json b/package.json index 9f3e573..c30a8b4 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,12 @@ "main": "./lib/index.js", "dependencies": { "optimist":"*", - "sardines":"*" + "sardines":"*", + "mkdirp":"*", + "celeri":"*" + }, + "bin": { + "nexe":"./bin/nexe" }, "devDependencies": {} }