Skip to content
Browse files

init

  • Loading branch information...
0 parents commit 899a4749c07565ce77fa701bc2e6dd98a7cf7e37 @ddollar committed May 25, 2012
Showing with 12,819 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +1 −0 Procfile
  3. +25 −0 README.md
  4. +42 −0 bin/compile
  5. +10 −0 bin/web
  6. +92 −0 lib/manifest.coffee
  7. +10 −0 lib/on.coffee
  8. +61 −0 lib/spawner.coffee
  9. +1 −0 node_modules/.bin/cake
  10. +1 −0 node_modules/.bin/coffee
  11. +1 −0 node_modules/.bin/express
  12. +1 −0 node_modules/.bin/nodemon
  13. +1 −0 node_modules/.bin/stylus
  14. +9 −0 node_modules/async/.gitmodules
  15. +4 −0 node_modules/async/.npmignore
  16. +19 −0 node_modules/async/LICENSE
  17. +25 −0 node_modules/async/Makefile
  18. +1,022 −0 node_modules/async/README.md
  19. +3 −0 node_modules/async/index.js
  20. +692 −0 node_modules/async/lib/async.js
  21. +42 −0 node_modules/async/package.json
  22. +11 −0 node_modules/coffee-script/.npmignore
  23. +22 −0 node_modules/coffee-script/LICENSE
  24. +51 −0 node_modules/coffee-script/README
  25. +78 −0 node_modules/coffee-script/Rakefile
  26. +7 −0 node_modules/coffee-script/bin/cake
  27. +7 −0 node_modules/coffee-script/bin/coffee
  28. +44 −0 node_modules/coffee-script/extras/jsl.conf
  29. +74 −0 node_modules/coffee-script/lib/coffee-script/browser.js
  30. +99 −0 node_modules/coffee-script/lib/coffee-script/cake.js
  31. +150 −0 node_modules/coffee-script/lib/coffee-script/coffee-script.js
  32. +442 −0 node_modules/coffee-script/lib/coffee-script/command.js
  33. +592 −0 node_modules/coffee-script/lib/coffee-script/grammar.js
  34. +72 −0 node_modules/coffee-script/lib/coffee-script/helpers.js
  35. +10 −0 node_modules/coffee-script/lib/coffee-script/index.js
  36. +686 −0 node_modules/coffee-script/lib/coffee-script/lexer.js
  37. +2,514 −0 node_modules/coffee-script/lib/coffee-script/nodes.js
  38. +122 −0 node_modules/coffee-script/lib/coffee-script/optparse.js
  39. +674 −0 node_modules/coffee-script/lib/coffee-script/parser.js
  40. +149 −0 node_modules/coffee-script/lib/coffee-script/repl.js
  41. +301 −0 node_modules/coffee-script/lib/coffee-script/rewriter.js
  42. +124 −0 node_modules/coffee-script/lib/coffee-script/scope.js
  43. +52 −0 node_modules/coffee-script/package.json
  44. +7 −0 node_modules/express/.npmignore
  45. +811 −0 node_modules/express/History.md
  46. +22 −0 node_modules/express/LICENSE
  47. +29 −0 node_modules/express/Makefile
  48. +145 −0 node_modules/express/Readme.md
  49. +417 −0 node_modules/express/bin/express
  50. +2 −0 node_modules/express/index.js
  51. +510 −0 node_modules/express/lib-cov/application.js
  52. +65 −0 node_modules/express/lib-cov/express.js
  53. +54 −0 node_modules/express/lib-cov/middleware.js
  54. +225 −0 node_modules/express/lib-cov/request.js
  55. +611 −0 node_modules/express/lib-cov/response.js
  56. +40 −0 node_modules/express/lib-cov/router/collection.js
  57. +515 −0 node_modules/express/lib-cov/router/index.js
  58. +9 −0 node_modules/express/lib-cov/router/methods.js
  59. +68 −0 node_modules/express/lib-cov/router/route.js
  60. +151 −0 node_modules/express/lib-cov/utils.js
  61. +81 −0 node_modules/express/lib-cov/view.js
  62. +79 −0 node_modules/express/lib/express.js
  63. +582 −0 node_modules/express/lib/http.js
  64. +52 −0 node_modules/express/lib/https.js
Sorry, we could not display the entire diff because too many files (502) changed.
1 .gitignore
@@ -0,0 +1 @@
+.env
1 Procfile
@@ -0,0 +1 @@
+web: bin/web
25 README.md
@@ -0,0 +1,25 @@
+# anvil
+
+Alternate Heroku push/deploy workflow.
+
+## Installation
+
+ $ heroku plugins:install https://github.com/ddollar/heroku-anvil
+
+## Usage
+
+#### Push your app
+
+ $ heroku push
+ Generating application manifest... done
+ Computing diff for upload... done
+ Uploading new files... done
+ Compiling...
+ Launching build slave
+ Buildpack: Buildkit+Node.js
+ -----> Compiling for Node.js
+ -----> Resolving engine versions
+ Using Node.js version: 0.6.12
+ Using npm version: 1.1.4
+ -----> Fetching Node.js binaries
+ ...
42 bin/compile
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+id=$1
+buildpack=$2
+
+# create a temporary compile directory
+compile_dir=$(mktemp -t compile_XXXXX)
+rm -rf $compile_dir
+mkdir -p $compile_dir
+
+# create a cache dir
+cache_dir=$(mktemp -t cache_XXXXX)
+rm -rf $cache_dir
+mkdir -p $cache_dir
+
+# fetching app
+cd $compile_dir
+curl -s $ANVIL_HOST/manifest/$id.tgz -o app.tgz
+tar xzf app.tgz
+rm app.tgz
+
+# fetch buildpack
+rm -rf .buildpack
+mkdir -p .buildpack
+cd .buildpack
+curl -s $buildpack -o- | tar xzf -
+cd ..
+
+# get buildpack name
+buildpack_name=$(.buildpack/bin/detect "$compile_dir")
+
+# abort if detect failes
+if [ $? -eq 0 ]; then
+ echo "Buildpack: ${buildpack_name}"
+else
+ echo "compile failed"
+ exit 1
+fi
+
+# compile
+cd $compile_dir
+.buildpack/bin/compile $compile_dir $cache_dir
10 bin/web
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+ROOT=$(dirname $(dirname $0))
+PATH="node_modules/.bin:$PATH"
+
+if [ "${NODE_ENV}" == "production" ]; then
+ exec coffee web.coffee
+else
+ exec nodemon -w . web.coffee
+fi
92 lib/manifest.coffee
@@ -0,0 +1,92 @@
+async = require("async")
+fs = require("fs")
+knox = require("knox")
+mkdirp = require("mkdirp")
+path = require("path")
+spawn = require("child_process").spawn
+spawner = require("spawner").init()
+temp = require("temp")
+uuid = require("node-uuid")
+
+class Manifest
+
+ constructor: (@manifest) ->
+ @knox = knox.createClient
+ key: process.env.AWS_ACCESS,
+ secret: process.env.AWS_SECRET,
+ bucket: process.env.AWS_BUCKET
+
+ build: (cb) ->
+ id = uuid.v1()
+ buffer = new Buffer(JSON.stringify(@manifest), "binary")
+
+ buildpack = "https://buildkit.herokuapp.com/buildkit/example.tgz"
+
+ put = @knox.put "/manifest/#{id}", { "Content-Length":buffer.length, "Content-Type":"text/plain" }
+ put.on "response", (res) -> cb(spawner.spawn("bin/compile \"#{id}\" \"#{buildpack}\""))
+ put.end(buffer)
+
+ create_hash: (hash, stream, cb) ->
+ @knox.putStream stream, "/hash/#{hash}", (err, knox_res) ->
+ cb null
+
+ generate_tarball: (cb) ->
+ temp.mkdir "compile", (err, path) =>
+ async.parallel @datastore_fetchers(path), (err, results) ->
+ cb spawn("tar", ["czf", "-", "."], cwd:path)
+
+ missing_hashes: (cb) ->
+ async.parallel @datastore_testers(), (err, results) ->
+ missing = []
+ for hash, exists of results
+ missing.push(hash) unless exists
+ cb missing
+
+ test_datastore_presence: (hash, cb) ->
+ @knox.headFile "/hash/#{hash}", (err, res) ->
+ cb(res.statusCode != 404)
+
+ datastore_fetchers: (dir) ->
+ fetchers = {}
+ for name, file_manifest of @manifest
+ do (name, file_manifest) =>
+ fetchers[file_manifest.hash] = (async_cb) =>
+ filename = "#{dir}/#{name}"
+ mkdirp path.dirname(filename), =>
+ fs.open filename, "w", (err, fd) =>
+ @knox.getFile "/hash/#{file_manifest["hash"]}", (err, get) =>
+ console.log "writing:#{filename}"
+ get.setEncoding "binary"
+ get.on "data", (chunk) -> fs.write fd, chunk
+ get.on "end", ->
+ fs.fchmod fd, file_manifest.mode
+ fs.close fd
+ async_cb null, true
+
+ datastore_testers: ->
+ @hashes(@manifest).reduce (ax, hash) =>
+ ax[hash] = (async_cb) =>
+ @test_datastore_presence hash, (exists) ->
+ async_cb(null, exists)
+ ax
+ ,{}
+
+ hashes: (manifest) ->
+ object.hash for name, object of manifest
+
+module.exports.init = (manifest) ->
+ new Manifest(manifest)
+
+module.exports.init_with_id = (id, cb) ->
+ manifest = ""
+
+ subknox = knox.createClient
+ key: process.env.AWS_ACCESS,
+ secret: process.env.AWS_SECRET,
+ bucket: process.env.AWS_BUCKET
+
+ subknox.getFile "/manifest/#{id}", (err, get) =>
+ get.setEncoding "binary"
+ get.on "data", (chunk) -> manifest += chunk
+ get.on "end", (success) ->
+ cb(new Manifest(JSON.parse(manifest)))
10 lib/on.coffee
@@ -0,0 +1,10 @@
+events = require("events")
+
+module.exports.inject = (object) ->
+ object.emitter = events.EventEmitter()
+
+ object.on = (key, handler) ->
+ object.emitter.on key, handler
+
+ object.emit = ->
+ object.emitter.emit arguments
61 lib/spawner.coffee
@@ -0,0 +1,61 @@
+events = require("events")
+https = require("https")
+net = require("net")
+qs = require("querystring")
+restler = require("restler")
+spawn = require("child_process").spawn
+tls = require("tls")
+
+class Spawner
+
+ constructor: (env) ->
+ @env = env or process.env.SPAWN_ENV or "local"
+
+ spawn: (command, options, cb) ->
+ spawner = this["spawn_#{@env}"]
+ spawner command, options, cb
+
+ spawn_local: (command, options, cb) ->
+ args = command.match(/("[^"]*"|[^"]+)(\s+|$)/g)
+ command = args.shift().replace(/\s+$/g, "")
+ args = args.map (arg) -> arg.match(/"?([^"]*)"?/)[1]
+ proc = spawn command, args, env:process.env
+ emitter = new events.EventEmitter()
+
+ proc.stdout.on "data", (data) -> emitter.emit("data", data)
+ proc.stderr.on "data", (data) -> emitter.emit("data", data)
+ proc.on "exit", (code) -> emitter.emit("end", code)
+ emitter
+
+ spawn_heroku: (command, cb) ->
+ api_key = process.env.HEROKU_API_KEY
+ app = process.env.HEROKU_APP
+ emitter = new events.EventEmitter()
+
+ request = restler.post "https://api.heroku.com/apps/#{app}/ps",
+ headers:
+ "Authorization": new Buffer(":" + api_key).toString("base64")
+ "Accept": "application/json"
+ "User-Agent": "heroku-gem/2.5"
+ data:
+ attach: true
+ command: command
+
+ request.on "success", (data) ->
+ url = require("url").parse(data.rendezvous_url)
+ rendezvous = tls.connect url.port, url.hostname, ->
+ if rendezvous.authorized
+ console.log "valid socket"
+ rendezvous.write url.pathname.substring(1) + "\n"
+ else
+ console.log "invalid socket"
+ rendezvous.on "data", (data) -> console.log "data", data; emitter.emit("data", data) unless data.toString() is "rendezvous\r\n"
+ rendezvous.on "end", -> emitter.emit "end"
+
+ request.on "error", (error) ->
+ emitter.emit "error", error
+
+ emitter
+
+module.exports.init = (env) ->
+ new Spawner(env)
1 node_modules/.bin/cake
1 node_modules/.bin/coffee
1 node_modules/.bin/express
1 node_modules/.bin/nodemon
1 node_modules/.bin/stylus
9 node_modules/async/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "deps/nodeunit"]
+ path = deps/nodeunit
+ url = git://github.com/caolan/nodeunit.git
+[submodule "deps/UglifyJS"]
+ path = deps/UglifyJS
+ url = https://github.com/mishoo/UglifyJS.git
+[submodule "deps/nodelint"]
+ path = deps/nodelint
+ url = https://github.com/tav/nodelint.git
4 node_modules/async/.npmignore
@@ -0,0 +1,4 @@
+deps
+dist
+test
+nodelint.cfg
19 node_modules/async/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Caolan McMahon
+
+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.
25 node_modules/async/Makefile
@@ -0,0 +1,25 @@
+PACKAGE = asyncjs
+NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node)
+CWD := $(shell pwd)
+NODEUNIT = $(CWD)/node_modules/nodeunit/bin/nodeunit
+UGLIFY = $(CWD)/node_modules/uglify-js/bin/uglifyjs
+NODELINT = $(CWD)/node_modules/nodelint/nodelint
+
+BUILDDIR = dist
+
+all: clean test build
+
+build: $(wildcard lib/*.js)
+ mkdir -p $(BUILDDIR)
+ $(UGLIFY) lib/async.js > $(BUILDDIR)/async.min.js
+
+test:
+ $(NODEUNIT) test
+
+clean:
+ rm -rf $(BUILDDIR)
+
+lint:
+ $(NODELINT) --config nodelint.cfg lib/async.js
+
+.PHONY: test build all
1,022 node_modules/async/README.md
@@ -0,0 +1,1022 @@
+# Async.js
+
+Async is a utility module which provides straight-forward, powerful functions
+for working with asynchronous JavaScript. Although originally designed for
+use with [node.js](http://nodejs.org), it can also be used directly in the
+browser.
+
+Async provides around 20 functions that include the usual 'functional'
+suspects (map, reduce, filter, forEach…) as well as some common patterns
+for asynchronous control flow (parallel, series, waterfall…). All these
+functions assume you follow the node.js convention of providing a single
+callback as the last argument of your async function.
+
+
+## Quick Examples
+
+ async.map(['file1','file2','file3'], fs.stat, function(err, results){
+ // results is now an array of stats for each file
+ });
+
+ async.filter(['file1','file2','file3'], path.exists, function(results){
+ // results now equals an array of the existing files
+ });
+
+ async.parallel([
+ function(){ ... },
+ function(){ ... }
+ ], callback);
+
+ async.series([
+ function(){ ... },
+ function(){ ... }
+ ]);
+
+There are many more functions available so take a look at the docs below for a
+full list. This module aims to be comprehensive, so if you feel anything is
+missing please create a GitHub issue for it.
+
+
+## Download
+
+Releases are available for download from
+[GitHub](http://github.com/caolan/async/downloads).
+Alternatively, you can install using Node Package Manager (npm):
+
+ npm install async
+
+
+__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed
+
+__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped
+
+
+## In the Browser
+
+So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
+
+ <script type="text/javascript" src="async.js"></script>
+ <script type="text/javascript">
+
+ async.map(data, asyncProcess, function(err, results){
+ alert(results);
+ });
+
+ </script>
+
+
+## Documentation
+
+### Collections
+
+* [forEach](#forEach)
+* [map](#map)
+* [filter](#filter)
+* [reject](#reject)
+* [reduce](#reduce)
+* [detect](#detect)
+* [sortBy](#sortBy)
+* [some](#some)
+* [every](#every)
+* [concat](#concat)
+
+### Control Flow
+
+* [series](#series)
+* [parallel](#parallel)
+* [whilst](#whilst)
+* [until](#until)
+* [waterfall](#waterfall)
+* [queue](#queue)
+* [auto](#auto)
+* [iterator](#iterator)
+* [apply](#apply)
+* [nextTick](#nextTick)
+
+### Utils
+
+* [memoize](#memoize)
+* [unmemoize](#unmemoize)
+* [log](#log)
+* [dir](#dir)
+* [noConflict](#noConflict)
+
+
+## Collections
+
+<a name="forEach" />
+### forEach(arr, iterator, callback)
+
+Applies an iterator function to each item in an array, in parallel.
+The iterator is called with an item from the list and a callback for when it
+has finished. If the iterator passes an error to this callback, the main
+callback for the forEach function is immediately called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(err) - A callback which is called after all the iterator functions
+ have finished, or an error has occurred.
+
+__Example__
+
+ // assuming openFiles is an array of file names and saveFile is a function
+ // to save the modified contents of that file:
+
+ async.forEach(openFiles, saveFile, function(err){
+ // if any of the saves produced an error, err would equal that error
+ });
+
+---------------------------------------
+
+<a name="forEachSeries" />
+### forEachSeries(arr, iterator, callback)
+
+The same as forEach only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. This means the iterator functions will complete in order.
+
+
+---------------------------------------
+
+<a name="forEachLimit" />
+### forEachLimit(arr, limit, iterator, callback)
+
+The same as forEach only the iterator is applied to batches of items in the
+array, in series. The next batch of iterators is only called once the current
+one has completed processing.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - How many items should be in each batch.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(err) - A callback which is called after all the iterator functions
+ have finished, or an error has occurred.
+
+__Example__
+
+ // Assume documents is an array of JSON objects and requestApi is a
+ // function that interacts with a rate-limited REST api.
+
+ async.forEachLimit(documents, 20, requestApi, function(err){
+ // if any of the saves produced an error, err would equal that error
+ });
+---------------------------------------
+
+<a name="map" />
+### map(arr, iterator, callback)
+
+Produces a new array of values by mapping each value in the given array through
+the iterator function. The iterator is called with an item from the array and a
+callback for when it has finished processing. The callback takes 2 arguments,
+an error and the transformed item from the array. If the iterator passes an
+error to this callback, the main callback for the map function is immediately
+called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order, however
+the results array will be in the same order as the original array.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is an array of the
+ transformed items from the original array.
+
+__Example__
+
+ async.map(['file1','file2','file3'], fs.stat, function(err, results){
+ // results is now an array of stats for each file
+ });
+
+---------------------------------------
+
+<a name="mapSeries" />
+### mapSeries(arr, iterator, callback)
+
+The same as map only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+---------------------------------------
+
+<a name="filter" />
+### filter(arr, iterator, callback)
+
+__Alias:__ select
+
+Returns a new array of all the values which pass an async truth test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists. This operation is
+performed in parallel, but the results array will be in the same order as the
+original.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(results) - A callback which is called after all the iterator
+ functions have finished.
+
+__Example__
+
+ async.filter(['file1','file2','file3'], path.exists, function(results){
+ // results now equals an array of the existing files
+ });
+
+---------------------------------------
+
+<a name="filterSeries" />
+### filterSeries(arr, iterator, callback)
+
+__alias:__ selectSeries
+
+The same as filter only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+---------------------------------------
+
+<a name="reject" />
+### reject(arr, iterator, callback)
+
+The opposite of filter. Removes values that pass an async truth test.
+
+---------------------------------------
+
+<a name="rejectSeries" />
+### rejectSeries(arr, iterator, callback)
+
+The same as filter, only the iterator is applied to each item in the array
+in series.
+
+
+---------------------------------------
+
+<a name="reduce" />
+### reduce(arr, memo, iterator, callback)
+
+__aliases:__ inject, foldl
+
+Reduces a list of values into a single value using an async iterator to return
+each successive step. Memo is the initial state of the reduction. This
+function only operates in series. For performance reasons, it may make sense to
+split a call to this function into a parallel map, then use the normal
+Array.prototype.reduce on the results. This function is for situations where
+each step in the reduction needs to be async, if you can get the data before
+reducing it then its probably a good idea to do so.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* memo - The initial state of the reduction.
+* iterator(memo, item, callback) - A function applied to each item in the
+ array to produce the next step in the reduction. The iterator is passed a
+ callback which accepts an optional error as its first argument, and the state
+ of the reduction as the second. If an error is passed to the callback, the
+ reduction is stopped and the main callback is immediately called with the
+ error.
+* callback(err, result) - A callback which is called after all the iterator
+ functions have finished. Result is the reduced value.
+
+__Example__
+
+ async.reduce([1,2,3], 0, function(memo, item, callback){
+ // pointless async:
+ process.nextTick(function(){
+ callback(null, memo + item)
+ });
+ }, function(err, result){
+ // result is now equal to the last value of memo, which is 6
+ });
+
+---------------------------------------
+
+<a name="reduceRight" />
+### reduceRight(arr, memo, iterator, callback)
+
+__Alias:__ foldr
+
+Same as reduce, only operates on the items in the array in reverse order.
+
+
+---------------------------------------
+
+<a name="detect" />
+### detect(arr, iterator, callback)
+
+Returns the first value in a list that passes an async truth test. The
+iterator is applied in parallel, meaning the first iterator to return true will
+fire the detect callback with that result. That means the result might not be
+the first item in the original array (in terms of order) that passes the test.
+
+If order within the original array is important then look at detectSeries.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+ true, or after all the iterator functions have finished. Result will be
+ the first item in the array that passes the truth test (iterator) or the
+ value undefined if none passed.
+
+__Example__
+
+ async.detect(['file1','file2','file3'], path.exists, function(result){
+ // result now equals the first file in the list that exists
+ });
+
+---------------------------------------
+
+<a name="detectSeries" />
+### detectSeries(arr, iterator, callback)
+
+The same as detect, only the iterator is applied to each item in the array
+in series. This means the result is always the first in the original array (in
+terms of array order) that passes the truth test.
+
+
+---------------------------------------
+
+<a name="sortBy" />
+### sortBy(arr, iterator, callback)
+
+Sorts a list by the results of running each value through an async iterator.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and a value to use as the sort criteria.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is the items from
+ the original array sorted by the values returned by the iterator calls.
+
+__Example__
+
+ async.sortBy(['file1','file2','file3'], function(file, callback){
+ fs.stat(file, function(err, stats){
+ callback(err, stats.mtime);
+ });
+ }, function(err, results){
+ // results is now the original array of files sorted by
+ // modified date
+ });
+
+
+---------------------------------------
+
+<a name="some" />
+### some(arr, iterator, callback)
+
+__Alias:__ any
+
+Returns true if at least one element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists. Once any iterator
+call returns true, the main callback is immediately called.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+ true, or after all the iterator functions have finished. Result will be
+ either true or false depending on the values of the async tests.
+
+__Example__
+
+ async.some(['file1','file2','file3'], path.exists, function(result){
+ // if result is true then at least one of the files exists
+ });
+
+---------------------------------------
+
+<a name="every" />
+### every(arr, iterator, callback)
+
+__Alias:__ all
+
+Returns true if every element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called after all the iterator
+ functions have finished. Result will be either true or false depending on
+ the values of the async tests.
+
+__Example__
+
+ async.every(['file1','file2','file3'], path.exists, function(result){
+ // if result is true then every file exists
+ });
+
+---------------------------------------
+
+<a name="concat" />
+### concat(arr, iterator, callback)
+
+Applies an iterator to each item in a list, concatenating the results. Returns the
+concatenated list. The iterators are called in parallel, and the results are
+concatenated as they return. There is no guarantee that the results array will
+be returned in the original order of the arguments passed to the iterator function.
+
+__Arguments__
+
+* arr - An array to iterate over
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and an array of results.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is an array containing
+ the concatenated results of the iterator function.
+
+__Example__
+
+ async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
+ // files is now a list of filenames that exist in the 3 directories
+ });
+
+---------------------------------------
+
+<a name="concatSeries" />
+### concatSeries(arr, iterator, callback)
+
+Same as async.concat, but executes in series instead of parallel.
+
+
+## Control Flow
+
+<a name="series" />
+### series(tasks, [callback])
+
+Run an array of functions in series, each one running once the previous
+function has completed. If any functions in the series pass an error to its
+callback, no more functions are run and the callback for the series is
+immediately called with the value of the error. Once the tasks have completed,
+the results are passed to the final callback as an array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.series.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed
+ a callback it must call on completion.
+* callback(err, results) - An optional callback to run once all the functions
+ have completed. This function gets an array of all the arguments passed to
+ the callbacks used in the array.
+
+__Example__
+
+ async.series([
+ function(callback){
+ // do some stuff ...
+ callback(null, 'one');
+ },
+ function(callback){
+ // do some more stuff ...
+ callback(null, 'two');
+ },
+ ],
+ // optional callback
+ function(err, results){
+ // results is now equal to ['one', 'two']
+ });
+
+
+ // an example using an object instead of an array
+ async.series({
+ one: function(callback){
+ setTimeout(function(){
+ callback(null, 1);
+ }, 200);
+ },
+ two: function(callback){
+ setTimeout(function(){
+ callback(null, 2);
+ }, 100);
+ },
+ },
+ function(err, results) {
+ // results is now equal to: {one: 1, two: 2}
+ });
+
+
+---------------------------------------
+
+<a name="parallel" />
+### parallel(tasks, [callback])
+
+Run an array of functions in parallel, without waiting until the previous
+function has completed. If any of the functions pass an error to its
+callback, the main callback is immediately called with the value of the error.
+Once the tasks have completed, the results are passed to the final callback as an
+array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.parallel.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed a
+ callback it must call on completion.
+* callback(err, results) - An optional callback to run once all the functions
+ have completed. This function gets an array of all the arguments passed to
+ the callbacks used in the array.
+
+__Example__
+
+ async.parallel([
+ function(callback){
+ setTimeout(function(){
+ callback(null, 'one');
+ }, 200);
+ },
+ function(callback){
+ setTimeout(function(){
+ callback(null, 'two');
+ }, 100);
+ },
+ ],
+ // optional callback
+ function(err, results){
+ // in this case, the results array will equal ['two','one']
+ // because the functions were run in parallel and the second
+ // function had a shorter timeout before calling the callback.
+ });
+
+
+ // an example using an object instead of an array
+ async.parallel({
+ one: function(callback){
+ setTimeout(function(){
+ callback(null, 1);
+ }, 200);
+ },
+ two: function(callback){
+ setTimeout(function(){
+ callback(null, 2);
+ }, 100);
+ },
+ },
+ function(err, results) {
+ // results is now equals to: {one: 1, two: 2}
+ });
+
+
+---------------------------------------
+
+<a name="whilst" />
+### whilst(test, fn, callback)
+
+Repeatedly call fn, while test returns true. Calls the callback when stopped,
+or an error occurs.
+
+__Arguments__
+
+* test() - synchronous truth test to perform before each execution of fn.
+* fn(callback) - A function to call each time the test passes. The function is
+ passed a callback which must be called once it has completed with an optional
+ error as the first argument.
+* callback(err) - A callback which is called after the test fails and repeated
+ execution of fn has stopped.
+
+__Example__
+
+ var count = 0;
+
+ async.whilst(
+ function () { return count < 5; },
+ function (callback) {
+ count++;
+ setTimeout(callback, 1000);
+ },
+ function (err) {
+ // 5 seconds have passed
+ }
+ );
+
+
+---------------------------------------
+
+<a name="until" />
+### until(test, fn, callback)
+
+Repeatedly call fn, until test returns true. Calls the callback when stopped,
+or an error occurs.
+
+The inverse of async.whilst.
+
+
+---------------------------------------
+
+<a name="waterfall" />
+### waterfall(tasks, [callback])
+
+Runs an array of functions in series, each passing their results to the next in
+the array. However, if any of the functions pass an error to the callback, the
+next function is not executed and the main callback is immediately called with
+the error.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a callback it
+ must call on completion.
+* callback(err, [results]) - An optional callback to run once all the functions
+ have completed. This will be passed the results of the last task's callback.
+
+
+
+__Example__
+
+ async.waterfall([
+ function(callback){
+ callback(null, 'one', 'two');
+ },
+ function(arg1, arg2, callback){
+ callback(null, 'three');
+ },
+ function(arg1, callback){
+ // arg1 now equals 'three'
+ callback(null, 'done');
+ }
+ ], function (err, result) {
+ // result now equals 'done'
+ });
+
+
+---------------------------------------
+
+<a name="queue" />
+### queue(worker, concurrency)
+
+Creates a queue object with the specified concurrency. Tasks added to the
+queue will be processed in parallel (up to the concurrency limit). If all
+workers are in progress, the task is queued until one is available. Once
+a worker has completed a task, the task's callback is called.
+
+__Arguments__
+
+* worker(task, callback) - An asynchronous function for processing a queued
+ task.
+* concurrency - An integer for determining how many worker functions should be
+ run in parallel.
+
+__Queue objects__
+
+The queue object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* concurrency - an integer for determining how many worker functions should be
+ run in parallel. This property can be changed after a queue is created to
+ alter the concurrency on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+ once the worker has finished processing the task.
+ instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+ // create a queue object with concurrency 2
+
+ var q = async.queue(function (task, callback) {
+ console.log('hello ' + task.name);
+ callback();
+ }, 2);
+
+
+ // assign a callback
+ q.drain = function() {
+ console.log('all items have been processed');
+ }
+
+ // add some items to the queue
+
+ q.push({name: 'foo'}, function (err) {
+ console.log('finished processing foo');
+ });
+ q.push({name: 'bar'}, function (err) {
+ console.log('finished processing bar');
+ });
+
+ // add some items to the queue (batch-wise)
+
+ q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
+ console.log('finished processing bar');
+ });
+
+
+---------------------------------------
+
+<a name="auto" />
+### auto(tasks, [callback])
+
+Determines the best order for running functions based on their requirements.
+Each function can optionally depend on other functions being completed first,
+and each function is run as soon as its requirements are satisfied. If any of
+the functions pass an error to their callback, that function will not complete
+(so any other functions depending on it will not run) and the main callback
+will be called immediately with the error. Functions also receive an object
+containing the results of functions which have completed so far.
+
+__Arguments__
+
+* tasks - An object literal containing named functions or an array of
+ requirements, with the function itself the last item in the array. The key
+ used for each function or array is used when specifying requirements. The
+ syntax is easier to understand by looking at the example.
+* callback(err, results) - An optional callback which is called when all the
+ tasks have been completed. The callback will receive an error as an argument
+ if any tasks pass an error to their callback. If all tasks complete
+ successfully, it will receive an object containing their results.
+
+__Example__
+
+ async.auto({
+ get_data: function(callback){
+ // async code to get some data
+ },
+ make_folder: function(callback){
+ // async code to create a directory to store a file in
+ // this is run at the same time as getting the data
+ },
+ write_file: ['get_data', 'make_folder', function(callback){
+ // once there is some data and the directory exists,
+ // write the data to a file in the directory
+ callback(null, filename);
+ }],
+ email_link: ['write_file', function(callback, results){
+ // once the file is written let's email a link to it...
+ // results.write_file contains the filename returned by write_file.
+ }]
+ });
+
+This is a fairly trivial example, but to do this using the basic parallel and
+series functions would look like this:
+
+ async.parallel([
+ function(callback){
+ // async code to get some data
+ },
+ function(callback){
+ // async code to create a directory to store a file in
+ // this is run at the same time as getting the data
+ }
+ ],
+ function(results){
+ async.series([
+ function(callback){
+ // once there is some data and the directory exists,
+ // write the data to a file in the directory
+ },
+ email_link: function(callback){
+ // once the file is written let's email a link to it...
+ }
+ ]);
+ });
+
+For a complicated series of async tasks using the auto function makes adding
+new tasks much easier and makes the code more readable.
+
+
+---------------------------------------
+
+<a name="iterator" />
+### iterator(tasks)
+
+Creates an iterator function which calls the next function in the array,
+returning a continuation to call the next one after that. Its also possible to
+'peek' the next iterator by doing iterator.next().
+
+This function is used internally by the async module but can be useful when
+you want to manually control the flow of functions in series.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a callback it
+ must call on completion.
+
+__Example__
+
+ var iterator = async.iterator([
+ function(){ sys.p('one'); },
+ function(){ sys.p('two'); },
+ function(){ sys.p('three'); }
+ ]);
+
+ node> var iterator2 = iterator();
+ 'one'
+ node> var iterator3 = iterator2();
+ 'two'
+ node> iterator3();
+ 'three'
+ node> var nextfn = iterator2.next();
+ node> nextfn();
+ 'three'
+
+
+---------------------------------------
+
+<a name="apply" />
+### apply(function, arguments..)
+
+Creates a continuation function with some arguments already applied, a useful
+shorthand when combined with other control flow functions. Any arguments
+passed to the returned function are added to the arguments originally passed
+to apply.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to automatically apply when the
+ continuation is called.
+
+__Example__
+
+ // using apply
+
+ async.parallel([
+ async.apply(fs.writeFile, 'testfile1', 'test1'),
+ async.apply(fs.writeFile, 'testfile2', 'test2'),
+ ]);
+
+
+ // the same process without using apply
+
+ async.parallel([
+ function(callback){
+ fs.writeFile('testfile1', 'test1', callback);
+ },
+ function(callback){
+ fs.writeFile('testfile2', 'test2', callback);
+ },
+ ]);
+
+It's possible to pass any number of additional arguments when calling the
+continuation:
+
+ node> var fn = async.apply(sys.puts, 'one');
+ node> fn('two', 'three');
+ one
+ two
+ three
+
+---------------------------------------
+
+<a name="nextTick" />
+### nextTick(callback)
+
+Calls the callback on a later loop around the event loop. In node.js this just
+calls process.nextTick, in the browser it falls back to setTimeout(callback, 0),
+which means other higher priority events may precede the execution of the callback.
+
+This is used internally for browser-compatibility purposes.
+
+__Arguments__
+
+* callback - The function to call on a later loop around the event loop.
+
+__Example__
+
+ var call_order = [];
+ async.nextTick(function(){
+ call_order.push('two');
+ // call_order now equals ['one','two]
+ });
+ call_order.push('one')
+
+
+## Utils
+
+<a name="memoize" />
+### memoize(fn, [hasher])
+
+Caches the results of an async function. When creating a hash to store function
+results against, the callback is omitted from the hash and an optional hash
+function can be used.
+
+__Arguments__
+
+* fn - the function you to proxy and cache results from.
+* hasher - an optional function for generating a custom hash for storing
+ results, it has all the arguments applied to it apart from the callback, and
+ must be synchronous.
+
+__Example__
+
+ var slow_fn = function (name, callback) {
+ // do something
+ callback(null, result);
+ };
+ var fn = async.memoize(slow_fn);
+
+ // fn can now be used as if it were slow_fn
+ fn('some name', function () {
+ // callback
+ });
+
+<a name="unmemoize" />
+### unmemoize(fn)
+
+Undoes a memoized function, reverting it to the original, unmemoized
+form. Comes handy in tests.
+
+__Arguments__
+
+* fn - the memoized function
+
+<a name="log" />
+### log(function, arguments)
+
+Logs the result of an async function to the console. Only works in node.js or
+in browsers that support console.log and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.log is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+ var hello = function(name, callback){
+ setTimeout(function(){
+ callback(null, 'hello ' + name);
+ }, 1000);
+ };
+
+ node> async.log(hello, 'world');
+ 'hello world'
+
+
+---------------------------------------
+
+<a name="dir" />
+### dir(function, arguments)
+
+Logs the result of an async function to the console using console.dir to
+display the properties of the resulting object. Only works in node.js or
+in browsers that support console.dir and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.dir is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+ var hello = function(name, callback){
+ setTimeout(function(){
+ callback(null, {hello: name});
+ }, 1000);
+ };
+
+ node> async.dir(hello, 'world');
+ {hello: 'world'}
+
+
+---------------------------------------
+
+<a name="noConflict" />
+### noConflict()
+
+Changes the value of async back to its original value, returning a reference to the
+async object.
3 node_modules/async/index.js
@@ -0,0 +1,3 @@
+// This file is just added for convenience so this repository can be
+// directly checked out into a project's deps folder
+module.exports = require('./lib/async');
692 node_modules/async/lib/async.js
@@ -0,0 +1,692 @@
+/*global setTimeout: false, console: false */
+(function () {
+
+ var async = {};
+
+ // global on the server, window in the browser
+ var root = this,
+ previous_async = root.async;
+
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = async;
+ }
+ else {
+ root.async = async;
+ }
+
+ async.noConflict = function () {
+ root.async = previous_async;
+ return async;
+ };
+
+ //// cross-browser compatiblity functions ////
+
+ var _forEach = function (arr, iterator) {
+ if (arr.forEach) {
+ return arr.forEach(iterator);
+ }
+ for (var i = 0; i < arr.length; i += 1) {
+ iterator(arr[i], i, arr);
+ }
+ };
+
+ var _map = function (arr, iterator) {
+ if (arr.map) {
+ return arr.map(iterator);
+ }
+ var results = [];
+ _forEach(arr, function (x, i, a) {
+ results.push(iterator(x, i, a));
+ });
+ return results;
+ };
+
+ var _reduce = function (arr, iterator, memo) {
+ if (arr.reduce) {
+ return arr.reduce(iterator, memo);
+ }
+ _forEach(arr, function (x, i, a) {
+ memo = iterator(memo, x, i, a);
+ });
+ return memo;
+ };
+
+ var _keys = function (obj) {
+ if (Object.keys) {
+ return Object.keys(obj);
+ }
+ var keys = [];
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ keys.push(k);
+ }
+ }
+ return keys;
+ };
+
+ //// exported async module functions ////
+
+ //// nextTick implementation with browser-compatible fallback ////
+ if (typeof process === 'undefined' || !(process.nextTick)) {
+ async.nextTick = function (fn) {
+ setTimeout(fn, 0);
+ };
+ }
+ else {
+ async.nextTick = process.nextTick;
+ }
+
+ async.forEach = function (arr, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length) {
+ return callback();
+ }
+ var completed = 0;
+ _forEach(arr, function (x) {
+ iterator(x, function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ if (completed === arr.length) {
+ callback();
+ }
+ }
+ });
+ });
+ };
+
+ async.forEachSeries = function (arr, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length) {
+ return callback();
+ }
+ var completed = 0;
+ var iterate = function () {
+ iterator(arr[completed], function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ if (completed === arr.length) {
+ callback();
+ }
+ else {
+ iterate();
+ }
+ }
+ });
+ };
+ iterate();
+ };
+
+ async.forEachLimit = function (arr, limit, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length || limit <= 0) {
+ return callback();
+ }
+ var completed = 0;
+ var started = 0;
+ var running = 0;
+
+ (function replenish () {
+ if (completed === arr.length) {
+ return callback();
+ }
+
+ while (running < limit && started < arr.length) {
+ iterator(arr[started], function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ running -= 1;
+ if (completed === arr.length) {
+ callback();
+ }
+ else {
+ replenish();
+ }
+ }
+ });
+ started += 1;
+ running += 1;
+ }
+ })();
+ };
+
+
+ var doParallel = function (fn) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [async.forEach].concat(args));
+ };
+ };
+ var doSeries = function (fn) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [async.forEachSeries].concat(args));
+ };
+ };
+
+
+ var _asyncMap = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (err, v) {
+ results[x.index] = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ };
+ async.map = doParallel(_asyncMap);
+ async.mapSeries = doSeries(_asyncMap);
+
+
+ // reduce only has a series version, as doing reduce in parallel won't
+ // work in many situations.
+ async.reduce = function (arr, memo, iterator, callback) {
+ async.forEachSeries(arr, function (x, callback) {
+ iterator(memo, x, function (err, v) {
+ memo = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, memo);
+ });
+ };
+ // inject alias
+ async.inject = async.reduce;
+ // foldl alias
+ async.foldl = async.reduce;
+
+ async.reduceRight = function (arr, memo, iterator, callback) {
+ var reversed = _map(arr, function (x) {
+ return x;
+ }).reverse();
+ async.reduce(reversed, memo, iterator, callback);
+ };
+ // foldr alias
+ async.foldr = async.reduceRight;
+
+ var _filter = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (v) {
+ if (v) {
+ results.push(x);
+ }
+ callback();
+ });
+ }, function (err) {
+ callback(_map(results.sort(function (a, b) {
+ return a.index - b.index;
+ }), function (x) {
+ return x.value;
+ }));
+ });
+ };
+ async.filter = doParallel(_filter);
+ async.filterSeries = doSeries(_filter);
+ // select alias
+ async.select = async.filter;
+ async.selectSeries = async.filterSeries;
+
+ var _reject = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (v) {
+ if (!v) {
+ results.push(x);
+ }
+ callback();
+ });
+ }, function (err) {
+ callback(_map(results.sort(function (a, b) {
+ return a.index - b.index;
+ }), function (x) {
+ return x.value;
+ }));
+ });
+ };
+ async.reject = doParallel(_reject);
+ async.rejectSeries = doSeries(_reject);
+
+ var _detect = function (eachfn, arr, iterator, main_callback) {
+ eachfn(arr, function (x, callback) {
+ iterator(x, function (result) {
+ if (result) {
+ main_callback(x);
+ main_callback = function () {};
+ }
+ else {
+ callback();
+ }
+ });
+ }, function (err) {
+ main_callback();
+ });
+ };
+ async.detect = doParallel(_detect);
+ async.detectSeries = doSeries(_detect);
+
+ async.some = function (arr, iterator, main_callback) {
+ async.forEach(arr, function (x, callback) {
+ iterator(x, function (v) {
+ if (v) {
+ main_callback(true);
+ main_callback = function () {};
+ }
+ callback();
+ });
+ }, function (err) {
+ main_callback(false);
+ });
+ };
+ // any alias
+ async.any = async.some;
+
+ async.every = function (arr, iterator, main_callback) {
+ async.forEach(arr, function (x, callback) {
+ iterator(x, function (v) {
+ if (!v) {
+ main_callback(false);
+ main_callback = function () {};
+ }
+ callback();
+ });
+ }, function (err) {
+ main_callback(true);
+ });
+ };
+ // all alias
+ async.all = async.every;
+
+ async.sortBy = function (arr, iterator, callback) {
+ async.map(arr, function (x, callback) {
+ iterator(x, function (err, criteria) {
+ if (err) {
+ callback(err);
+ }
+ else {
+ callback(null, {value: x, criteria: criteria});
+ }
+ });
+ }, function (err, results) {
+ if (err) {
+ return callback(err);
+ }
+ else {
+ var fn = function (left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ };
+ callback(null, _map(results.sort(fn), function (x) {
+ return x.value;
+ }));
+ }
+ });
+ };
+
+ async.auto = function (tasks, callback) {
+ callback = callback || function () {};
+ var keys = _keys(tasks);
+ if (!keys.length) {
+ return callback(null);
+ }
+
+ var results = {};
+
+ var listeners = [];
+ var addListener = function (fn) {
+ listeners.unshift(fn);
+ };
+ var removeListener = function (fn) {
+ for (var i = 0; i < listeners.length; i += 1) {
+ if (listeners[i] === fn) {
+ listeners.splice(i, 1);
+ return;
+ }
+ }
+ };
+ var taskComplete = function () {
+ _forEach(listeners.slice(0), function (fn) {
+ fn();
+ });
+ };
+
+ addListener(function () {
+ if (_keys(results).length === keys.length) {
+ callback(null, results);
+ callback = function () {};
+ }
+ });
+
+ _forEach(keys, function (k) {
+ var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
+ var taskCallback = function (err) {
+ if (err) {
+ callback(err);
+ // stop subsequent errors hitting callback multiple times
+ callback = function () {};
+ }
+ else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ taskComplete();
+ }
+ };
+ var requires = task.slice(0, Math.abs(task.length - 1)) || [];
+ var ready = function () {
+ return _reduce(requires, function (a, x) {
+ return (a && results.hasOwnProperty(x));
+ }, true);
+ };
+ if (ready()) {
+ task[task.length - 1](taskCallback, results);
+ }
+ else {
+ var listener = function () {
+ if (ready()) {
+ removeListener(listener);
+ task[task.length - 1](taskCallback, results);
+ }
+ };
+ addListener(listener);
+ }
+ });
+ };
+
+ async.waterfall = function (tasks, callback) {
+ callback = callback || function () {};
+ if (!tasks.length) {
+ return callback();
+ }
+ var wrapIterator = function (iterator) {
+ return function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var next = iterator.next();
+ if (next) {
+ args.push(wrapIterator(next));
+ }
+ else {
+ args.push(callback);
+ }
+ async.nextTick(function () {
+ iterator.apply(null, args);
+ });
+ }
+ };
+ };
+ wrapIterator(async.iterator(tasks))();
+ };
+
+ async.parallel = function (tasks, callback) {
+ callback = callback || function () {};
+ if (tasks.constructor === Array) {
+ async.map(tasks, function (fn, callback) {
+ if (fn) {
+ fn(function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ callback.call(null, err, args);
+ });
+ }
+ }, callback);
+ }
+ else {
+ var results = {};
+ async.forEach(_keys(tasks), function (k, callback) {
+ tasks[k](function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ }
+ };
+
+ async.series = function (tasks, callback) {
+ callback = callback || function () {};
+ if (tasks.constructor === Array) {
+ async.mapSeries(tasks, function (fn, callback) {
+ if (fn) {
+ fn(function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ callback.call(null, err, args);
+ });
+ }
+ }, callback);
+ }
+ else {
+ var results = {};
+ async.forEachSeries(_keys(tasks), function (k, callback) {
+ tasks[k](function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ }
+ };
+
+ async.iterator = function (tasks) {
+ var makeCallback = function (index) {
+ var fn = function () {
+ if (tasks.length) {
+ tasks[index].apply(null, arguments);
+ }
+ return fn.next();
+ };
+ fn.next = function () {
+ return (index < tasks.length - 1) ? makeCallback(index + 1): null;
+ };
+ return fn;
+ };
+ return makeCallback(0);
+ };
+
+ async.apply = function (fn) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function () {
+ return fn.apply(
+ null, args.concat(Array.prototype.slice.call(arguments))
+ );
+ };
+ };
+
+ var _concat = function (eachfn, arr, fn, callback) {
+ var r = [];
+ eachfn(arr, function (x, cb) {
+ fn(x, function (err, y) {
+ r = r.concat(y || []);
+ cb(err);
+ });
+ }, function (err) {
+ callback(err, r);
+ });
+ };
+ async.concat = doParallel(_concat);
+ async.concatSeries = doSeries(_concat);
+
+ async.whilst = function (test, iterator, callback) {
+ if (test()) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ async.whilst(test, iterator, callback);
+ });
+ }
+ else {
+ callback();
+ }
+ };
+
+ async.until = function (test, iterator, callback) {
+ if (!test()) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ async.until(test, iterator, callback);
+ });
+ }
+ else {
+ callback();
+ }
+ };
+
+ async.queue = function (worker, concurrency) {
+ var workers = 0;
+ var q = {
+ tasks: [],
+ concurrency: concurrency,
+ saturated: null,
+ empty: null,
+ drain: null,
+ push: function (data, callback) {
+ if(data.constructor !== Array) {
+ data = [data];
+ }
+ _forEach(data, function(task) {
+ q.tasks.push({
+ data: task,
+ callback: typeof callback === 'function' ? callback : null
+ });
+ if (q.saturated && q.tasks.length == concurrency) {
+ q.saturated();
+ }
+ async.nextTick(q.process);
+ });
+ },
+ process: function () {
+ if (workers < q.concurrency && q.tasks.length) {
+ var task = q.tasks.shift();
+ if(q.empty && q.tasks.length == 0) q.empty();
+ workers += 1;
+ worker(task.data, function () {
+ workers -= 1;
+ if (task.callback) {
+ task.callback.apply(task, arguments);
+ }
+ if(q.drain && q.tasks.length + workers == 0) q.drain();
+ q.process();
+ });
+ }
+ },
+ length: function () {
+ return q.tasks.length;
+ },
+ running: function () {
+ return workers;
+ }
+ };
+ return q;
+ };
+
+ var _console_fn = function (name) {
+ return function (fn) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ fn.apply(null, args.concat([function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (typeof console !== 'undefined') {
+ if (err) {
+ if (console.error) {
+ console.error(err);
+ }
+ }
+ else if (console[name]) {
+ _forEach(args, function (x) {
+ console[name](x);
+ });
+ }
+ }
+ }]));
+ };
+ };
+ async.log = _console_fn('log');
+ async.dir = _console_fn('dir');
+ /*async.info = _console_fn('info');
+ async.warn = _console_fn('warn');
+ async.error = _console_fn('error');*/
+
+ async.memoize = function (fn, hasher) {
+ var memo = {};
+ var queues = {};
+ hasher = hasher || function (x) {
+ return x;
+ };
+ var memoized = function () {
+ var args = Array.prototype.slice.call(arguments);
+ var callback = args.pop();
+ var key = hasher.apply(null, args);
+ if (key in memo) {
+ callback.apply(null, memo[key]);
+ }
+ else if (key in queues) {
+ queues[key].push(callback);
+ }
+ else {
+ queues[key] = [callback];
+ fn.apply(null, args.concat([function () {
+ memo[key] = arguments;
+ var q = queues[key];
+ delete queues[key];
+ for (var i = 0, l = q.length; i < l; i++) {
+ q[i].apply(null, arguments);
+ }
+ }]));
+ }
+ };
+ memoized.unmemoized = fn;
+ return memoized;
+ };
+
+ async.unmemoize = function (fn) {
+ return function () {
+ return (fn.unmemoized || fn).apply(null, arguments);
+ }
+ };
+
+}());
42 node_modules/async/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "async",
+ "description": "Higher-order functions and common patterns for asynchronous code",
+ "main": "./index",
+ "author": {
+ "name": "Caolan McMahon"
+ },
+ "version": "0.1.18",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/caolan/async.git"
+ },
+ "bugs": {
+ "url": "http://github.com/caolan/async/issues"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/caolan/async/raw/master/LICENSE"
+ }
+ ],
+ "devDependencies": {
+ "nodeunit": ">0.0.0",
+ "uglify-js": "1.2.x",
+ "nodelint": ">0.0.0"
+ },
+ "_npmUser": {
+ "name": "ddollar",
+ "email": "ddollar@gmail.com"
+ },
+ "_id": "async@0.1.18",
+ "dependencies": {},
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ },
+ "_engineSupported": true,
+ "_npmVersion": "1.1.21",
+ "_nodeVersion": "v0.6.17",
+ "_defaultsLoaded": true,
+ "_from": "async@0.1.x"
+}
11 node_modules/coffee-script/.npmignore
@@ -0,0 +1,11 @@
+*.coffee
+*.html
+.DS_Store
+.git*
+Cakefile
+documentation/
+examples/
+extras/coffee-script.js
+raw/
+src/
+test/
22 node_modules/coffee-script/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Jeremy Ashkenas
+
+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.
51 node_modules/coffee-script/README
@@ -0,0 +1,51 @@
+
+ {
+ } } {
+ { { } }
+ } }{ {
+ { }{ } } _____ __ __
+ ( }{ }{ { ) / ____| / _|/ _|
+ .- { { } { }} -. | | ___ | |_| |_ ___ ___
+ ( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \
+ |`-..________ ..-'| | |___| (_) | | | || __/ __/
+ | | \_____\___/|_| |_| \___|\___|
+ | ;--.
+ | (__ \ _____ _ _
+ | | ) ) / ____| (_) | |
+ | |/ / | (___ ___ _ __ _ _ __ | |_
+ | ( / \___ \ / __| '__| | '_ \| __|
+ | |/ ____) | (__| | | | |_) | |_
+ | | |_____/ \___|_| |_| .__/ \__|
+ `-.._________..-' | |
+ |_|
+
+
+ CoffeeScript is a little language that compiles into JavaScript.
+
+ Install Node.js, and then the CoffeeScript compiler:
+ sudo bin/cake install
+
+ Or, if you have the Node Package Manager installed:
+ npm install -g coffee-script
+ (Leave off the -g if you don't wish to install globally.)
+
+ Execute a script:
+ coffee /path/to/script.coffee
+
+ Compile a script:
+ coffee -c /path/to/script.coffee
+
+ For documentation, usage, and examples, see:
+ http://coffeescript.org/
+
+ To suggest a feature, report a bug, or general discussion:
+ http://github.com/jashkenas/coffee-script/issues/
+
+ If you'd like to chat, drop by #coffeescript on Freenode IRC,
+ or on webchat.freenode.net.
+
+ The source repository:
+ git://github.com/jashkenas/coffee-script.git
+
+ All contributors are listed here:
+ http://github.com/jashkenas/coffee-script/contributors
78 node_modules/coffee-script/Rakefile
@@ -0,0 +1,78 @@
+require 'rubygems'
+require 'erb'
+require 'fileutils'
+require 'rake/testtask'
+require 'json'
+
+desc "Build the documentation page"
+task :doc do
+ source = 'documentation/index.html.erb'
+ child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
+ at_exit { Process.kill("INT", child) }
+ Signal.trap("INT") { exit }
+ loop do
+ mtime = File.stat(source).mtime
+ if !@mtime || mtime > @mtime
+ rendered = ERB.new(File.read(source)).result(binding)
+ File.open('index.html', 'w+') {|f| f.write(rendered) }
+ end
+ @mtime = mtime
+ sleep 1
+ end
+end
+
+desc "Build coffee-script-source gem"
+task :gem do
+ require 'rubygems'
+ require 'rubygems/package'
+
+ gemspec = Gem::Specification.new do |s|
+ s.name = 'coffee-script-source'
+ s.version = JSON.parse(File.read('package.json'))["version"]
+ s.date = Time.now.strftime("%Y-%m-%d")
+
+ s.homepage = "http://jashkenas.github.com/coffee-script/"
+ s.summary = "The CoffeeScript Compiler"
+ s.description = <<-EOS
+ CoffeeScript is a little language that compiles into JavaScript.
+ Underneath all of those embarrassing braces and semicolons,
+ JavaScript has always had a gorgeous object model at its heart.
+ CoffeeScript is an attempt to expose the good parts of JavaScript
+ in a simple way.
+ EOS
+
+ s.files = [
+ 'lib/coffee_script/coffee-script.js',
+ 'lib/coffee_script/source.rb'
+ ]
+
+ s.authors = ['Jeremy Ashkenas']
+ s.email = 'jashkenas@gmail.com'
+ s.rubyforge_project = 'coffee-script-source'
+ end
+
+ file = File.open("coffee-script-source.gem", "w")
+ Gem::Package.open(file, 'w') do |pkg|
+ pkg.metadata = gemspec.to_yaml
+
+ path = "lib/coffee_script/source.rb"
+ contents = <<-ERUBY
+module CoffeeScript
+ module Source
+ def self.bundled_path
+ File.expand_path("../coffee-script.js", __FILE__)
+ end
+ end
+end
+ ERUBY
+ pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+ tar_io.write(contents)
+ end
+
+ contents = File.read("extras/coffee-script.js")
+ path = "lib/coffee_script/coffee-script.js"
+ pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
+ tar_io.write(contents)
+ end
+ end
+end
7 node_modules/coffee-script/bin/cake
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs = require('fs');
+var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/coffee-script/cake').run();
7 node_modules/coffee-script/bin/coffee
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+var path = require('path');
+var fs = require('fs');
+var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
+
+require(lib + '/coffee-script/command').run();
44 node_modules/coffee-script/extras/jsl.conf
@@ -0,0 +1,44 @@
+# JavaScriptLint configuration file for CoffeeScript.
+
++no_return_value # function {0} does not always return a value
++duplicate_formal # duplicate formal argument {0}
+-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
++var_hides_arg # variable {0} hides argument
++redeclared_var # redeclaration of {0} {1}
+-anon_no_return_value # anonymous function does not always return a value
++missing_semicolon # missing semicolon
++meaningless_block # meaningless block; curly braces have no impact
+-comma_separated_stmts # multiple statements separated by commas (use semicolons?)
++unreachable_code # unreachable code
++missing_break # missing break statement
+-missing_break_for_last_case # missing break statement for last case in switch
+-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
+-useless_void # use of the void type may be unnecessary (void is always undefined)
++multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
++use_of_label # use of label
+-block_without_braces # block statement without curly braces
++leading_decimal_point # leading decimal point may indicate a number or an object member
++trailing_decimal_point # trailing decimal point may indicate a number or an object member
++octal_number # leading zeros make an octal number
++nested_comment # nested comment
++misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
++ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
++empty_statement # empty statement or extra semicolon
+-missing_option_explicit # the "option explicit" control comment is missing
++partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
++dup_option_explicit # duplicate "option explicit" control comment
++useless_assign # useless assignment
++ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
++ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+-missing_default_case # missing default case in switch statement
++duplicate_case_in_switch # duplicate case in switch statements
++default_not_at_end # the default case is not at the end of the switch statement
++legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
++jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
++useless_comparison # useless comparison; comparing identical expressions
++with_statement # with statement hides undeclared variables; use temporary variable instead
++trailing_comma_in_array # extra comma is not recommended in array initializers
++assign_to_function_call # assignment to a function call
++parseint_missing_radix # parseInt missing radix parameter
++lambda_assign_requires_semicolon
74 node_modules/coffee-script/lib/coffee-script/browser.js
@@ -0,0 +1,74 @@
+(function() {
+ var CoffeeScript, runScripts;
+
+ CoffeeScript = require('./coffee-script');
+
+ CoffeeScript.require = require;
+