diff options
Diffstat (limited to 'node_modules/supertest')
147 files changed, 23068 insertions, 0 deletions
diff --git a/node_modules/supertest/.npmignore b/node_modules/supertest/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/supertest/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/supertest/.travis.yml b/node_modules/supertest/.travis.yml new file mode 100644 index 0000000..471b276 --- /dev/null +++ b/node_modules/supertest/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "5" + - "4" + - "0.12" + - "0.10" diff --git a/node_modules/supertest/History.md b/node_modules/supertest/History.md new file mode 100644 index 0000000..6960f8a --- /dev/null +++ b/node_modules/supertest/History.md @@ -0,0 +1,181 @@ +1.2.0 / 2016-02-11 +=================== + + * PR-302 - Update to superagent ^1.7.2 + * PR-313 - Update node versions on Travis CI + * PR-223 - Remove Makefile for running tests + * PR-286 - Fix bug with redirects + +1.1.0 / 2015-08-26 +=================== + + * PR-235 - Update test framework to express 4, update other deps + * PR-239 - Core refactor to run expectations in order of definition + * PR-273 - Documentation update related to PR-239 + * PR-268 - Bump superagent to 1.3.0 + +1.0.1 / 2015-05-08 +=================== + + * PR-224 - Better expected error support as result of super-agent 1.x + +1.0.0 / 2015-05-08 +=================== + + * Bumping version to 1.0.0!, big changes with superagent + * Update superagent dependency to 1.2.0 + +0.15.0 / 2014-11-11 +=================== + + * Update superagent dependency + +0.14.0 / 2014-09-29 +=================== + + * Update superagent dependency + * Update methods dependency + +0.13.0 / 2014-05-22 +=================== + + * Wait for server close before invoke the callback for `end()` + * Fix global leak in tests + +0.12.1 / 2014-05-09 +=================== + + * update methods dependency + +0.11.0 / 2014-04-14 +================== + + * close internal server upon test end + * add .delete() method (aliases .del()) + +0.10.0 / 2014-03-20 +================== + + * assert respond body prior to the status code + * add documentation for .agent() + +0.9.2 / 2014-03-17 +================== + + * fix package.json + +0.9.1 / 2014-03-17 +================== + + * update superagent + +0.9.0 / 2014-01-17 +================== + + * add expect(function(res) {}) syntax + +0.8.3 / 2014-01-07 +================== + + * update superagent. + +0.8.2 / 2013-11-26 +================== + + * update superagent. Closes #85 + +0.8.1 / 2013-10-28 +================== + + * merge pull request #82 from jonathanong/patch-1 + * bump node-methods + * merge pull request #79 from menzoic/patch-1 + * update Readme.md + * Merge pull request #73 from repoify/add/repository + * add repository field to readme + +0.8.0 / 2013-08-09 +================== + + * add ability for multiple assertions per header + +0.7.1 / 2013-07-02 +================== + + * update superagent + +0.7.0 / 2013-06-04 +================== + + * add error properties so test frameworks can show diffs etc. Closes #65 + +0.6.1 / 2013-06-02 +================== + + * fix: EADDRINUSE errnos, use ephemeral ports now + * fix: handling of socket errors + +0.6.0 / 2013-04-15 +================== + + * add exposing of `Test` to enable extensibility + * add request.agent(app) support + * add request(url) test. Closes #33 + +0.5.1 2012-12-07 +================== + + * fix .expect(status) should assert only status + +0.5.0/ 2012-11-28 +================== + + * add support for multiple body assertions + +0.4.2 / 2012-11-17 +================== + + * add .buffer() so that responses with no content-length are testable. closes #36 + * add failing test for #36 + * update superagent + +0.4.1 / 2012-11-14 +================== + + * update superagent + +0.4.0 / 2012-10-18 +================== + + * add url support [vesln] + +0.3.1 / 2012-10-01 +================== + + * update superagent + +0.3.0 / 2012-09-24 +================== + + * add `https.Server` support [fengmk2] + +0.2.0 / 2012-08-29 +================== + + * update superagent. Closes #18 + +0.1.2 / 2012-07-15 +================== + + * change bind address from 0.0.0.0 to 127.0.0.1 to prevent EADDRNOTAVAIL on windows + +0.1.1 / 2012-07-03 +================== + + * add `.expect(status, body, fn)` support + * add `.expect(status, body)` support + +0.1.0 / 2012-07-02 +================== + + * add parsed body assertion support. Closes #1 diff --git a/node_modules/supertest/LICENSE b/node_modules/supertest/LICENSE new file mode 100644 index 0000000..a7693b0 --- /dev/null +++ b/node_modules/supertest/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca> + +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/supertest/Readme.md b/node_modules/supertest/Readme.md new file mode 100644 index 0000000..daf1b43 --- /dev/null +++ b/node_modules/supertest/Readme.md @@ -0,0 +1,222 @@ +# SuperTest [](https://travis-ci.org/visionmedia/supertest) [](https://www.npmjs.com/package/supertest) + + HTTP assertions made easy via [super-agent](http://github.com/visionmedia/superagent). + +## About + + The motivation with this module is to provide a high-level abstraction for testing + HTTP, while still allowing you to drop down to the lower-level API provided by super-agent. + +## Getting Started + + Install SuperTest as an npm module and save it to your package.json file as a development dependency: + ``` +npm install supertest --save-dev + ``` + + Once installed it can now be referenced by simply calling ```require("supertest");``` + +## Example + + You may pass an `http.Server`, or a `Function` to `request()` - if the server is not + already listening for connections then it is bound to an ephemeral port for you so + there is no need to keep track of ports. + + SuperTest works with any test framework, here is an example without using any + test framework at all: + +```js +var request = require('supertest') + , express = require('express'); + +var app = express(); + +app.get('/user', function(req, res){ + res.status(200).json({ name: 'tobi' }); +}); + +request(app) + .get('/user') + .expect('Content-Type', /json/) + .expect('Content-Length', '15') + .expect(200) + .end(function(err, res){ + if (err) throw err; + }); +``` + + Here's an example with mocha, note how you can pass `done` straight to any of the `.expect()` calls: + +```js +describe('GET /user', function(){ + it('respond with json', function(done){ + request(app) + .get('/user') + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200, done); + }) +}) +``` + +One thing to note with the above statement is that superagent now sends any HTTP +error (anything other than a 2XX response code) to the callback as the first argument if +you do not add a status code expect (i.e. `.expect(302)`). + + If you are using the `.end()` method `.expect()` assertions that fail will + not throw - they will return the assertion as an error to the `.end()` callback. In + order to fail the test case, you will need to rethrow or pass `err` to `done()`, as follows: + +```js +describe('GET /users', function(){ + it('respond with json', function(done){ + request(app) + .get('/user') + .set('Accept', 'application/json') + .expect(200) + .end(function(err, res){ + if (err) return done(err); + done(); + }); + }); +}); +``` + + Expectations are run in the order of definition. This characteristic can be used + to modify the response body or headers before executing an assertion. + +```js +describe('GET /user', function(){ + it('user.name should be an case-insensitive match for "tobi"', function(done){ + request(app) + .get('/user') + .set('Accept', 'application/json') + .expect(function(res) { + res.body.id = 'some fixed id'; + res.body.name = res.body.name.toUpperCase(); + }) + .expect(200, { + id: 'some fixed id', + name: 'TOBI' + }, done); + }); +}); + +``` + + Anything you can do with superagent, you can do with supertest - for example multipart file uploads! + +```js +request(app) +.post('/') +.field('name', 'my awesome avatar') +.attach('avatar', 'test/fixtures/homeboy.jpg') +... +``` + + Passing the app or url each time is not necessary, if you're testing + the same host you may simply re-assign the request variable with the + initialization app or url, a new `Test` is created per `request.VERB()` call. + +```js +request = request('http://localhost:5555'); + +request.get('/').expect(200, function(err){ + console.log(err); +}); + +request.get('/').expect('heya', function(err){ + console.log(err); +}); +``` + Here's an example with mocha that shows how to persist a request and its cookies: + +```js +var request = require('supertest') + , should = require('should') + , express = require('express'); + + +describe('request.agent(app)', function(){ + var app = express(); + app.use(express.cookieParser()); + + app.get('/', function(req, res){ + res.cookie('cookie', 'hey'); + res.send(); + }); + + app.get('/return', function(req, res){ + if (req.cookies.cookie) res.send(req.cookies.cookie); + else res.send(':(') + }); + + var agent = request.agent(app); + + it('should save cookies', function(done){ + agent + .get('/') + .expect('set-cookie', 'cookie=hey; Path=/', done); + }) + + it('should send cookies', function(done){ + agent + .get('/return') + .expect('hey', done); + }) +}) +``` + There is another example that is introduced by the file [agency.js](https://github.com/visionmedia/superagent/blob/master/test/node/agency.js) + +## API + + You may use any [super-agent](http://github.com/visionmedia/superagent) methods, + including `.write()`, `.pipe()` etc and perform assertions in the `.end()` callback + for lower-level needs. + +### .expect(status[, fn]) + + Assert response `status` code. + +### .expect(status, body[, fn]) + + Assert response `status` code and `body`. + +### .expect(body[, fn]) + + Assert response `body` text with a string, regular expression, or + parsed body object. + +### .expect(field, value[, fn]) + + Assert header `field` `value` with a string or regular expression. + +### .expect(function(res) {}) + + Pass a custom assertion function. It'll be given the response object to check. If the response is ok, it should return falsy, most commonly by not returning anything. If the check fails, throw an error or return a truthy value like a string that'll be turned into an error. + + Here the string or error throwing options are both demonstrated: + + ```js + request(app) + .get('/') + .expect(hasPreviousAndNextKeys) + .end(done); + + function hasPreviousAndNextKeys(res) { + if (!('next' in res.body)) return "missing next key"; + if (!('prev' in res.body)) throw new Error("missing prev key"); + } + ``` + +### .end(fn) + + Perform the request and invoke `fn(err, res)`. + +## Notes + + Inspired by [api-easy](https://github.com/flatiron/api-easy) minus vows coupling. + +## License + + MIT diff --git a/node_modules/supertest/example.js b/node_modules/supertest/example.js new file mode 100644 index 0000000..d128ab7 --- /dev/null +++ b/node_modules/supertest/example.js @@ -0,0 +1,20 @@ + +var request = require('./') + , express = require('express'); + +var app = express(); + +app.get('/user', function(req, res){ + res.status(201).json({ name: 'tobi' }); +}); + +request(app) + .get('/user') + .expect('Content-Type', /json/) + .expect('Content-Length', '15') + .expect(201) + .end(function(err, res){ + if (err) throw err; + console.log('done'); + process.exit(); + }); diff --git a/node_modules/supertest/index.js b/node_modules/supertest/index.js new file mode 100644 index 0000000..41a75d5 --- /dev/null +++ b/node_modules/supertest/index.js @@ -0,0 +1,45 @@ + +/** + * Module dependencies. + */ + +var methods = require('methods') + , Test = require('./lib/test') + , http = require('http'); + +/** + * Test against the given `app`, + * returning a new `Test`. + * + * @param {Function|Server} app + * @return {Test} + * @api public + */ + +module.exports = function(app){ + if ('function' == typeof app) app = http.createServer(app); + var obj = {}; + + methods.forEach(function(method){ + obj[method] = function(url){ + return new Test(app, method, url); + }; + }); + + // Support previous use of del + obj.del = obj['delete']; + + return obj; +}; + +/** + * Expose `Test` + */ + +module.exports.Test = Test; + +/** + * Expose the agent function + */ + +module.exports.agent = require('./lib/agent'); diff --git a/node_modules/supertest/lib/agent.js b/node_modules/supertest/lib/agent.js new file mode 100644 index 0000000..ccd2cfd --- /dev/null +++ b/node_modules/supertest/lib/agent.js @@ -0,0 +1,54 @@ + +/** + * Module dependencies. + */ + +var Agent = require('superagent').agent + , methods = require('methods') + , http = require('http') + , Test = require('./test'); + +/** + * Expose `Agent`. + */ + +module.exports = TestAgent; + +/** + * Initialize a new `TestAgent`. + * + * @param {Function|Server} app + * @param {Object} options + * @api public + */ + +function TestAgent(app, options){ + if (!(this instanceof TestAgent)) return new TestAgent(app, options); + if ('function' == typeof app) app = http.createServer(app); + if (options) this._ca = options.ca; + Agent.call(this); + this.app = app; +} + +/** + * Inherits from `Agent.prototype`. + */ + +TestAgent.prototype.__proto__ = Agent.prototype; + +// override HTTP verb methods +methods.forEach(function(method){ + TestAgent.prototype[method] = function(url, fn){ + var req = new Test(this.app, method.toUpperCase(), url); + req.ca(this._ca); + + req.on('response', this.saveCookies.bind(this)); + req.on('redirect', this.saveCookies.bind(this)); + req.on('redirect', this.attachCookies.bind(this, req)); + this.attachCookies(req); + + return req; + }; +}); + +TestAgent.prototype.del = TestAgent.prototype.delete; diff --git a/node_modules/supertest/lib/test.js b/node_modules/supertest/lib/test.js new file mode 100644 index 0000000..6bdca85 --- /dev/null +++ b/node_modules/supertest/lib/test.js @@ -0,0 +1,270 @@ +/** + * Module dependencies. + */ + +var request = require('superagent') + , util = require('util') + , http = require('http') + , https = require('https') + , assert = require('assert') + , Request = request.Request; + +/** + * Expose `Test`. + */ + +module.exports = Test; + +/** + * Initialize a new `Test` with the given `app`, + * request `method` and `path`. + * + * @param {Server} app + * @param {String} method + * @param {String} path + * @api public + */ + +function Test(app, method, path) { + Request.call(this, method, path); + this.redirects(0); + this.buffer(); + this.app = app; + this._asserts = []; + this.url = 'string' == typeof app + ? app + path + : this.serverAddress(app, path); +} + +/** + * Inherits from `Request.prototype`. + */ + +Test.prototype.__proto__ = Request.prototype; + +/** + * Returns a URL, extracted from a server. + * + * @param {Server} app + * @param {String} path + * @returns {String} URL address + * @api private + */ + +Test.prototype.serverAddress = function(app, path){ + var addr = app.address(); + if (!addr) this._server = app.listen(0); + var port = app.address().port; + var protocol = app instanceof https.Server ? 'https' : 'http'; + return protocol + '://127.0.0.1:' + port + path; +}; + +/** + * Expectations: + * + * .expect(200) + * .expect(200, fn) + * .expect(200, body) + * .expect('Some body') + * .expect('Some body', fn) + * .expect('Content-Type', 'application/json') + * .expect('Content-Type', 'application/json', fn) + * .expect(fn) + * + * @return {Test} + * @api public + */ + +Test.prototype.expect = function(a, b, c){ + // callback + if ('function' == typeof a) { + this._asserts.push(a); + return this; + } + if ('function' == typeof b) this.end(b); + if ('function' == typeof c) this.end(c); + + // status + if ('number' == typeof a) { + this._asserts.push(this._assertStatus.bind(this, a)); + // body + if ('function' != typeof b && arguments.length > 1) + this._asserts.push(this._assertBody.bind(this, b)); + return this; + } + + // header field + if ('string' == typeof b || 'number' == typeof b || b instanceof RegExp) { + this._asserts.push(this._assertHeader.bind(this, {name: ''+a, value: b})); + return this; + } + + // body + this._asserts.push(this._assertBody.bind(this, a)); + + return this; +}; + +/** + * Defer invoking superagent's `.end()` until + * the server is listening. + * + * @param {Function} fn + * @api public + */ + +Test.prototype.end = function(fn){ + var self = this; + var server = this._server; + var end = Request.prototype.end; + + end.call(this, function(err, res){ + if (server && server._handle) return server.close(assert); + + assert(); + + function assert(){ + self.assert(err, res, fn); + } + }); + + return this; +}; + +/** + * Perform assertions and invoke `fn(err, res)`. + * + * @param {?Error} resError + * @param {Response} res + * @param {Function} fn + * @api private + */ + +Test.prototype.assert = function(resError, res, fn){ + var error; + + // asserts + for (var i = 0; i < this._asserts.length && !error; ++i) { + error = this._assertFunction(this._asserts[i], res); + } + + // set unexpected superagent error if no other error has occurred. + if (!error && resError instanceof Error && + (!res || resError.status !== res.status)) + error = resError; + + fn.call(this, error || null, res); +}; + +/** + * Perform assertions on a response body and return an Error upon failure. + * + * @param {Mixed} body + * @param {Response} res + * @return {?Error} + * @api private + */ + +Test.prototype._assertBody = function(body, res) { + var isregexp = body instanceof RegExp; + // parsed + if ('object' == typeof body && !isregexp) { + try { + assert.deepEqual(body, res.body); + } catch (err) { + var a = util.inspect(body); + var b = util.inspect(res.body); + return error('expected ' + a + ' response body, got ' + b, body, res.body); + } + } else { + // string + if (body !== res.text) { + var a = util.inspect(body); + var b = util.inspect(res.text); + + // regexp + if (isregexp) { + if (!body.test(res.text)) { + return error('expected body ' + b + ' to match ' + body, body, res.body); + } + } else { + return error('expected ' + a + ' response body, got ' + b, body, res.body); + } + } + } +}; + +/** + * Perform assertions on a response header and return an Error upon failure. + * + * @param {Object} header + * @param {Response} res + * @return {?Error} + * @api private + */ + +Test.prototype._assertHeader = function(header, res) { + var field = header.name; + var actual = res.header[field.toLowerCase()]; + if (null == actual) return new Error('expected "' + field + '" header field'); + var fieldExpected = header.value; + if (fieldExpected == actual) return; + if (fieldExpected instanceof RegExp) { + if (!fieldExpected.test(actual)) return new Error('expected "' + field + '" matching ' + fieldExpected + ', got "' + actual + '"'); + } else { + return new Error('expected "' + field + '" of "' + fieldExpected + '", got "' + actual + '"'); + } +}; + +/** + * Perform assertions on the response status and return an Error upon failure. + * + * @param {Number} status + * @param {Response} res + * @return {?Error} + * @api private + */ + +Test.prototype._assertStatus = function(status, res) { + if (res.status !== status) { + var a = http.STATUS_CODES[status]; + var b = http.STATUS_CODES[res.status]; + return new Error('expected ' + status + ' "' + a + '", got ' + res.status + ' "' + b + '"'); + } +}; + +/** + * Performs an assertion by calling a function and return an Error upon failure. + * + * @param {Function} fn + * @param {Response} res + * @return {?Error} + * @api private + */ +Test.prototype._assertFunction = function(check, res) { + var err; + try { + err = check(res); + } catch(e) { + err = e; + } + if (err instanceof Error) return err; +}; + +/** + * Return an `Error` with `msg` and results properties. + * + * @param {String} msg + * @param {Mixed} expected + * @param {Mixed} actual + * @return {Error} + * @api private + */ + +function error(msg, expected, actual) { + var err = new Error(msg); + err.expected = expected; + err.actual = actual; + err.showDiff = true; + return err; +} diff --git a/node_modules/supertest/node_modules/superagent/.npmignore b/node_modules/supertest/node_modules/superagent/.npmignore new file mode 100644 index 0000000..90d998b --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/.npmignore @@ -0,0 +1,6 @@ +support +test +examples +*.sock +lib-cov +coverage.html diff --git a/node_modules/supertest/node_modules/superagent/.travis.yml b/node_modules/supertest/node_modules/superagent/.travis.yml new file mode 100644 index 0000000..0262c01 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/.travis.yml @@ -0,0 +1,18 @@ +sudo: false +language: node_js +node_js: + - "5.4" + - "4.2" + - "0.12" + - "0.10" + - "iojs" + +env: + global: + - SAUCE_USERNAME='shtylman-superagent' + - SAUCE_ACCESS_KEY='39a45464-cb1d-4b8d-aa1f-83c7c04fa673' + +matrix: + include: + - node_js: "4.2" + env: BROWSER=1 diff --git a/node_modules/supertest/node_modules/superagent/.zuul.yml b/node_modules/supertest/node_modules/superagent/.zuul.yml new file mode 100644 index 0000000..031c56a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/.zuul.yml @@ -0,0 +1,15 @@ +ui: mocha-bdd +server: ./test/support/server.js +browsers: + - name: chrome + version: latest + - name: firefox + version: latest + - name: safari + version: latest + - name: iphone + version: latest + - name: android + version: latest + - name: ie + version: 9..latest diff --git a/node_modules/supertest/node_modules/superagent/Contributing.md b/node_modules/supertest/node_modules/superagent/Contributing.md new file mode 100644 index 0000000..1eca592 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/Contributing.md @@ -0,0 +1,7 @@ +When submitting a PR, your chance of acceptance increases if you do the following: + +* Code style is consistent with existing in the file. +* Tests are passing (client and server). +* You add a test for the failing issue you are fixing. +* Code changes are focused on the area of discussion. +* Do not rebuild the distribution files or increment version numbers. diff --git a/node_modules/supertest/node_modules/superagent/History.md b/node_modules/supertest/node_modules/superagent/History.md new file mode 100644 index 0000000..553a5ea --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/History.md @@ -0,0 +1,554 @@ +# 1.8.2 (2016-03-20) + + * Fixed handling of HTTP status 204 with content-encoding: gzip (Andrew Shelton) + * Handling of FormData error events (scriptype) + * Fixed parsing of `vnd+json` MIME types (Kornel Lesiński) + * Aliased browser implementation of `.parse()` as `.serialize()` for forward compatibility + +# 1.8.1 (2016-03-14) + + * Fixed form-data incompatibility with IE9 + +# 1.8.0 (2016-03-09) + + * Extracted common code into request-base class (Peter Lyons) + * It does not affect the public API, but please let us know if you notice any plugins/subclasses breaking! + * Added option `{type:'auto'}` to `auth` method, which enables browser-native auth types (Jungle, Askar Yusupov) + * Added `responseType()` to set XHR `responseType` (chris) + * Switched to form-data for browserify-compatible `FormData` (Peter Lyons) + * Added `statusCode` to error response when JSON response is malformed (mattdell) + * Prevented TCP port conflicts in all tests (Peter Lyons) + * Updated form-data dependency + +# 1.7.2 (2016-01-26) + + * Fix case-sensitivity of header fields introduced by a4ddd6a. (Edward J. Jinotti) + * bump extend dependency, as former version did not contain any license information (Lukas Eipert) + +# 1.7.1 (2016-01-21) + + * Fixed a conflict with express when using npm 3.x (Glenn) + * Fixed redirects after a multipart/form-data POST request (cyclist2) + +# 1.7.0 (2016-01-18) + + * When attaching files, read default filename from the `File` object (JD Isaacks) + * Add `direction` property to `progress` events (Joseph Dykstra) + * Update component-emitter & formidable (Kornel Lesiński) + * Don't re-encode query string needlessly (Ruben Verborgh) + * ensure querystring is appended when doing `stream.pipe(request)` (Keith Grennan) + * change set header function, not call `this.request()` until call `this.end()` (vicanso) + * Add no-op `withCredentials` to Node API (markdalgleish) + * fix `delete` breaking on ie8 (kenjiokabe) + * Don't let request error override responses (Clay Reimann) + * Increased number of tests shared between node and client (Kornel Lesiński) + +# 1.6.0/1.6.1 (2015-12-09) + + * avoid misleading CORS error message + * added 'progress' event on file/form upload in Node (Olivier Lalonde) + * return raw response if the response parsing fails (Rei Colina) + * parse content-types ending with `+json` as JSON (Eiryyy) + * fix to avoid throwing errors on aborted requests (gjurgens) + * retain cookies on redirect when hosts match (Tom Conroy) + * added Bower manifest (Johnny Freeman) + * upgrade to latest cookiejar (Andy Burke) + +# 1.5.0 (2015-11-30) + + * encode array values as `key=1&key=2&key=3` etc... (aalpern, Davis Kim) + * avoid the error which is omitted from 'socket hang up' + * faster JSON parsing, handling of zlib errors (jbellenger) + * fix IE11 sends 'undefined' string if data was undefined (Vadim Goncharov) + * alias `del()` method as `delete()` (Aaron Krause) + * revert Request#parse since it was actually Response#parse + +# 1.4.0 (2015-09-14) + + * add Request#parse method to client library + * add missing statusCode in client response + * don't apply JSON heuristics if a valid parser is found + * fix detection of root object for webworkers + +# 1.3.0 (2015-08-05) + + * fix incorrect content-length of data set to buffer + * serialize request data takes into account charsets + * add basic promise support via a `then` function + +# 1.2.0 (2015-04-13) + + * add progress events to downlodas + * make usable in webworkers + * add support for 308 redirects + * update node-form-data dependency + * update to work in react native + * update node-mime dependency + +# 1.1.0 (2015-03-13) + + * Fix responseType checks without xhr2 and ie9 tests (rase-) + * errors have .status and .response fields if applicable (defunctzombie) + * fix end callback called before saving cookies (rase-) + +1.0.0 / 2015-03-08 +================== + + * All non-200 responses are treated as errors now. (The callback is called with an error when the response has a status < 200 or >= 300 now. In previous versions this would not have raised an error and the client would have to check the `res` object. See [#283](https://github.com/visionmedia/superagent/issues/283). + * keep timeouts intact across redirects (hopkinsth) + * handle falsy json values (themaarten) + * fire response events in browser version (Schoonology) + * getXHR exported in client version (KidsKilla) + * remove arity check on `.end()` callbacks (defunctzombie) + * avoid setting content-type for host objects (rexxars) + * don't index array strings in querystring (travisjeffery) + * fix pipe() with redirects (cyrilis) + * add xhr2 file download (vstirbu) + * set default response type to text/plain if not specified (warrenseine) + +0.21.0 / 2014-11-11 +================== + + * Trim text before parsing json (gjohnson) + * Update tests to express 4 (gaastonsr) + * Prevent double callback when error is thrown (pgn-vole) + * Fix missing clearTimeout (nickdima) + * Update debug (TooTallNate) + +0.20.0 / 2014-10-02 +================== + + * Add toJSON() to request and response instances. (yields) + * Prevent HEAD requests from getting parsed. (gjohnson) + * Update debug. (TooTallNate) + +0.19.1 / 2014-09-24 +================== + + * Fix basic auth issue when password is falsey value. (gjohnson) + +0.19.0 / 2014-09-24 +================== + + * Add unset() to browser. (shesek) + * Prefer XHR over ActiveX. (omeid) + * Catch parse errors. (jacwright) + * Update qs dependency. (wercker) + * Add use() to node. (Financial-Times) + * Add response text to errors. (yields) + * Don't send empty cookie headers. (undoZen) + * Don't parse empty response bodies. (DveMac) + * Use hostname when setting cookie host. (prasunsultania) + +0.18.2 / 2014-07-12 +================== + + * Handle parser errors. (kof) + * Ensure not to use default parsers when there is a user defined one. (kof) + +0.18.1 / 2014-07-05 +================== + + * Upgrade cookiejar dependency (juanpin) + * Support image mime types (nebulade) + * Make .agent chainable (kof) + * Upgrade debug (TooTallNate) + * Fix docs (aheckmann) + +0.18.0 / 2014-04-29 +=================== + +* Use "form-data" module for the multipart/form-data implementation. (TooTallNate) +* Add basic `field()` and `attach()` functions for HTML5 FormData. (TooTallNate) +* Deprecate `part()`. (TooTallNate) +* Set default user-agent header. (bevacqua) +* Add `unset()` method for removing headers. (bevacqua) +* Update cookiejar. (missinglink) +* Fix response error formatting. (shesek) + +0.17.0 / 2014-03-06 +=================== + + * supply uri malformed error to the callback (yields) + * add request event (yields) + * allow simple auth (yields) + * add request event (yields) + * switch to component/reduce (visionmedia) + * fix part content-disposition (mscdex) + * add browser testing via zuul (defunctzombie) + * adds request.use() (johntron) + +0.16.0 / 2014-01-07 +================== + + * remove support for 0.6 (superjoe30) + * fix CORS withCredentials (wejendorp) + * add "test" script (superjoe30) + * add request .accept() method (nickl-) + * add xml to mime types mappings (nickl-) + * fix parse body error on HEAD requests (gjohnson) + * fix documentation typos (matteofigus) + * fix content-type + charset (bengourley) + * fix null values on query parameters (cristiandouce) + +0.15.7 / 2013-10-19 +================== + + * pin should.js to 1.3.0 due to breaking change in 2.0.x + * fix browserify regression + +0.15.5 / 2013-10-09 +================== + + * add browser field to support browserify + * fix .field() value number support + +0.15.4 / 2013-07-09 +================== + + * node: add a Request#agent() function to set the http Agent to use + +0.15.3 / 2013-07-05 +================== + + * fix .pipe() unzipping on more recent nodes. Closes #240 + * fix passing an empty object to .query() no longer appends "?" + * fix formidable error handling + * update formidable + +0.15.2 / 2013-07-02 +================== + + * fix: emit 'end' when piping. + +0.15.1 / 2013-06-26 +================== + + * add try/catch around parseLinks + +0.15.0 / 2013-06-25 +================== + + * make `Response#toError()` have a more meaningful `message` + +0.14.9 / 2013-06-15 +================== + + * add debug()s to the node client + * add .abort() method to node client + +0.14.8 / 2013-06-13 +================== + + * set .agent = false always + * remove X-Requested-With. Closes #189 + +0.14.7 / 2013-06-06 +================== + + * fix unzip error handling + +0.14.6 / 2013-05-23 +================== + + * fix HEAD unzip bug + +0.14.5 / 2013-05-23 +================== + + * add flag to ensure the callback is __never__ invoked twice + +0.14.4 / 2013-05-22 +================== + + * add superagent.js build output + * update qs + * update emitter-component + * revert "add browser field to support browserify" see GH-221 + +0.14.3 / 2013-05-18 +================== + + * add browser field to support browserify + +0.14.2/ 2013-05-07 +================== + + * add host object check to fix serialization of File/Blobs etc as json + +0.14.1 / 2013-04-09 +================== + + * update qs + +0.14.0 / 2013-04-02 +================== + + * add client-side basic auth + * fix retaining of .set() header field case + +0.13.0 / 2013-03-13 +================== + + * add progress events to client + * add simple example + * add res.headers as alias of res.header for browser client + * add res.get(field) to node/client + +0.12.4 / 2013-02-11 +================== + + * fix get content-type even if can't get other headers in firefox. fixes #181 + +0.12.3 / 2013-02-11 +================== + + * add quick "progress" event support + +0.12.2 / 2013-02-04 +================== + + * add test to check if response acts as a readable stream + * add ReadableStream in the Response prototype. + * add test to assert correct redirection when the host changes in the location header. + * add default Accept-Encoding. Closes #155 + * fix req.pipe() return value of original stream for node parity. Closes #171 + * remove the host header when cleaning headers to properly follow the redirection. + +0.12.1 / 2013-01-10 +================== + + * add x-domain error handling + +0.12.0 / 2013-01-04 +================== + + * add header persistence on redirects + +0.11.0 / 2013-01-02 +================== + + * add .error Error object. Closes #156 + * add forcing of res.text removal for FF HEAD responses. Closes #162 + * add reduce component usage. Closes #90 + * move better-assert dep to development deps + +0.10.0 / 2012-11-14 +================== + + * add req.timeout(ms) support for the client + +0.9.10 / 2012-11-14 +================== + + * fix client-side .query(str) support + +0.9.9 / 2012-11-14 +================== + + * add .parse(fn) support + * fix socket hangup with dates in querystring. Closes #146 + * fix socket hangup "error" event when a callback of arity 2 is provided + +0.9.8 / 2012-11-03 +================== + + * add emission of error from `Request#callback()` + * add a better fix for nodes weird socket hang up error + * add PUT/POST/PATCH data support to client short-hand functions + * add .license property to component.json + * change client portion to build using component(1) + * fix GET body support [guille] + +0.9.7 / 2012-10-19 +================== + + * fix `.buffer()` `res.text` when no parser matches + +0.9.6 / 2012-10-17 +================== + + * change: use `this` when `window` is undefined + * update to new component spec [juliangruber] + * fix emission of "data" events for compressed responses without encoding. Closes #125 + +0.9.5 / 2012-10-01 +================== + + * add field name to .attach() + * add text "parser" + * refactor isObject() + * remove wtf isFunction() helper + +0.9.4 / 2012-09-20 +================== + + * fix `Buffer` responses [TooTallNate] + * fix `res.type` when a "type" param is present [TooTallNate] + +0.9.3 / 2012-09-18 +================== + + * remove __GET__ `.send()` == `.query()` special-case (__API__ change !!!) + +0.9.2 / 2012-09-17 +================== + + * add `.aborted` prop + * add `.abort()`. Closes #115 + +0.9.1 / 2012-09-07 +================== + + * add `.forbidden` response property + * add component.json + * change emitter-component to 0.0.5 + * fix client-side tests + +0.9.0 / 2012-08-28 +================== + + * add `.timeout(ms)`. Closes #17 + +0.8.2 / 2012-08-28 +================== + + * fix pathname relative redirects. Closes #112 + +0.8.1 / 2012-08-21 +================== + + * fix redirects when schema is specified + +0.8.0 / 2012-08-19 +================== + + * add `res.buffered` flag + * add buffering of text/*, json and forms only by default. Closes #61 + * add `.buffer(false)` cancellation + * add cookie jar support [hunterloftis] + * add agent functionality [hunterloftis] + +0.7.0 / 2012-08-03 +================== + + * allow `query()` to be called after the internal `req` has been created [tootallnate] + +0.6.0 / 2012-07-17 +================== + + * add `res.send('foo=bar')` default of "application/x-www-form-urlencoded" + +0.5.1 / 2012-07-16 +================== + + * add "methods" dep + * add `.end()` arity check to node callbacks + * fix unzip support due to weird node internals + +0.5.0 / 2012-06-16 +================== + + * Added "Link" response header field parsing, exposing `res.links` + +0.4.3 / 2012-06-15 +================== + + * Added 303, 305 and 307 as redirect status codes [slaskis] + * Fixed passing an object as the url + +0.4.2 / 2012-06-02 +================== + + * Added component support + * Fixed redirect data + +0.4.1 / 2012-04-13 +================== + + * Added HTTP PATCH support + * Fixed: GET / HEAD when following redirects. Closes #86 + * Fixed Content-Length detection for multibyte chars + +0.4.0 / 2012-03-04 +================== + + * Added `.head()` method [browser]. Closes #78 + * Added `make test-cov` support + * Added multipart request support. Closes #11 + * Added all methods that node supports. Closes #71 + * Added "response" event providing a Response object. Closes #28 + * Added `.query(obj)`. Closes #59 + * Added `res.type` (browser). Closes #54 + * Changed: default `res.body` and `res.files` to {} + * Fixed: port existing query-string fix (browser). Closes #57 + +0.3.0 / 2012-01-24 +================== + + * Added deflate/gzip support [guillermo] + * Added `res.type` (Content-Type void of params) + * Added `res.statusCode` to mirror node + * Added `res.headers` to mirror node + * Changed: parsers take callbacks + * Fixed optional schema support. Closes #49 + +0.2.0 / 2012-01-05 +================== + + * Added url auth support + * Added `.auth(username, password)` + * Added basic auth support [node]. Closes #41 + * Added `make test-docs` + * Added guillermo's EventEmitter. Closes #16 + * Removed `Request#data()` for SS, renamed to `send()` + * Removed `Request#data()` from client, renamed to `send()` + * Fixed array support. [browser] + * Fixed array support. Closes #35 [node] + * Fixed `EventEmitter#emit()` + +0.1.3 / 2011-10-25 +================== + + * Added error to callback + * Bumped node dep for 0.5.x + +0.1.2 / 2011-09-24 +================== + + * Added markdown documentation + * Added `request(url[, fn])` support to the client + * Added `qs` dependency to package.json + * Added options for `Request#pipe()` + * Added support for `request(url, callback)` + * Added `request(url)` as shortcut for `request.get(url)` + * Added `Request#pipe(stream)` + * Added inherit from `Stream` + * Added multipart support + * Added ssl support (node) + * Removed Content-Length field from client + * Fixed buffering, `setEncoding()` to utf8 [reported by stagas] + * Fixed "end" event when piping + +0.1.1 / 2011-08-20 +================== + + * Added `res.redirect` flag (node) + * Added redirect support (node) + * Added `Request#redirects(n)` (node) + * Added `.set(object)` header field support + * Fixed `Content-Length` support + +0.1.0 / 2011-08-09 +================== + + * Added support for multiple calls to `.data()` + * Added support for `.get(uri, obj)` + * Added GET `.data()` querystring support + * Added IE{6,7,8} support [alexyoung] + +0.0.1 / 2011-08-05 +================== + + * Initial commit + diff --git a/node_modules/supertest/node_modules/superagent/LICENSE b/node_modules/supertest/node_modules/superagent/LICENSE new file mode 100644 index 0000000..1b188ba --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca> + +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/supertest/node_modules/superagent/Makefile b/node_modules/supertest/node_modules/superagent/Makefile new file mode 100644 index 0000000..bac2be5 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/Makefile @@ -0,0 +1,57 @@ + +NODETESTS ?= test/*.js test/node/*.js +BROWSERTESTS ?= test/*.js test/client/*.js +REPORTER = spec + +all: superagent.js + +test: + @if [ "x$(BROWSER)" = "x" ]; then make test-node; else make test-browser; fi + +test-node: + @NODE_ENV=test NODE_TLS_REJECT_UNAUTHORIZED=0 ./node_modules/.bin/mocha \ + --require should \ + --reporter $(REPORTER) \ + --timeout 5000 \ + --growl \ + $(NODETESTS) + +test-cov: lib-cov + SUPERAGENT_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html + +test-browser: + ./node_modules/.bin/zuul -- $(BROWSERTESTS) + +test-browser-local: + ./node_modules/.bin/zuul --local 4000 -- $(BROWSERTESTS) + +lib-cov: + jscoverage lib lib-cov + +superagent.js: lib/node/*.js lib/node/parsers/*.js + @./node_modules/.bin/browserify \ + --standalone superagent \ + --outfile superagent.js . + +test-server: + @node test/server + +docs: index.html test-docs + +index.html: docs/index.md + marked < $< \ + | cat docs/head.html - docs/tail.html \ + > $@ + +docclean: + rm -f index.html test.html + +test-docs: + make test REPORTER=doc \ + | cat docs/head.html - docs/tail.html \ + > test.html + +clean: + rm -fr superagent.js components + +.PHONY: test-cov test docs test-docs clean test-browser-local diff --git a/node_modules/supertest/node_modules/superagent/Readme.md b/node_modules/supertest/node_modules/superagent/Readme.md new file mode 100644 index 0000000..eed472d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/Readme.md @@ -0,0 +1,116 @@ +# SuperAgent [](https://travis-ci.org/visionmedia/superagent) + +[](https://saucelabs.com/u/shtylman-superagent) + +SuperAgent is a small progressive __client-side__ HTTP request library, and __Node.js__ module with the same API, sporting many high-level HTTP client features. View the [docs](http://visionmedia.github.io/superagent/). + + + +## Installation + +node: + +``` +$ npm install superagent +``` + +component: + +``` +$ component install visionmedia/superagent +``` + +Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia/superagent/wiki/Superagent-for-Webpack) + +```js +request + .post('/api/pet') + .send({ name: 'Manny', species: 'cat' }) + .set('X-API-Key', 'foobar') + .set('Accept', 'application/json') + .end(function(err, res){ + // Calling the end function will send the request + }); +``` + +## Supported browsers + +Tested browsers: + +- Latest Android +- Latest Firefox +- Latest Chrome +- IE9 through latest +- Latest iPhone +- Latest Safari + +Even though IE9 is supported, a polyfill `window.btoa` is needed to use basic auth. + +# Plugins + +Superagent is easily extended via plugins. + +```js +var nocache = require('superagent-no-cache'); +var request = require('superagent'); +var prefix = require('superagent-prefix')('/static'); + +request +.get('/some-url') +.use(prefix) // Prefixes *only* this request +.use(nocache) // Prevents caching of *only* this request +.end(function(err, res){ + // Do something +}); +``` + +Existing plugins: + * [superagent-no-cache](https://github.com/johntron/superagent-no-cache) - prevents caching by including Cache-Control header + * [superagent-prefix](https://github.com/johntron/superagent-prefix) - prefixes absolute URLs (useful in test environment) + * [superagent-suffix](https://github.com/timneutkens1/superagent-suffix) - suffix URLs with a given path + * [superagent-mock](https://github.com/M6Web/superagent-mock) - simulate HTTP calls by returning data fixtures based on the requested URL + * [superagent-mocker](https://github.com/shuvalov-anton/superagent-mocker) — simulate REST API + * [superagent-cache](https://github.com/jpodwys/superagent-cache) - superagent with built-in, flexible caching + * [superagent-jsonapify](https://github.com/alex94puchades/superagent-jsonapify) - A lightweight [json-api](http://jsonapi.org/format/) client addon for superagent + * [superagent-serializer](https://github.com/zzarcon/superagent-serializer) - Converts server payload into different cases + * [superagent-promise-plugin](https://github.com/jomaxx/superagent-promise-plugin) - Shims req.end to return a promise when executed with no callback. + * [superagent-use](https://github.com/koenpunt/superagent-use) - A client addon to apply plugins to all requests. + +Please prefix your plugin with `superagent-*` so that it can easily be found by others. + +For superagent extensions such as couchdb and oauth visit the [wiki](https://github.com/visionmedia/superagent/wiki). + +## Running node tests + +Install dependencies: + +```shell +$ npm install +``` +Run em! + +```shell +$ make test +``` + +## Running browser tests + +Install dependencies: + +```shell +$ npm install +``` + +Start the test runner: + +```shell +$ make test-browser-local +``` + +Visit `http://localhost:4000/__zuul` in your browser. + +Edit tests and refresh your browser. You do not have to restart the test runner. + +## License + +MIT diff --git a/node_modules/supertest/node_modules/superagent/bower.json b/node_modules/supertest/node_modules/superagent/bower.json new file mode 100644 index 0000000..d01423c --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/bower.json @@ -0,0 +1,4 @@ +{ + "name": "superagent", + "main": "lib/client.js" +} diff --git a/node_modules/supertest/node_modules/superagent/component.json b/node_modules/supertest/node_modules/superagent/component.json new file mode 100644 index 0000000..f192fbd --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/component.json @@ -0,0 +1,21 @@ +{ + "name": "superagent", + "repo": "visionmedia/superagent", + "version": "1.8.3", + "description": "elegant & feature rich browser / node HTTP with a fluent API", + "keywords": [ + "http", + "ajax", + "request", + "agent" + ], + "scripts": [ + "lib/client.js" + ], + "main": "lib/client.js", + "dependencies": { + "component/emitter": "*", + "component/reduce": "*" + }, + "license": "MIT" +} diff --git a/node_modules/supertest/node_modules/superagent/docs/head.html b/node_modules/supertest/node_modules/superagent/docs/head.html new file mode 100644 index 0000000..4d3bc50 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/head.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <title>SuperAgent - Ajax with less suck</title> + <link rel="stylesheet" href="docs/style.css"> + <script src="docs/jquery.js"></script> + <script src="docs/jquery-ui.min.js"></script> + <script src="docs/highlight.js"></script> + <script src="docs/jquery.tocify.min.js"></script> + <script> + $(function(){ + $('#menu').tocify({ + selectors: 'h2', + hashGenerator: 'pretty' + }); + }); + </script> + </head> + <body> + <ul id="menu"></ul> + <div id="content"> diff --git a/node_modules/supertest/node_modules/superagent/docs/highlight.js b/node_modules/supertest/node_modules/superagent/docs/highlight.js new file mode 100644 index 0000000..b37eefb --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/highlight.js @@ -0,0 +1,17 @@ + +$(function(){ + $('code').each(function(){ + $(this).html(highlight($(this).text())); + }); +}); + +function highlight(js) { + return js + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/('.*?')/gm, '<span class="string">$1</span>') + .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>') + .replace(/(\d+)/gm, '<span class="number">$1</span>') + .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>') +}
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/images/bg.png b/node_modules/supertest/node_modules/superagent/docs/images/bg.png Binary files differnew file mode 100644 index 0000000..ca3d267 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/images/bg.png diff --git a/node_modules/supertest/node_modules/superagent/docs/index.md b/node_modules/supertest/node_modules/superagent/docs/index.md new file mode 100644 index 0000000..3dc9843 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/index.md @@ -0,0 +1,448 @@ + +# SuperAgent + + Super Agent is light-weight progressive ajax API crafted for flexibility, readability, and a low learning curve after being frustrated with many of the existing request APIs. It also works with Node.js! + + request + .post('/api/pet') + .send({ name: 'Manny', species: 'cat' }) + .set('X-API-Key', 'foobar') + .set('Accept', 'application/json') + .end(function(err, res){ + if (err || !res.ok) { + alert('Oh no! error'); + } else { + alert('yay got ' + JSON.stringify(res.body)); + } + }); + +## Test documentation + + The following [test documentation](docs/test.html) was generated with [Mocha's](http://visionmedia.github.com/mocha) "doc" reporter, and directly reflects the test suite. This provides an additional source of documentation. + +## Request basics + + A request can be initiated by invoking the appropriate method on the `request` object, then calling `.end()` to send the request. For example a simple GET request: + + request + .get('/search') + .end(function(err, res){ + + }); + + A method string may also be passed: + + request('GET', '/search').end(callback); + + The __node__ client may also provide absolute urls: + + request + .get('http://example.com/search') + .end(function(err, res){ + + }); + + __DELETE__, __HEAD__, __POST__, __PUT__ and other __HTTP__ verbs may also be used, simply change the method name: + + request + .head('/favicon.ico') + .end(function(err, res){ + + }); + + __DELETE__ is a special-case, as it's a reserved word, so the method is named `.del()`: + + request + .del('/user/1') + .end(function(err, res){ + + }); + + The HTTP method defaults to __GET__, so if you wish, the following is valid: + + request('/search', function(err, res){ + + }); + +## Setting header fields + + Setting header fields is simple, invoke `.set()` with a field name and value: + + request + .get('/search') + .set('API-Key', 'foobar') + .set('Accept', 'application/json') + .end(callback); + + You may also pass an object to set several fields in a single call: + + request + .get('/search') + .set({ 'API-Key': 'foobar', Accept: 'application/json' }) + .end(callback); + +## GET requests + + The `.query()` method accepts objects, which when used with the __GET__ method will form a query-string. The following will produce the path `/search?query=Manny&range=1..5&order=desc`. + + request + .get('/search') + .query({ query: 'Manny' }) + .query({ range: '1..5' }) + .query({ order: 'desc' }) + .end(function(err, res){ + + }); + + Or as a single object: + + request + .get('/search') + .query({ query: 'Manny', range: '1..5', order: 'desc' }) + .end(function(err, res){ + + }); + + The `.query()` method accepts strings as well: + + request + .get('/querystring') + .query('search=Manny&range=1..5') + .end(function(err, res){ + + }); + + Or joined: + + request + .get('/querystring') + .query('search=Manny') + .query('range=1..5') + .end(function(err, res){ + + }); + +## HEAD requests + +You can also use the `.query()` method for HEAD requests. The following will produce the path `/users?email=joe@smith.com`. + + request + .head('/users') + .query({ email: 'joe@smith.com' }) + .end(function(err, res){ + + }); + +## POST / PUT requests + + A typical JSON __POST__ request might look a little like the following, where we set the Content-Type header field appropriately, and "write" some data, in this case just a JSON string. + + request.post('/user') + .set('Content-Type', 'application/json') + .send('{"name":"tj","pet":"tobi"}') + .end(callback) + + Since JSON is undoubtably the most common, it's the _default_! The following example is equivalent to the previous. + + request.post('/user') + .send({ name: 'tj', pet: 'tobi' }) + .end(callback) + + Or using multiple `.send()` calls: + + request.post('/user') + .send({ name: 'tj' }) + .send({ pet: 'tobi' }) + .end(callback) + + By default sending strings will set the Content-Type to `application/x-www-form-urlencoded`, + multiple calls will be concatenated with `&`, here resulting in `name=tj&pet=tobi`: + + request.post('/user') + .send('name=tj') + .send('pet=tobi') + .end(callback); + + SuperAgent formats are extensible, however by default "json" and "form" are supported. To send the data as `application/x-www-form-urlencoded` simply invoke `.type()` with "form", where the default is "json". This request will POST the body "name=tj&pet=tobi". + + request.post('/user') + .type('form') + .send({ name: 'tj' }) + .send({ pet: 'tobi' }) + .end(callback) + + Note: "form" is aliased as "form-data" and "urlencoded" for backwards compat. + +## Setting the Content-Type + + The obvious solution is to use the `.set()` method: + + request.post('/user') + .set('Content-Type', 'application/json') + + As a short-hand the `.type()` method is also available, accepting + the canonicalized MIME type name complete with type/subtype, or + simply the extension name such as "xml", "json", "png", etc: + + request.post('/user') + .type('application/json') + + request.post('/user') + .type('json') + + request.post('/user') + .type('png') + +## Setting Accept + +In a similar fashion to the `.type()` method it is also possible to set the Accept header via the short hand method `.accept()`. Which references `request.types` as well allowing you to specify either the full canonicalized MIME type name as type/subtype, or the extension suffix form as "xml", "json", "png", etc for convenience: + + request.get('/user') + .accept('application/json') + + request.get('/user') + .accept('json') + + request.post('/user') + .accept('png') + +## Query strings + + `res.query(obj)` is a method which may be used to build up a query-string. For example populating `?format=json&dest=/login` on a __POST__: + + request + .post('/') + .query({ format: 'json' }) + .query({ dest: '/login' }) + .send({ post: 'data', here: 'wahoo' }) + .end(callback); + +## Parsing response bodies + + Super Agent will parse known response-body data for you, currently supporting _application/x-www-form-urlencoded_, _application/json_, and _multipart/form-data_. + +### JSON / Urlencoded + + The property `res.body` is the parsed object, for example if a request responded with the JSON string '{"user":{"name":"tobi"}}', `res.body.user.name` would be "tobi". Likewise the x-www-form-urlencoded value of "user[name]=tobi" would yield the same result. + +### Multipart + + The Node client supports _multipart/form-data_ via the [Formidable](https://github.com/felixge/node-formidable) module. When parsing multipart responses, the object `res.files` is also available to you. Suppose for example a request responds with the following multipart body: + + --whoop + Content-Disposition: attachment; name="image"; filename="tobi.png" + Content-Type: image/png + + ... data here ... + --whoop + Content-Disposition: form-data; name="name" + Content-Type: text/plain + + Tobi + --whoop-- + + You would have the values `res.body.name` provided as "Tobi", and `res.files.image` as a `File` object containing the path on disk, filename, and other properties. + +## Response properties + + Many helpful flags and properties are set on the `Response` object, ranging from the response text, parsed response body, header fields, status flags and more. + +### Response text + + The `res.text` property contains the unparsed response body string. This + property is always present for the client API, and only when the mime type + matches "text/*", "*/json", or "x-www-form-urlencoding" by default for node. The + reasoning is to conserve memory, as buffering text of large bodies such as multipart files or images is extremely inefficient. + + To force buffering see the "Buffering responses" section. + +### Response body + + Much like SuperAgent can auto-serialize request data, it can also automatically parse it. When a parser is defined for the Content-Type, it is parsed, which by default includes "application/json" and "application/x-www-form-urlencoded". The parsed object is then available via `res.body`. + +### Response header fields + + The `res.header` contains an object of parsed header fields, lowercasing field names much like node does. For example `res.header['content-length']`. + +### Response Content-Type + + The Content-Type response header is special-cased, providing `res.type`, which is void of the charset (if any). For example the Content-Type of "text/html; charset=utf8" will provide "text/html" as `res.type`, and the `res.charset` property would then contain "utf8". + +### Response status + + The response status flags help determine if the request was a success, among other useful information, making SuperAgent ideal for interacting with RESTful web services. These flags are currently defined as: + + var type = status / 100 | 0; + + // status / class + res.status = status; + res.statusType = type; + + // basics + res.info = 1 == type; + res.ok = 2 == type; + res.clientError = 4 == type; + res.serverError = 5 == type; + res.error = 4 == type || 5 == type; + + // sugar + res.accepted = 202 == status; + res.noContent = 204 == status || 1223 == status; + res.badRequest = 400 == status; + res.unauthorized = 401 == status; + res.notAcceptable = 406 == status; + res.notFound = 404 == status; + res.forbidden = 403 == status; + +## Aborting requests + + To abort requests simply invoke the `req.abort()` method. + +## Request timeouts + + A timeout can be applied by invoking `req.timeout(ms)`, after which an error + will be triggered. To differentiate between other errors the `err.timeout` property + is set to the `ms` value. __NOTE__ that this is a timeout applied to the request + and all subsequent redirects, not per request. + +## Basic authentication + + Basic auth is currently provided by the _node_ client in two forms, first via the URL as "user:pass": + + request.get('http://tobi:learnboost@local').end(callback); + + As well as via the `.auth()` method: + + request + .get('http://local') + .auth('tobi', 'learnboost') + .end(callback); + +## Following redirects + + By default up to 5 redirects will be followed, however you may specify this with the `res.redirects(n)` method: + + request + .get('/some.png') + .redirects(2) + .end(callback); + +## Piping data + + The Node client allows you to pipe data to and from the request. For example piping a file's contents as the request: + + var request = require('superagent') + , fs = require('fs'); + + var stream = fs.createReadStream('path/to/my.json'); + var req = request.post('/somewhere'); + req.type('json'); + stream.pipe(req); + + Or piping the response to a file: + + var request = require('superagent') + , fs = require('fs'); + + var stream = fs.createWriteStream('path/to/my.json'); + var req = request.get('/some.json'); + req.pipe(stream); + +## Multipart requests + + Super Agent is also great for _building_ multipart requests for which it provides methods `.attach()` and `.field()`. + +### Attaching files + + As mentioned a higher-level API is also provided, in the form of `.attach(name, [path], [filename])` and `.field(name, value)`. Attaching several files is simple, you can also provide a custom filename for the attachment, otherwise the basename of the attached file is used. + + request + .post('/upload') + .attach('avatar', 'path/to/tobi.png', 'user.png') + .attach('image', 'path/to/loki.png') + .attach('file', 'path/to/jane.png') + .end(callback); + +### Field values + + Much like form fields in HTML, you can set field values with the `.field(name, value)` method. Suppose you want to upload a few images with your name and email, your request might look something like this: + + request + .post('/upload') + .field('user[name]', 'Tobi') + .field('user[email]', 'tobi@learnboost.com') + .attach('image', 'path/to/tobi.png') + .end(callback); + +## Compression + + The node client supports compressed responses, best of all, you don't have to do anything! It just works. + +## Buffering responses + + To force buffering of response bodies as `res.text` you may invoke `req.buffer()`. To undo the default of buffering for text responses such + as "text/plain", "text/html" etc you may invoke `req.buffer(false)`. + + When buffered the `res.buffered` flag is provided, you may use this to + handle both buffered and unbuffered responses in the same callback. + +## CORS + + The `.withCredentials()` method enables the ability to send cookies + from the origin, however only when "Access-Control-Allow-Origin" is + _not_ a wildcard ("*"), and "Access-Control-Allow-Credentials" is "true". + + request + .get('http://localhost:4001/') + .withCredentials() + .end(function(err, res){ + assert(200 == res.status); + assert('tobi' == res.text); + next(); + }) + +## Error handling + +Your callback function will always be passed two arguments: error and response. If no error occurred, the first argument will be null: + + request + .post('/upload') + .attach('image', 'path/to/tobi.png') + .end(function(err, res){ + + }); + + An "error" event is also emitted, with you can listen for: + + request + .post('/upload') + .attach('image', 'path/to/tobi.png') + .on('error', handle) + .end(function(err, res){ + + }); + + Note that a 4xx or 5xx response with super agent **are** considered an error by default. For example if you get a 500 or 403 response, this status information will be available via `err.status`. Errors from such responses also contain an `err.response` field with all of the properties mentioned in "Response properties". The library behaves in this way to handle the common case of wanting success responses and treating HTTP error status codes as errors while still allowing for custom logic around specific error conditions. + + Network failures, timeouts, and other errors that produce no response will contain no `err.status` or `err.response` fields. + + If you wish to handle 404 or other HTTP error responses, you can query the `err.status` property. + When an HTTP error occurs (4xx or 5xx response) the `res.error` property is an `Error` object, + this allows you to perform checks such as: + + if (err && err.status === 404) { + alert('oh no ' + res.body.message); + } + else if (err) { + // all other error types we handle generically + } + +## Generator support + +Superagent now supports easier control flow using generators. By using a generator control flow +like [co](https://github.com/tj/co) or a web framework like [koa](https://github.com/koajs/koa), +you can `yield` on any superagent method: + + var res = yield request + .get('http://local') + .auth('tobi', 'learnboost') diff --git a/node_modules/supertest/node_modules/superagent/docs/jquery-ui.min.js b/node_modules/supertest/node_modules/superagent/docs/jquery-ui.min.js new file mode 100644 index 0000000..932f867 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/jquery-ui.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.11.4 - 2015-11-20 +* http://jqueryui.com +* Includes: widget.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){var t=0,i=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var s,n,a=i.call(arguments,1),o=0,r=a.length;r>o;o++)for(s in a[o])n=a[o][s],a[o].hasOwnProperty(s)&&void 0!==n&&(t[s]=e.isPlainObject(n)?e.isPlainObject(t[s])?e.widget.extend({},t[s],n):e.widget.extend({},n):n);return t},e.widget.bridge=function(t,s){var n=s.prototype.widgetFullName||t;e.fn[t]=function(a){var o="string"==typeof a,r=i.call(arguments,1),h=this;return o?this.each(function(){var i,s=e.data(this,n);return"instance"===a?(h=s,!1):s?e.isFunction(s[a])&&"_"!==a.charAt(0)?(i=s[a].apply(s,r),i!==s&&void 0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+a+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+a+"'")}):(r.length&&(a=e.widget.extend.apply(null,[a].concat(r))),this.each(function(){var t=e.data(this,n);t?(t.option(a||{}),t._init&&t._init()):e.data(this,n,new s(a,this))})),h}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(i,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=t++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget});
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/jquery.js b/node_modules/supertest/node_modules/superagent/docs/jquery.js new file mode 100644 index 0000000..d2424e6 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7 jquery.com | jquery.org/license */ +(function(a,b){function cA(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cx(a){if(!cm[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cn||(cn=c.createElement("iframe"),cn.frameBorder=cn.width=cn.height=0),b.appendChild(cn);if(!co||!cn.createElement)co=(cn.contentWindow||cn.contentDocument).document,co.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),co.close();d=co.createElement(a),co.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cn)}cm[a]=e}return cm[a]}function cw(a,b){var c={};f.each(cs.concat.apply([],cs.slice(0,b)),function(){c[this]=a});return c}function cv(){ct=b}function cu(){setTimeout(cv,0);return ct=f.now()}function cl(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ck(){try{return new a.XMLHttpRequest}catch(b){}}function ce(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cd(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function cc(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bG.test(a)?d(a,e):cc(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)cc(a+"["+e+"]",b[e],c,d);else d(a,b)}function cb(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function ca(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bV,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=ca(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=ca(a,c,d,e,"*",g));return l}function b_(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bR),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bE(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bz:bA;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bB(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function br(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bi,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bq(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bp(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bp)}function bp(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bo(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bn(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bm(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bl(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a){var b=Y.split(" "),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(){return!0}function M(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.add(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return a!=null&&m.test(a)&&!isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(I)return I.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())}),typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return e});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){return i.done.apply(i,arguments).fail.apply(i,arguments)},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,unknownElems:!!a.getElementsByTagName("nav").length,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",enctype:!!c.createElement("form").enctype,submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.lastChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-999px",top:"-999px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;f(function(){var a,b,d,e,g,h,i=1,j="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",l="visibility:hidden;border:0;",n="style='"+j+"border:5px solid #000;padding:0;'",p="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>";m=c.getElementsByTagName("body")[0];!m||(a=c.createElement("div"),a.style.cssText=l+"width:0;height:0;position:static;top:0;margin-top:"+i+"px",m.insertBefore(a,m.firstChild),o=c.createElement("div"),o.style.cssText=j+l,o.innerHTML=p,a.appendChild(o),b=o.firstChild,d=b.firstChild,g=b.nextSibling.firstChild.firstChild,h={doesNotAddBorder:d.offsetTop!==5,doesAddBorderForTableAndCells:g.offsetTop===5},d.style.position="fixed",d.style.top="20px",h.fixedPosition=d.offsetTop===20||d.offsetTop===15,d.style.position=d.style.top="",b.style.overflow="hidden",b.style.position="relative",h.subtractsBorderForOverflowNotVisible=d.offsetTop===-5,h.doesNotIncludeMarginInBodyOffset=m.offsetTop!==i,m.removeChild(a),o=a=null,f.extend(k,h))}),o.innerHTML="",n.removeChild(o),o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[f.expando]:a[f.expando]&&f.expando,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[f.expando]=n=++f.uuid:n=f.expando),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[f.expando]:f.expando;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)?b=b:b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" "));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];if(!arguments.length){if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}return b}e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!a||j===3||j===8||j===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g},removeAttr:function(a,b){var c,d,e,g,h=0;if(a.nodeType===1){d=(b||"").split(p),g=d.length;for(;h<g;h++)e=d[h].toLowerCase(),c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1)}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return b;h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/\.(.*)$/,A=/^(?:textarea|input|select)$/i,B=/\./g,C=/ /g,D=/[^\w\s.|`]/g,E=/^([^\.]*)?(?:\.(.+))?$/,F=/\bhover(\.\S+)?/,G=/^key/,H=/^(?:mouse|contextmenu)|click/,I=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,J=function(a){var b=I.exec(a);b&& +(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},K=function(a,b){return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||a.id===b[2])&&(!b[3]||b[3].test(a.className))},L=function(a){return f.event.special.hover?a:a.replace(F,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=L(c).split(" ");for(k=0;k<c.length;k++){l=E.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,namespace:n.join(".")},p),g&&(o.quick=J(g),!o.quick&&f.expr.match.POS.test(g)&&(o.isPositional=!0)),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d){var e=f.hasData(a)&&f._data(a),g,h,i,j,k,l,m,n,o,p,q;if(!!e&&!!(m=e.events)){b=L(b||"").split(" ");for(g=0;g<b.length;g++){h=E.exec(b[g])||[],i=h[1],j=h[2];if(!i){j=j?"."+j:"";for(l in m)f.event.remove(a,l+j,c,d);return}n=f.event.special[i]||{},i=(d?n.delegateType:n.bindType)||i,p=m[i]||[],k=p.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;if(c||j||d||n.remove)for(l=0;l<p.length;l++){q=p[l];if(!c||c.guid===q.guid)if(!j||j.test(q.namespace))if(!d||d===q.selector||d==="**"&&q.selector)p.splice(l--,1),q.selector&&p.delegateCount--,n.remove&&n.remove.call(a,q)}else p.length=0;p.length===0&&k!==p.length&&((!n.teardown||n.teardown.call(a,j)===!1)&&f.removeEvent(a,i,e.handle),delete m[i])}f.isEmptyObject(m)&&(o=e.handle,o&&(o.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"",(g||!e)&&c.preventDefault();if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,n=null;for(m=e.parentNode;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length;l++){m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d);if(c.isPropagationStopped())break}c.type=h,c.isDefaultPrevented()||(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=(f.event.special[c.type]||{}).handle,j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click"))for(m=c.target;m!=this;m=m.parentNode||this){o={},q=[];for(k=0;k<e;k++)r=d[k],s=r.selector,t=o[s],r.isPositional?t=(t||(o[s]=f(s))).index(m)>=0:t===b&&(t=o[s]=r.quick?K(m,r.quick):f(m).is(s)),t&&q.push(r);q.length&&j.push({elem:m,matches:q})}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){p=j[k],c.currentTarget=p.elem;for(l=0;l<p.matches.length&&!c.isImmediatePropagationStopped();l++){r=p.matches[l];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=(i||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},focus:{delegateType:"focusin",noBubble:!0},blur:{delegateType:"focusout",noBubble:!0},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?N:M):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=N;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=N;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=N,this.stopPropagation()},isDefaultPrevented:M,isPropagationStopped:M,isImmediatePropagationStopped:M},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]=f.event.special[b]={delegateType:b,bindType:b,handle:function(a){var b=this,c=a.relatedTarget,d=a.handleObj,e=d.selector,g,h;if(!c||d.origType===a.type||c!==b&&!f.contains(b,c))g=a.type,a.type=d.origType,h=d.handler.apply(this,arguments),a.type=g;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(A.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;A.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return A.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=M;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=M);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),G.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),H.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw"Syntax error, unrecognized expression: "+a};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?T.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",Z=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,_=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,ba=/<([\w:]+)/,bb=/<tbody/i,bc=/<|&#?\w+;/,bd=/<(?:script|style)/i,be=/<(?:script|object|embed|option|style)/i,bf=new RegExp("<(?:"+Y.replace(" ","|")+")","i"),bg=/checked\s*(?:[^=]|=\s*.checked.)/i,bh=/\/(java|ecma)script/i,bi=/^\s*<!(?:\[CDATA\[|\-\-)/,bj={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bk=X(c);bj.optgroup=bj.option,bj.tbody=bj.tfoot=bj.colgroup=bj.caption=bj.thead,bj.th=bj.td,f.support.htmlSerialize||(bj._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after" +,arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Z,""):null;if(typeof a=="string"&&!bd.test(a)&&(f.support.leadingWhitespace||!$.test(a))&&!bj[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(_,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bg.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bl(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,br)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!be.test(j)&&(f.support.checkClone||!bg.test(j))&&!f.support.unknownElems&&bf.test(j)&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bn(a,d),e=bo(a),g=bo(d);for(h=0;e[h];++h)g[h]&&bn(e[h],g[h])}if(b){bm(a,d);if(c){e=bo(a),g=bo(d);for(h=0;e[h];++h)bm(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bc.test(k))k=b.createTextNode(k);else{k=k.replace(_,"<$1></$2>");var l=(ba.exec(k)||["",""])[1].toLowerCase(),m=bj[l]||bj._default,n=m[0],o=b.createElement("div");b===c?bk.appendChild(o):X(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=bb.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&$.test(k)&&o.insertBefore(b.createTextNode($.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bq(k[i]);else bq(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bh.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bs=/alpha\([^)]*\)/i,bt=/opacity=([^)]*)/,bu=/([A-Z]|^ms)/g,bv=/^-?\d+(?:px)?$/i,bw=/^-?\d/,bx=/^([\-+])=([\-+.\de]+)/,by={position:"absolute",visibility:"hidden",display:"block"},bz=["Left","Right"],bA=["Top","Bottom"],bB,bC,bD;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bB(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bx.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bB)return bB(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bE(a,b,d);f.swap(a,by,function(){e=bE(a,b,d)});return e}},set:function(a,b){if(!bv.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bt.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bs,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bs.test(g)?g.replace(bs,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bB(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bC=function(a,c){var d,e,g;c=c.replace(bu,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bD=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bv.test(f)&&bw.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bB=bC||bD,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bF=/%20/g,bG=/\[\]$/,bH=/\r?\n/g,bI=/#.*$/,bJ=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bK=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bL=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bM=/^(?:GET|HEAD)$/,bN=/^\/\//,bO=/\?/,bP=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bQ=/^(?:select|textarea)/i,bR=/\s+/,bS=/([?&])_=[^&]*/,bT=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bU=f.fn.load,bV={},bW={},bX,bY,bZ=["*/"]+["*"];try{bX=e.href}catch(b$){bX=c.createElement("a"),bX.href="",bX=bX.href}bY=bT.exec(bX.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bU)return bU.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bP,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bQ.test(this.nodeName)||bK.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bH,"\r\n")}}):{name:b.name,value:c.replace(bH,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?cb(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),cb(a,b);return a},ajaxSettings:{url:bX,isLocal:bL.test(bY[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bZ},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:b_(bV),ajaxTransport:b_(bW),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cd(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=ce(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bJ.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bI,"").replace(bN,bY[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bR),d.crossDomain==null&&(r=bT.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bY[1]&&r[2]==bY[2]&&(r[3]||(r[1]==="http:"?80:443))==(bY[3]||(bY[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),ca(bV,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bM.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bO.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bS,"$1_="+x);d.url=y+(y===d.url?(bO.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bZ+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=ca(bW,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)cc(g,a[g],c,e);return d.join("&").replace(bF,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cf=f.now(),cg=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cf++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cg.test(b.url)||e&&cg.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cg,l),b.url===j&&(e&&(k=k.replace(cg,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ch=a.ActiveXObject?function(){for(var a in cj)cj[a](0,1)}:!1,ci=0,cj;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ck()||cl()}:ck,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ch&&delete cj[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++ci,ch&&(cj||(cj={},f(a).unload(ch)),cj[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cm={},cn,co,cp=/^(?:toggle|show|hide)$/,cq=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cr,cs=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],ct;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cw("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cx(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cw("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cw("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cx(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cp.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=cq.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cw("show",1),slideUp:cw("hide",1),slideToggle:cw("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=ct||cu(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cr&&(cr=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=ct||cu(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cr),cr=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now))}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cy=/^t(?:able|d|h)$/i,cz=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cA(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cy.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cz.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cz.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cA(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cA(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/jquery.tocify.min.js b/node_modules/supertest/node_modules/superagent/docs/jquery.tocify.min.js new file mode 100755 index 0000000..0fc0442 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/jquery.tocify.min.js @@ -0,0 +1,4 @@ +/*! jquery.tocify - v1.9.0 - 2013-10-01 +* http://gregfranko.com/jquery.tocify.js/ +* Copyright (c) 2013 Greg Franko; Licensed MIT*/ +(function(e){"use strict";e(window.jQuery,window,document)})(function(e,t,s){"use strict";var i="tocify",o="tocify-focus",n="tocify-hover",a="tocify-hide",l="tocify-header",h="."+l,r="tocify-subheader",d="."+r,c="tocify-item",f="."+c,u="tocify-extend-page",p="."+u;e.widget("toc.tocify",{version:"1.9.0",options:{context:"body",ignoreSelector:null,selectors:"h1, h2, h3",showAndHide:!0,showEffect:"slideDown",showEffectSpeed:"medium",hideEffect:"slideUp",hideEffectSpeed:"medium",smoothScroll:!0,smoothScrollSpeed:"medium",scrollTo:0,showAndHideOnScroll:!0,highlightOnScroll:!0,highlightOffset:40,theme:"bootstrap",extendPage:!0,extendPageOffset:100,history:!0,scrollHistory:!1,hashGenerator:"compact",highlightDefault:!0},_create:function(){var s=this;s.extendPageScroll=!0,s.items=[],s._generateToc(),s._addCSSClasses(),s.webkit=function(){for(var e in t)if(e&&-1!==e.toLowerCase().indexOf("webkit"))return!0;return!1}(),s._setEventHandlers(),e(t).load(function(){s._setActiveElement(!0),e("html, body").promise().done(function(){setTimeout(function(){s.extendPageScroll=!1},0)})})},_generateToc:function(){var t,s,o=this,n=o.options.ignoreSelector;return t=-1!==this.options.selectors.indexOf(",")?e(this.options.context).find(this.options.selectors.replace(/ /g,"").substr(0,this.options.selectors.indexOf(","))):e(this.options.context).find(this.options.selectors.replace(/ /g,"")),t.length?(o.element.addClass(i),t.each(function(t){e(this).is(n)||(s=e("<ul/>",{id:l+t,"class":l}).append(o._nestElements(e(this),t)),o.element.append(s),e(this).nextUntil(this.nodeName.toLowerCase()).each(function(){0===e(this).find(o.options.selectors).length?e(this).filter(o.options.selectors).each(function(){e(this).is(n)||o._appendSubheaders.call(this,o,s)}):e(this).find(o.options.selectors).each(function(){e(this).is(n)||o._appendSubheaders.call(this,o,s)})}))}),undefined):(o.element.addClass(a),undefined)},_setActiveElement:function(e){var s=this,i=t.location.hash.substring(1),o=s.element.find('li[data-unique="'+i+'"]');return i.length?(s.element.find("."+s.focusClass).removeClass(s.focusClass),o.addClass(s.focusClass),s.options.showAndHide&&o.click()):(s.element.find("."+s.focusClass).removeClass(s.focusClass),!i.length&&e&&s.options.highlightDefault&&s.element.find(f).first().addClass(s.focusClass)),s},_nestElements:function(t,s){var i,o,n;return i=e.grep(this.items,function(e){return e===t.text()}),i.length?this.items.push(t.text()+s):this.items.push(t.text()),n=this._generateHashValue(i,t,s),o=e("<li/>",{"class":c,"data-unique":n}).append(e("<a/>",{text:t.text()})),t.before(e("<div/>",{name:n,"data-unique":n})),o},_generateHashValue:function(e,t,s){var i="",o=this.options.hashGenerator;if("pretty"===o){for(i=t.text().toLowerCase().replace(/\s/g,"-");i.indexOf("--")>-1;)i=i.replace(/--/g,"-");for(;i.indexOf(":-")>-1;)i=i.replace(/:-/g,"-")}else i="function"==typeof o?o(t.text(),t):t.text().replace(/\s/g,"");return e.length&&(i+=""+s),i},_appendSubheaders:function(t,s){var i=e(this).index(t.options.selectors),o=e(t.options.selectors).eq(i-1),n=+e(this).prop("tagName").charAt(1),a=+o.prop("tagName").charAt(1);a>n?t.element.find(d+"[data-tag="+n+"]").last().append(t._nestElements(e(this),i)):n===a?s.find(f).last().after(t._nestElements(e(this),i)):s.find(f).last().after(e("<ul/>",{"class":r,"data-tag":n})).next(d).append(t._nestElements(e(this),i))},_setEventHandlers:function(){var i=this;this.element.on("click.tocify","li",function(){if(i.options.history&&(t.location.hash=e(this).attr("data-unique")),i.element.find("."+i.focusClass).removeClass(i.focusClass),e(this).addClass(i.focusClass),i.options.showAndHide){var s=e('li[data-unique="'+e(this).attr("data-unique")+'"]');i._triggerShow(s)}i._scrollTo(e(this))}),this.element.find("li").on({"mouseenter.tocify":function(){e(this).addClass(i.hoverClass),e(this).css("cursor","pointer")},"mouseleave.tocify":function(){"bootstrap"!==i.options.theme&&e(this).removeClass(i.hoverClass)}}),(i.options.extendPage||i.options.highlightOnScroll||i.options.scrollHistory||i.options.showAndHideOnScroll)&&e(t).on("scroll.tocify",function(){e("html, body").promise().done(function(){var o,n,a,l,h=e(t).scrollTop(),r=e(t).height(),d=e(s).height(),c=e("body")[0].scrollHeight;if(i.options.extendPage&&(i.webkit&&h>=c-r-i.options.extendPageOffset||!i.webkit&&r+h>d-i.options.extendPageOffset)&&!e(p).length){if(n=e('div[data-unique="'+e(f).last().attr("data-unique")+'"]'),!n.length)return;a=n.offset().top,e(i.options.context).append(e("<div />",{"class":u,height:Math.abs(a-h)+"px","data-unique":u})),i.extendPageScroll&&(l=i.element.find("li.active"),i._scrollTo(e('div[data-unique="'+l.attr("data-unique")+'"]')))}setTimeout(function(){var s,n=null,a=null,l=e(i.options.context).find("div[data-unique]");l.each(function(t){var s=Math.abs((e(this).next().length?e(this).next():e(this)).offset().top-h-i.options.highlightOffset);return null==n||n>s?(n=s,a=t,undefined):!1}),s=e(l[a]).attr("data-unique"),o=e('li[data-unique="'+s+'"]'),i.options.highlightOnScroll&&o.length&&(i.element.find("."+i.focusClass).removeClass(i.focusClass),o.addClass(i.focusClass)),i.options.scrollHistory&&t.location.hash!=="#"+s&&t.location.replace("#"+s),i.options.showAndHideOnScroll&&i.options.showAndHide&&i._triggerShow(o,!0)},0)})})},show:function(t){var s=this;if(!t.is(":visible"))switch(t.find(d).length||t.parent().is(h)||t.parent().is(":visible")?t.children(d).length||t.parent().is(h)||(t=t.closest(d)):t=t.parents(d).add(t),s.options.showEffect){case"none":t.show();break;case"show":t.show(s.options.showEffectSpeed);break;case"slideDown":t.slideDown(s.options.showEffectSpeed);break;case"fadeIn":t.fadeIn(s.options.showEffectSpeed);break;default:t.show()}return t.parent().is(h)?s.hide(e(d).not(t)):s.hide(e(d).not(t.closest(h).find(d).not(t.siblings()))),s},hide:function(e){var t=this;switch(t.options.hideEffect){case"none":e.hide();break;case"hide":e.hide(t.options.hideEffectSpeed);break;case"slideUp":e.slideUp(t.options.hideEffectSpeed);break;case"fadeOut":e.fadeOut(t.options.hideEffectSpeed);break;default:e.hide()}return t},_triggerShow:function(e,t){var s=this;return e.parent().is(h)||e.next().is(d)?s.show(e.next(d),t):e.parent().is(d)&&s.show(e.parent(),t),s},_addCSSClasses:function(){return"jqueryui"===this.options.theme?(this.focusClass="ui-state-default",this.hoverClass="ui-state-hover",this.element.addClass("ui-widget").find(".toc-title").addClass("ui-widget-header").end().find("li").addClass("ui-widget-content")):"bootstrap"===this.options.theme?(this.element.find(h+","+d).addClass("nav nav-list"),this.focusClass="active"):(this.focusClass=o,this.hoverClass=n),this},setOption:function(){e.Widget.prototype._setOption.apply(this,arguments)},setOptions:function(){e.Widget.prototype._setOptions.apply(this,arguments)},_scrollTo:function(t){var s=this,i=s.options.smoothScroll||0,o=s.options.scrollTo,n=e('div[data-unique="'+t.attr("data-unique")+'"]');return n.length?(e("html, body").promise().done(function(){e("html, body").animate({scrollTop:n.offset().top-(e.isFunction(o)?o.call():o)+"px"},{duration:i})}),s):s}})});
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/style.css b/node_modules/supertest/node_modules/superagent/docs/style.css new file mode 100644 index 0000000..9ca0e5c --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/style.css @@ -0,0 +1,81 @@ +body { + padding: 40px 80px; + font: 14px/1.5 "Helvetica Neue", Helvetica, sans-serif; + background: #181818 url(images/bg.png); + text-align: center; +} + +#content { + margin: 0 auto; + padding: 10px 40px; + text-align: left; + background: white; + width: 50%; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + -webkit-box-shadow: 0 2px 5px 0 black; +} + +#menu { + font-size: 13px; + margin: 0; + padding: 0; + text-align: left; + position: fixed; + top: 15px; + left: 15px; +} + +#menu ul { + margin: 0; + padding: 0; +} + +#menu li { + list-style: none; +} + +#menu a { + color: rgba(255,255,255,.5); + text-decoration: none; +} + +#menu a:hover { + color: white; +} + +#menu .active a { + color: white; +} + +pre { + padding: 10px; +} + +code { + font: 12px/1 monaco, monospace; +} + +p code { + border: 1px solid #ECEA75; + padding: 1px 3px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + background: #FDFCD1; +} + +pre { + padding: 20px 25px; + border: 1px solid #ddd; + -webkit-box-shadow: inset 0 0 5px #eee; + -moz-box-shadow: inset 0 0 5px #eee; + box-shadow: inset 0 0 5px #eee; +} + +code .comment { color: #ddd } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD }
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/tail.html b/node_modules/supertest/node_modules/superagent/docs/tail.html new file mode 100644 index 0000000..09994c9 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/tail.html @@ -0,0 +1,4 @@ + </div> + <a href="http://github.com/visionmedia/superagent"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png" alt="Fork me on GitHub"></a> + </body> +</html>
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/docs/test.html b/node_modules/supertest/node_modules/superagent/docs/test.html new file mode 100644 index 0000000..3dff111 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/docs/test.html @@ -0,0 +1,2082 @@ +<!DOCTYPE html> +<html> + <head> + <title>SuperAgent - Ajax with less suck</title> + <link rel="stylesheet" href="style.css"> + <script src="jquery.js"></script> + <script src="jquery-ui.min.js"></script> + <script src="highlight.js"></script> + <script src="jquery.tocify.min.js"></script> + <script> + $(function(){ + $('#menu').tocify({ + selectors: 'h2', + hashGenerator: 'pretty' + }); + }); + </script> + </head> + <body> + <ul id="menu"></ul> + <div id="content"> <section class="suite"> + <h1>request</h1> + <dl> + <section class="suite"> + <h1>with a callback</h1> + <dl> + <dt>should invoke .end()</dt> + <dd><pre><code>request +.get(uri + '/login', function(err, res){ + assert(res.status == 200); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.end()</h1> + <dl> + <dt>should issue a request</dt> + <dd><pre><code>request +.get(uri + '/login') +.end(function(err, res){ + assert(res.status == 200); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.error</h1> + <dl> + <dt>should should be an Error object</dt> + <dd><pre><code>request +.get(uri + '/error') +.end(function(err, res){ + if (NODE) { + res.error.message.should.equal('cannot GET /error (500)'); + } + else { + res.error.message.should.equal('cannot GET ' + uri + '/error (500)'); + } + assert(res.error.status === 500); + assert(err, 'should have an error for 500'); + assert.equal(err.message, 'Internal Server Error'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.header</h1> + <dl> + <dt>should be an object</dt> + <dd><pre><code>request +.get(uri + '/login') +.end(function(err, res){ + assert('Express' == res.header['x-powered-by']); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.charset</h1> + <dl> + <dt>should be set when present</dt> + <dd><pre><code>request +.get(uri + '/login') +.end(function(err, res){ + res.charset.should.equal('utf-8'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.statusType</h1> + <dl> + <dt>should provide the first digit</dt> + <dd><pre><code>request +.get(uri + '/login') +.end(function(err, res){ + assert(!err, 'should not have an error for success responses'); + assert(200 == res.status); + assert(2 == res.statusType); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.type</h1> + <dl> + <dt>should provide the mime-type void of params</dt> + <dd><pre><code>request +.get(uri + '/login') +.end(function(err, res){ + res.type.should.equal('text/html'); + res.charset.should.equal('utf-8'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.set(field, val)</h1> + <dl> + <dt>should set the header field</dt> + <dd><pre><code>request +.post(uri + '/echo') +.set('X-Foo', 'bar') +.set('X-Bar', 'baz') +.end(function(err, res){ + assert('bar' == res.header['x-foo']); + assert('baz' == res.header['x-bar']); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.set(obj)</h1> + <dl> + <dt>should set the header fields</dt> + <dd><pre><code>request +.post(uri + '/echo') +.set({ 'X-Foo': 'bar', 'X-Bar': 'baz' }) +.end(function(err, res){ + assert('bar' == res.header['x-foo']); + assert('baz' == res.header['x-bar']); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.type(str)</h1> + <dl> + <dt>should set the Content-Type</dt> + <dd><pre><code>request +.post(uri + '/echo') +.type('text/x-foo') +.end(function(err, res){ + res.header['content-type'].should.equal('text/x-foo'); + done(); +});</code></pre></dd> + <dt>should map "json"</dt> + <dd><pre><code>request +.post(uri + '/echo') +.type('json') +.send('{"a": 1}') +.end(function(err, res){ + res.should.be.json; + done(); +});</code></pre></dd> + <dt>should map "html"</dt> + <dd><pre><code>request +.post(uri + '/echo') +.type('html') +.end(function(err, res){ + res.header['content-type'].should.equal('text/html'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.accept(str)</h1> + <dl> + <dt>should set Accept</dt> + <dd><pre><code>request +.get(uri + '/echo') +.accept('text/x-foo') +.end(function(err, res){ + res.header['accept'].should.equal('text/x-foo'); + done(); +});</code></pre></dd> + <dt>should map "json"</dt> + <dd><pre><code>request +.get(uri + '/echo') +.accept('json') +.end(function(err, res){ + res.header['accept'].should.equal('application/json'); + done(); +});</code></pre></dd> + <dt>should map "xml"</dt> + <dd><pre><code>request +.get(uri + '/echo') +.accept('xml') +.end(function(err, res){ + res.header['accept'].should.equal('application/xml'); + done(); +});</code></pre></dd> + <dt>should map "html"</dt> + <dd><pre><code>request +.get(uri + '/echo') +.accept('html') +.end(function(err, res){ + res.header['accept'].should.equal('text/html'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.send(str)</h1> + <dl> + <dt>should write the string</dt> + <dd><pre><code>request +.post(uri + '/echo') +.type('json') +.send('{"name":"tobi"}') +.end(function(err, res){ + res.text.should.equal('{"name":"tobi"}'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.send(Object)</h1> + <dl> + <dt>should default to json</dt> + <dd><pre><code>request +.post(uri + '/echo') +.send({ name: 'tobi' }) +.end(function(err, res){ + res.should.be.json + res.text.should.equal('{"name":"tobi"}'); + done(); +});</code></pre></dd> + <section class="suite"> + <h1>when called several times</h1> + <dl> + <dt>should merge the objects</dt> + <dd><pre><code>request +.post(uri + '/echo') +.send({ name: 'tobi' }) +.send({ age: 1 }) +.end(function(err, res){ + res.should.be.json + if (NODE) { + res.buffered.should.be.true; + } + res.text.should.equal('{"name":"tobi","age":1}'); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>.end(fn)</h1> + <dl> + <dt>should check arity</dt> + <dd><pre><code>request +.post(uri + '/echo') +.send({ name: 'tobi' }) +.end(function(err, res){ + assert(null == err); + res.text.should.equal('{"name":"tobi"}'); + done(); +});</code></pre></dd> + <dt>should emit request</dt> + <dd><pre><code>var req = request.post(uri + '/echo'); +req.on('request', function(request){ + assert(req == request); + done(); +}); +req.end();</code></pre></dd> + <dt>should emit response</dt> + <dd><pre><code>request +.post(uri + '/echo') +.send({ name: 'tobi' }) +.on('response', function(res){ + res.text.should.equal('{"name":"tobi"}'); + done(); +}) +.end();</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.then(fulfill, reject)</h1> + <dl> + <dt>should support successful fulfills with .then(fulfill)</dt> + <dd><pre><code>request +.post(uri + '/echo') +.send({ name: 'tobi' }) +.then(function(res) { + res.text.should.equal('{"name":"tobi"}'); + done(); +})</code></pre></dd> + <dt>should reject an error with .then(null, reject)</dt> + <dd><pre><code>request +.get(uri + '/error') +.then(null, function(err) { + assert(err.status == 500); + assert(err.response.text == 'boom'); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.abort()</h1> + <dl> + <dt>should abort the request</dt> + <dd><pre><code>var req = request +.get(uri + '/delay/3000') +.end(function(err, res){ + assert(false, 'should not complete the request'); +}); +req.on('abort', done); +setTimeout(function() { + req.abort(); +}, 1000);</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>request</h1> + <dl> + <section class="suite"> + <h1>persistent agent</h1> + <dl> + <dt>should gain a session on POST</dt> + <dd><pre><code>agent3 + .post('http://localhost:4000/signin') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + should.not.exist(res.headers['set-cookie']); + res.text.should.include('dashboard'); + done(); + });</code></pre></dd> + <dt>should start with empty session (set cookies)</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/dashboard') + .end(function(err, res) { + should.exist(err); + res.should.have.status(401); + should.exist(res.headers['set-cookie']); + done(); + });</code></pre></dd> + <dt>should gain a session (cookies already set)</dt> + <dd><pre><code>agent1 + .post('http://localhost:4000/signin') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + should.not.exist(res.headers['set-cookie']); + res.text.should.include('dashboard'); + done(); + });</code></pre></dd> + <dt>should persist cookies across requests</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/dashboard') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + done(); + });</code></pre></dd> + <dt>should have the cookie set in the end callback</dt> + <dd><pre><code>agent4 + .post('http://localhost:4000/setcookie') + .end(function(err, res) { + agent4 + .get('http://localhost:4000/getcookie') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + assert(res.text === 'jar'); + done(); + }); + });</code></pre></dd> + <dt>should not share cookies</dt> + <dd><pre><code>agent2 + .get('http://localhost:4000/dashboard') + .end(function(err, res) { + should.exist(err); + res.should.have.status(401); + done(); + });</code></pre></dd> + <dt>should not lose cookies between agents</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/dashboard') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + done(); + });</code></pre></dd> + <dt>should be able to follow redirects</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + res.text.should.include('dashboard'); + done(); + });</code></pre></dd> + <dt>should be able to post redirects</dt> + <dd><pre><code>agent1 + .post('http://localhost:4000/redirect') + .send({ foo: 'bar', baz: 'blaaah' }) + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + res.text.should.include('simple'); + res.redirects.should.eql(['http://localhost:4000/simple']); + done(); + });</code></pre></dd> + <dt>should be able to limit redirects</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/') + .redirects(0) + .end(function(err, res) { + should.exist(err); + res.should.have.status(302); + res.redirects.should.eql([]); + res.header.location.should.equal('/dashboard'); + done(); + });</code></pre></dd> + <dt>should be able to create a new session (clear cookie)</dt> + <dd><pre><code>agent1 + .post('http://localhost:4000/signout') + .end(function(err, res) { + should.not.exist(err); + res.should.have.status(200); + should.exist(res.headers['set-cookie']); + done(); + });</code></pre></dd> + <dt>should regenerate with an empty session</dt> + <dd><pre><code>agent1 + .get('http://localhost:4000/dashboard') + .end(function(err, res) { + should.exist(err); + res.should.have.status(401); + should.not.exist(res.headers['set-cookie']); + done(); + });</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>Basic auth</h1> + <dl> + <section class="suite"> + <h1>when credentials are present in url</h1> + <dl> + <dt>should set Authorization</dt> + <dd><pre><code>request +.get('http://tobi:learnboost@localhost:3010') +.end(function(err, res){ + res.status.should.equal(200); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.auth(user, pass)</h1> + <dl> + <dt>should set Authorization</dt> + <dd><pre><code>request +.get('http://localhost:3010') +.auth('tobi', 'learnboost') +.end(function(err, res){ + res.status.should.equal(200); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.auth(user + ":" + pass)</h1> + <dl> + <dt>should set authorization</dt> + <dd><pre><code>request +.get('http://localhost:3010/again') +.auth('tobi') +.end(function(err, res){ + res.status.should.eql(200); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>[node] request</h1> + <dl> + <section class="suite"> + <h1>res.statusCode</h1> + <dl> + <dt>should set statusCode</dt> + <dd><pre><code>request +.get('http://localhost:5000/login', function(err, res){ + assert(res.statusCode === 200); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with an object</h1> + <dl> + <dt>should format the url</dt> + <dd><pre><code>request +.get(url.parse('http://localhost:5000/login')) +.end(function(err, res){ + assert(res.ok); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>without a schema</h1> + <dl> + <dt>should default to http</dt> + <dd><pre><code>request +.get('localhost:5000/login') +.end(function(err, res){ + assert(res.status == 200); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.toJSON()</h1> + <dl> + <dt>should describe the request</dt> + <dd><pre><code>request +.post(':5000/echo') +.send({ foo: 'baz' }) +.end(function(err, res){ + var obj = res.request.toJSON(); + assert('POST' == obj.method); + assert(':5000/echo' == obj.url); + assert('baz' == obj.data.foo); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>should allow the send shorthand</h1> + <dl> + <dt>with callback in the method call</dt> + <dd><pre><code>request +.get('http://localhost:5000/login', function(err, res) { + assert(res.status == 200); + done(); +});</code></pre></dd> + <dt>with data in the method call</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo', { foo: 'bar' }) +.end(function(err, res) { + assert('{"foo":"bar"}' == res.text); + done(); +});</code></pre></dd> + <dt>with callback and data in the method call</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo', { foo: 'bar' }, function(err, res) { + assert('{"foo":"bar"}' == res.text); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.toJSON()</h1> + <dl> + <dt>should describe the response</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo') +.send({ foo: 'baz' }) +.end(function(err, res){ + var obj = res.toJSON(); + assert('object' == typeof obj.header); + assert('object' == typeof obj.req); + assert(200 == obj.status); + assert('{"foo":"baz"}' == obj.text); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.links</h1> + <dl> + <dt>should default to an empty object</dt> + <dd><pre><code>request +.get('http://localhost:5000/login') +.end(function(err, res){ + res.links.should.eql({}); + done(); +})</code></pre></dd> + <dt>should parse the Link header field</dt> + <dd><pre><code>request +.get('http://localhost:5000/links') +.end(function(err, res){ + res.links.next.should.equal('https://api.github.com/repos/visionmedia/mocha/issues?page=2'); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.unset(field)</h1> + <dl> + <dt>should remove the header field</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo') +.unset('User-Agent') +.end(function(err, res){ + assert(void 0 == res.header['user-agent']); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.write(str)</h1> + <dl> + <dt>should write the given data</dt> + <dd><pre><code>var req = request.post('http://localhost:5000/echo'); +req.set('Content-Type', 'application/json'); +req.write('{"name"').should.be.a.boolean; +req.write(':"tobi"}').should.be.a.boolean; +req.end(function(err, res){ + res.text.should.equal('{"name":"tobi"}'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.pipe(stream)</h1> + <dl> + <dt>should pipe the response to the given stream</dt> + <dd><pre><code>var stream = new EventEmitter; +stream.buf = ''; +stream.writable = true; +stream.write = function(chunk){ + this.buf += chunk; +}; +stream.end = function(){ + this.buf.should.equal('{"name":"tobi"}'); + done(); +}; +request +.post('http://localhost:5000/echo') +.send('{"name":"tobi"}') +.pipe(stream);</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.buffer()</h1> + <dl> + <dt>should enable buffering</dt> + <dd><pre><code>request +.get('http://localhost:5000/custom') +.buffer() +.end(function(err, res){ + assert(null == err); + assert('custom stuff' == res.text); + assert(res.buffered); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.buffer(false)</h1> + <dl> + <dt>should disable buffering</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo') +.type('application/x-dog') +.send('hello this is dog') +.buffer(false) +.end(function(err, res){ + assert(null == err); + assert(null == res.text); + res.body.should.eql({}); + var buf = ''; + res.setEncoding('utf8'); + res.on('data', function(chunk){ buf += chunk }); + res.on('end', function(){ + buf.should.equal('hello this is dog'); + done(); + }); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.agent()</h1> + <dl> + <dt>should return the defaut agent</dt> + <dd><pre><code>var req = request.post('http://localhost:5000/echo'); +req.agent().should.equal(false); +done();</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.agent(undefined)</h1> + <dl> + <dt>should set an agent to undefined and ensure it is chainable</dt> + <dd><pre><code>var req = request.get('http://localhost:5000/echo'); +var ret = req.agent(undefined); +ret.should.equal(req); +assert(req.agent() === undefined); +done();</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.agent(new http.Agent())</h1> + <dl> + <dt>should set passed agent</dt> + <dd><pre><code>var http = require('http'); +var req = request.get('http://localhost:5000/echo'); +var agent = new http.Agent(); +var ret = req.agent(agent); +ret.should.equal(req); +req.agent().should.equal(agent) +done();</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with a content type other than application/json or text/*</h1> + <dl> + <dt>should disable buffering</dt> + <dd><pre><code>request +.post('http://localhost:5000/echo') +.type('application/x-dog') +.send('hello this is dog') +.end(function(err, res){ + assert(null == err); + assert(null == res.text); + res.body.should.eql({}); + var buf = ''; + res.setEncoding('utf8'); + res.buffered.should.be.false; + res.on('data', function(chunk){ buf += chunk }); + res.on('end', function(){ + buf.should.equal('hello this is dog'); + done(); + }); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>content-length</h1> + <dl> + <dt>should be set to the byte length of a non-buffer object</dt> + <dd><pre><code>var decoder = new StringDecoder('utf8'); +var img = fs.readFileSync(__dirname + '/fixtures/test.png'); +img = decoder.write(img); +request +.post('http://localhost:5000/echo') +.type('application/x-image') +.send(img) +.buffer(false) +.end(function(err, res){ + assert(null == err); + assert(!res.buffered); + assert(res.header['content-length'] == Buffer.byteLength(img)); + done(); +});</code></pre></dd> + <dt>should be set to the length of a buffer object</dt> + <dd><pre><code>var img = fs.readFileSync(__dirname + '/fixtures/test.png'); +request +.post('http://localhost:5000/echo') +.type('application/x-image') +.send(img) +.buffer(true) +.end(function(err, res){ + assert(null == err); + assert(res.buffered); + assert(res.header['content-length'] == img.length); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.set("Content-Type", contentType)</h1> + <dl> + <dt>should work with just the contentType component</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.set('Content-Type', 'application/json') +.send({ name: 'tobi' }) +.end(function(err, res){ + assert(!err); + done(); +});</code></pre></dd> + <dt>should work with the charset component</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.set('Content-Type', 'application/json; charset=utf-8') +.send({ name: 'tobi' }) +.end(function(err, res){ + assert(!err); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>exports</h1> + <dl> + <dt>should expose Part</dt> + <dd><pre><code>request.Part.should.be.a.function;</code></pre></dd> + <dt>should expose .protocols</dt> + <dd><pre><code>Object.keys(request.protocols) + .should.eql(['http:', 'https:']);</code></pre></dd> + <dt>should expose .serialize</dt> + <dd><pre><code>Object.keys(request.serialize) + .should.eql(['application/x-www-form-urlencoded', 'application/json']);</code></pre></dd> + <dt>should expose .parse</dt> + <dd><pre><code>Object.keys(request.parse) + .should.eql(['application/x-www-form-urlencoded', 'application/json', 'text', 'image']);</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>flags</h1> + <dl> + <section class="suite"> + <h1>with 4xx response</h1> + <dl> + <dt>should set res.error and res.clientError</dt> + <dd><pre><code>request +.get('http://localhost:3004/notfound') +.end(function(err, res){ + assert(err); + assert(!res.ok, 'response should not be ok'); + assert(res.error, 'response should be an error'); + assert(res.clientError, 'response should be a client error'); + assert(!res.serverError, 'response should not be a server error'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 5xx response</h1> + <dl> + <dt>should set res.error and res.serverError</dt> + <dd><pre><code>request +.get('http://localhost:3004/error') +.end(function(err, res){ + assert(err); + assert(!res.ok, 'response should not be ok'); + assert(!res.notFound, 'response should not be notFound'); + assert(res.error, 'response should be an error'); + assert(!res.clientError, 'response should not be a client error'); + assert(res.serverError, 'response should be a server error'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 404 Not Found</h1> + <dl> + <dt>should res.notFound</dt> + <dd><pre><code>request +.get('http://localhost:3004/notfound') +.end(function(err, res){ + assert(err); + assert(res.notFound, 'response should be .notFound'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 400 Bad Request</h1> + <dl> + <dt>should set req.badRequest</dt> + <dd><pre><code>request +.get('http://localhost:3004/bad-request') +.end(function(err, res){ + assert(err); + assert(res.badRequest, 'response should be .badRequest'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 401 Bad Request</h1> + <dl> + <dt>should set res.unauthorized</dt> + <dd><pre><code>request +.get('http://localhost:3004/unauthorized') +.end(function(err, res){ + assert(err); + assert(res.unauthorized, 'response should be .unauthorized'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 406 Not Acceptable</h1> + <dl> + <dt>should set res.notAcceptable</dt> + <dd><pre><code>request +.get('http://localhost:3004/not-acceptable') +.end(function(err, res){ + assert(err); + assert(res.notAcceptable, 'response should be .notAcceptable'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>with 204 No Content</h1> + <dl> + <dt>should set res.noContent</dt> + <dd><pre><code>request +.get('http://localhost:3004/no-content') +.end(function(err, res){ + assert(!err); + assert(res.noContent, 'response should be .noContent'); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.send(Object) as "form"</h1> + <dl> + <section class="suite"> + <h1>with req.type() set to form</h1> + <dl> + <dt>should send x-www-form-urlencoded data</dt> + <dd><pre><code>request +.post('http://localhost:3002/echo') +.type('form') +.send({ name: 'tobi' }) +.end(function(err, res){ + res.header['content-type'].should.equal('application/x-www-form-urlencoded'); + res.text.should.equal('name=tobi'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>when called several times</h1> + <dl> + <dt>should merge the objects</dt> + <dd><pre><code>request +.post('http://localhost:3002/echo') +.type('form') +.send({ name: { first: 'tobi', last: 'holowaychuk' } }) +.send({ age: '1' }) +.end(function(err, res){ + res.header['content-type'].should.equal('application/x-www-form-urlencoded'); + res.text.should.equal('name%5Bfirst%5D=tobi&name%5Blast%5D=holowaychuk&age=1'); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.send(String)</h1> + <dl> + <dt>should default to "form"</dt> + <dd><pre><code>request +.post('http://localhost:3002/echo') +.send('user[name]=tj') +.send('user[email]=tj@vision-media.ca') +.end(function(err, res){ + res.header['content-type'].should.equal('application/x-www-form-urlencoded'); + res.body.should.eql({ user: { name: 'tj', email: 'tj@vision-media.ca' } }); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>res.body</h1> + <dl> + <section class="suite"> + <h1>application/x-www-form-urlencoded</h1> + <dl> + <dt>should parse the body</dt> + <dd><pre><code>request +.get('http://localhost:3002/form-data') +.end(function(err, res){ + res.text.should.equal('pet[name]=manny'); + res.body.should.eql({ pet: { name: 'manny' }}); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>https</h1> + <dl> + <section class="suite"> + <h1>request</h1> + <dl> + <dt>should give a good response</dt> + <dd><pre><code>request +.get('https://localhost:8443/') +.ca(cert) +.end(function(err, res){ + assert(res.ok); + assert('Safe and secure!' === res.text); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.agent</h1> + <dl> + <dt>should be able to make multiple requests without redefining the certificate</dt> + <dd><pre><code>var agent = request.agent({ca: cert}); +agent +.get('https://localhost:8443/') +.end(function(err, res){ + assert(res.ok); + assert('Safe and secure!' === res.text); + agent + .get(url.parse('https://localhost:8443/')) + .end(function(err, res){ + assert(res.ok); + assert('Safe and secure!' === res.text); + done(); + }); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>res.body</h1> + <dl> + <section class="suite"> + <h1>image/png</h1> + <dl> + <dt>should parse the body</dt> + <dd><pre><code>request +.get('http://localhost:3011/image') +.end(function(err, res){ + (res.body.length - img.length).should.equal(0); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>zlib</h1> + <dl> + <dt>should deflate the content</dt> + <dd><pre><code>request + .get('http://localhost:3080') + .end(function(err, res){ + res.should.have.status(200); + res.text.should.equal(subject); + res.headers['content-length'].should.be.below(subject.length); + done(); + });</code></pre></dd> + <dt>should handle corrupted responses</dt> + <dd><pre><code>request + .get('http://localhost:3080/corrupt') + .end(function(err, res){ + assert(err, 'missing error'); + assert(!res, 'response should not be defined'); + done(); + });</code></pre></dd> + <section class="suite"> + <h1>without encoding set</h1> + <dl> + <dt>should emit buffers</dt> + <dd><pre><code>request + .get('http://localhost:3080/binary') + .end(function(err, res){ + res.should.have.status(200); + res.headers['content-length'].should.be.below(subject.length); + res.on('data', function(chunk){ + chunk.should.have.length(subject.length); + }); + res.on('end', done); + });</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.send(Object) as "json"</h1> + <dl> + <dt>should default to json</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.send({ name: 'tobi' }) +.end(function(err, res){ + res.should.be.json + res.text.should.equal('{"name":"tobi"}'); + done(); +});</code></pre></dd> + <dt>should work with arrays</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.send([1,2,3]) +.end(function(err, res){ + res.should.be.json + res.text.should.equal('[1,2,3]'); + done(); +});</code></pre></dd> + <dt>should work with value null</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.type('json') +.send('null') +.end(function(err, res){ + res.should.be.json + assert(res.body === null); + done(); +});</code></pre></dd> + <dt>should work with value false</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.type('json') +.send('false') +.end(function(err, res){ + res.should.be.json + res.body.should.equal(false); + done(); +});</code></pre></dd> + <dt>should work with value 0</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.type('json') +.send('0') +.end(function(err, res){ + res.should.be.json + res.body.should.equal(0); + done(); +});</code></pre></dd> + <dt>should work with empty string value</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.type('json') +.send('""') +.end(function(err, res){ + res.should.be.json + res.body.should.equal(""); + done(); +});</code></pre></dd> + <dt>should work with GET</dt> + <dd><pre><code>request +.get('http://localhost:3005/echo') +.send({ tobi: 'ferret' }) +.end(function(err, res){ + res.should.be.json + res.text.should.equal('{"tobi":"ferret"}'); + done(); +});</code></pre></dd> + <dt>should work with vendor MIME type</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.set('Content-Type', 'application/vnd.example+json') +.send({ name: 'vendor' }) +.end(function(err, res){ + res.text.should.equal('{"name":"vendor"}'); + done(); +});</code></pre></dd> + <section class="suite"> + <h1>when called several times</h1> + <dl> + <dt>should merge the objects</dt> + <dd><pre><code>request +.post('http://localhost:3005/echo') +.send({ name: 'tobi' }) +.send({ age: 1 }) +.end(function(err, res){ + res.should.be.json + res.text.should.equal('{"name":"tobi","age":1}'); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>res.body</h1> + <dl> + <section class="suite"> + <h1>application/json</h1> + <dl> + <dt>should parse the body</dt> + <dd><pre><code>request +.get('http://localhost:3005/json') +.end(function(err, res){ + res.text.should.equal('{"name":"manny"}'); + res.body.should.eql({ name: 'manny' }); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>HEAD requests</h1> + <dl> + <dt>should not throw a parse error</dt> + <dd><pre><code>request +.head('http://localhost:3005/json') +.end(function(err, res){ + assert(err === null); + assert(res.text === undefined) + assert(Object.keys(res.body).length === 0) + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>Invalid JSON response</h1> + <dl> + <dt>should return the raw response</dt> + <dd><pre><code>request +.get('http://localhost:3005/invalid-json') +.end(function(err, res){ + assert.deepEqual(err.rawResponse, ")]}', {'header':{'code':200,'text':'OK','version':'1.0'},'data':'some data'}"); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>No content</h1> + <dl> + <dt>should not throw a parse error</dt> + <dd><pre><code>request +.get('http://localhost:3005/no-content') +.end(function(err, res){ + assert(err === null); + assert(res.text === ''); + assert(Object.keys(res.body).length === 0); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>application/json+hal</h1> + <dl> + <dt>should parse the body</dt> + <dd><pre><code>request +.get('http://localhost:3005/json-hal') +.end(function(err, res){ + if (err) return done(err); + res.text.should.equal('{"name":"hal 5000"}'); + res.body.should.eql({ name: 'hal 5000' }); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>vnd.collection+json</h1> + <dl> + <dt>should parse the body</dt> + <dd><pre><code>request +.get('http://localhost:3005/collection-json') +.end(function(err, res){ + res.text.should.equal('{"name":"chewbacca"}'); + res.body.should.eql({ name: 'chewbacca' }); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>Request</h1> + <dl> + <section class="suite"> + <h1>#attach(name, path, filename)</h1> + <dl> + <dt>should use the custom filename</dt> + <dd><pre><code>request +.post(':3005/echo') +.attach('document', 'test/node/fixtures/user.html', 'doc.html') +.end(function(err, res){ + if (err) return done(err); + var html = res.files.document; + html.name.should.equal('doc.html'); + html.type.should.equal('text/html'); + read(html.path).should.equal('<h1>name</h1>'); + done(); +})</code></pre></dd> + <dt>should fire progress event</dt> + <dd><pre><code>var loaded = 0; +var total = 0; +request +.post(':3005/echo') +.attach('document', 'test/node/fixtures/user.html') +.on('progress', function (event) { + total = event.total; + loaded = event.loaded; +}) +.end(function(err, res){ + if (err) return done(err); + var html = res.files.document; + html.name.should.equal('user.html'); + html.type.should.equal('text/html'); + read(html.path).should.equal('<h1>name</h1>'); + total.should.equal(221); + loaded.should.equal(221); + done(); +})</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>with network error</h1> + <dl> + <dt>should error</dt> + <dd><pre><code>request +.get('http://localhost:' + this.port + '/') +.end(function(err, res){ + assert(err, 'expected an error'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>request</h1> + <dl> + <section class="suite"> + <h1>not modified</h1> + <dl> + <dt>should start with 200</dt> + <dd><pre><code>request +.get('http://localhost:3008/') +.end(function(err, res){ + res.should.have.status(200) + res.text.should.match(/^\d+$/); + ts = +res.text; + done(); +});</code></pre></dd> + <dt>should then be 304</dt> + <dd><pre><code>request +.get('http://localhost:3008/') +.set('If-Modified-Since', new Date(ts).toUTCString()) +.end(function(err, res){ + res.should.have.status(304) + // res.text.should.be.empty + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.parse(fn)</h1> + <dl> + <dt>should take precedence over default parsers</dt> + <dd><pre><code>request +.get('http://localhost:3033/manny') +.parse(request.parse['application/json']) +.end(function(err, res){ + assert(res.ok); + assert('{"name":"manny"}' == res.text); + assert('manny' == res.body.name); + done(); +});</code></pre></dd> + <dt>should be the only parser</dt> + <dd><pre><code>request +.get('http://localhost:3033/image') +.parse(function(res, fn) { + res.on('data', function() {}); +}) +.end(function(err, res){ + assert(res.ok); + assert(res.text === undefined); + res.body.should.eql({}); + done(); +});</code></pre></dd> + <dt>should emit error if parser throws</dt> + <dd><pre><code>request +.get('http://localhost:3033/manny') +.parse(function() { + throw new Error('I am broken'); +}) +.on('error', function(err) { + err.message.should.equal('I am broken'); + done(); +}) +.end();</code></pre></dd> + <dt>should emit error if parser returns an error</dt> + <dd><pre><code>request +.get('http://localhost:3033/manny') +.parse(function(res, fn) { + fn(new Error('I am broken')); +}) +.on('error', function(err) { + err.message.should.equal('I am broken'); + done(); +}) +.end()</code></pre></dd> + <dt>should not emit error on chunked json</dt> + <dd><pre><code>request +.get('http://localhost:3033/chunked-json') +.end(function(err){ + assert(!err); + done(); +});</code></pre></dd> + <dt>should not emit error on aborted chunked json</dt> + <dd><pre><code>var req = request +.get('http://localhost:3033/chunked-json') +.end(function(err){ + assert(!err); + done(); +}); +setTimeout(function(){req.abort()},50);</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>pipe on redirect</h1> + <dl> + <dt>should follow Location</dt> + <dd><pre><code>var stream = fs.createWriteStream('test/node/fixtures/pipe.txt'); +var redirects = []; +var req = request + .get('http://localhost:3012/') + .on('redirect', function (res) { + redirects.push(res.headers.location); + }) + .on('end', function () { + var arr = []; + arr.push('/movies'); + arr.push('/movies/all'); + arr.push('/movies/all/0'); + redirects.should.eql(arr); + fs.readFileSync('test/node/fixtures/pipe.txt', 'utf8').should.eql('first movie page'); + done(); + }); + req.pipe(stream);</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>request pipe</h1> + <dl> + <dt>should act as a writable stream</dt> + <dd><pre><code>var req = request.post('http://localhost:3020'); +var stream = fs.createReadStream('test/node/fixtures/user.json'); +req.type('json'); +req.on('response', function(res){ + res.body.should.eql({ name: 'tobi' }); + done(); +}); +stream.pipe(req);</code></pre></dd> + <dt>should act as a readable stream</dt> + <dd><pre><code>var stream = fs.createWriteStream('test/node/fixtures/tmp.json'); +var req = request.get('http://localhost:3025'); +req.type('json'); +req.on('end', function(){ + JSON.parse(fs.readFileSync('test/node/fixtures/tmp.json', 'utf8')).should.eql({ name: 'tobi' }); + done(); +}); +req.pipe(stream);</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.query(String)</h1> + <dl> + <dt>should supply uri malformed error to the callback</dt> + <dd><pre><code>request +.get('http://localhost:3006') +.query('name=toby') +.query('a=\uD800') +.query({ b: '\uD800' }) +.end(function(err, res){ + assert(err instanceof Error); + assert('URIError' == err.name); + done(); +});</code></pre></dd> + <dt>should support passing in a string</dt> + <dd><pre><code>request +.del('http://localhost:3006') +.query('name=t%F6bi') +.end(function(err, res){ + res.body.should.eql({ name: 't%F6bi' }); + done(); +});</code></pre></dd> + <dt>should work with url query-string and string for query</dt> + <dd><pre><code>request +.del('http://localhost:3006/?name=tobi') +.query('age=2%20') +.end(function(err, res){ + res.body.should.eql({ name: 'tobi', age: '2 ' }); + done(); +});</code></pre></dd> + <dt>should support compound elements in a string</dt> + <dd><pre><code>request + .del('http://localhost:3006/') + .query('name=t%F6bi&age=2') + .end(function(err, res){ + res.body.should.eql({ name: 't%F6bi', age: '2' }); + done(); + });</code></pre></dd> + <dt>should work when called multiple times with a string</dt> + <dd><pre><code>request +.del('http://localhost:3006/') +.query('name=t%F6bi') +.query('age=2%F6') +.end(function(err, res){ + res.body.should.eql({ name: 't%F6bi', age: '2%F6' }); + done(); +});</code></pre></dd> + <dt>should work with normal `query` object and query string</dt> + <dd><pre><code>request +.del('http://localhost:3006/') +.query('name=t%F6bi') +.query({ age: '2' }) +.end(function(err, res){ + res.body.should.eql({ name: 't%F6bi', age: '2' }); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.query(Object)</h1> + <dl> + <dt>should construct the query-string</dt> + <dd><pre><code>request +.del('http://localhost:3006/') +.query({ name: 'tobi' }) +.query({ order: 'asc' }) +.query({ limit: ['1', '2'] }) +.end(function(err, res){ + res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] }); + done(); +});</code></pre></dd> + <dt>should not error on dates</dt> + <dd><pre><code>var date = new Date(0); +request +.del('http://localhost:3006/') +.query({ at: date }) +.end(function(err, res){ + assert(date.toISOString() == res.body.at); + done(); +});</code></pre></dd> + <dt>should work after setting header fields</dt> + <dd><pre><code>request +.del('http://localhost:3006/') +.set('Foo', 'bar') +.set('Bar', 'baz') +.query({ name: 'tobi' }) +.query({ order: 'asc' }) +.query({ limit: ['1', '2'] }) +.end(function(err, res){ + res.body.should.eql({ name: 'tobi', order: 'asc', limit: ['1', '2'] }); + done(); +});</code></pre></dd> + <dt>should append to the original query-string</dt> + <dd><pre><code>request +.del('http://localhost:3006/?name=tobi') +.query({ order: 'asc' }) +.end(function(err, res) { + res.body.should.eql({ name: 'tobi', order: 'asc' }); + done(); +});</code></pre></dd> + <dt>should retain the original query-string</dt> + <dd><pre><code>request +.del('http://localhost:3006/?name=tobi') +.end(function(err, res) { + res.body.should.eql({ name: 'tobi' }); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>request.get</h1> + <dl> + <section class="suite"> + <h1>on 301 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .get('http://localhost:3210/test-301') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 302 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .get('http://localhost:3210/test-302') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 303 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .get('http://localhost:3210/test-303') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 307 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .get('http://localhost:3210/test-307') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 308 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .get('http://localhost:3210/test-308') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>request.post</h1> + <dl> + <section class="suite"> + <h1>on 301 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .post('http://localhost:3210/test-301') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 302 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .post('http://localhost:3210/test-302') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 303 redirect</h1> + <dl> + <dt>should follow Location with a GET request</dt> + <dd><pre><code>var req = request + .post('http://localhost:3210/test-303') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('GET'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 307 redirect</h1> + <dl> + <dt>should follow Location with a POST request</dt> + <dd><pre><code>var req = request + .post('http://localhost:3210/test-307') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('POST'); + done(); + });</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 308 redirect</h1> + <dl> + <dt>should follow Location with a POST request</dt> + <dd><pre><code>var req = request + .post('http://localhost:3210/test-308') + .redirects(1) + .end(function(err, res){ + req.req._headers.host.should.eql('localhost:3211'); + res.status.should.eql(200); + res.text.should.eql('POST'); + done(); + });</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>request</h1> + <dl> + <section class="suite"> + <h1>on redirect</h1> + <dl> + <dt>should follow Location</dt> + <dd><pre><code>var redirects = []; +request +.get('http://localhost:3003/') +.on('redirect', function(res){ + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + arr.push('/movies'); + arr.push('/movies/all'); + arr.push('/movies/all/0'); + redirects.should.eql(arr); + res.text.should.equal('first movie page'); + done(); +});</code></pre></dd> + <dt>should retain header fields</dt> + <dd><pre><code>request +.get('http://localhost:3003/header') +.set('X-Foo', 'bar') +.end(function(err, res){ + res.body.should.have.property('x-foo', 'bar'); + done(); +});</code></pre></dd> + <dt>should remove Content-* fields</dt> + <dd><pre><code>request +.post('http://localhost:3003/header') +.type('txt') +.set('X-Foo', 'bar') +.set('X-Bar', 'baz') +.send('hey') +.end(function(err, res){ + res.body.should.have.property('x-foo', 'bar'); + res.body.should.have.property('x-bar', 'baz'); + res.body.should.not.have.property('content-type'); + res.body.should.not.have.property('content-length'); + res.body.should.not.have.property('transfer-encoding'); + done(); +});</code></pre></dd> + <dt>should retain cookies</dt> + <dd><pre><code>request +.get('http://localhost:3003/header') +.set('Cookie', 'foo=bar;') +.end(function(err, res){ + res.body.should.have.property('cookie', 'foo=bar;'); + done(); +});</code></pre></dd> + <dt>should preserve timeout across redirects</dt> + <dd><pre><code>request +.get('http://localhost:3003/movies/random') +.timeout(250) +.end(function(err, res){ + assert(err instanceof Error, 'expected an error'); + err.should.have.property('timeout', 250); + done(); +});</code></pre></dd> + <dt>should not resend query parameters</dt> + <dd><pre><code>var redirects = []; +var query = []; +request +.get('http://localhost:3003/?foo=bar') +.on('redirect', function(res){ + query.push(res.headers.query); + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + arr.push('/movies'); + arr.push('/movies/all'); + arr.push('/movies/all/0'); + redirects.should.eql(arr); + res.text.should.equal('first movie page'); + query.should.eql(['{"foo":"bar"}', '{}', '{}']); + res.headers.query.should.eql('{}'); + done(); +});</code></pre></dd> + <dt>should handle no location header</dt> + <dd><pre><code>request +.get('http://localhost:3003/bad-redirect') +.end(function(err, res){ + err.message.should.equal('No location header for redirect'); + done(); +});</code></pre></dd> + <section class="suite"> + <h1>when relative</h1> + <dl> + <dt>should redirect to a sibling path</dt> + <dd><pre><code>var redirects = []; +request +.get('http://localhost:3003/relative') +.on('redirect', function(res){ + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + redirects.should.eql(['tobi']); + res.text.should.equal('tobi'); + done(); +});</code></pre></dd> + <dt>should redirect to a parent path</dt> + <dd><pre><code>var redirects = []; +request +.get('http://localhost:3003/relative/sub') +.on('redirect', function(res){ + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + redirects.should.eql(['../tobi']); + res.text.should.equal('tobi'); + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>req.redirects(n)</h1> + <dl> + <dt>should alter the default number of redirects to follow</dt> + <dd><pre><code>var redirects = []; +request +.get('http://localhost:3003/') +.redirects(2) +.on('redirect', function(res){ + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + assert(res.redirect, 'res.redirect'); + arr.push('/movies'); + arr.push('/movies/all'); + redirects.should.eql(arr); + res.text.should.match(/Moved Temporarily|Found/); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on POST</h1> + <dl> + <dt>should redirect as GET</dt> + <dd><pre><code>var redirects = []; +request +.post('http://localhost:3003/movie') +.send({ name: 'Tobi' }) +.redirects(2) +.on('redirect', function(res){ + redirects.push(res.headers.location); +}) +.end(function(err, res){ + var arr = []; + arr.push('/movies/all/0'); + redirects.should.eql(arr); + res.text.should.equal('first movie page'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 303</h1> + <dl> + <dt>should redirect with same method</dt> + <dd><pre><code>request +.put('http://localhost:3003/redirect-303') +.send({msg: "hello"}) +.redirects(1) +.on('redirect', function(res) { + res.headers.location.should.equal('/reply-method') +}) +.end(function(err, res){ + res.text.should.equal('method=get'); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 307</h1> + <dl> + <dt>should redirect with same method</dt> + <dd><pre><code>request +.put('http://localhost:3003/redirect-307') +.send({msg: "hello"}) +.redirects(1) +.on('redirect', function(res) { + res.headers.location.should.equal('/reply-method') +}) +.end(function(err, res){ + res.text.should.equal('method=put'); + done(); +})</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>on 308</h1> + <dl> + <dt>should redirect with same method</dt> + <dd><pre><code>request +.put('http://localhost:3003/redirect-308') +.send({msg: "hello"}) +.redirects(1) +.on('redirect', function(res) { + res.headers.location.should.equal('/reply-method') +}) +.end(function(err, res){ + res.text.should.equal('method=put'); + done(); +})</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>response</h1> + <dl> + <dt>should act as a readable stream</dt> + <dd><pre><code>var req = request + .get('http://localhost:3025') + .buffer(false); +req.end(function(err,res){ + if (err) return done(err); + var trackEndEvent = 0; + var trackCloseEvent = 0; + res.on('end',function(){ + trackEndEvent++; + trackEndEvent.should.equal(1); + trackCloseEvent.should.equal(0); // close should not have been called + done(); + }); + res.on('close',function(){ + trackCloseEvent++; + }); + + (function(){ res.pause() }).should.not.throw(); + (function(){ res.resume() }).should.not.throw(); + (function(){ res.destroy() }).should.not.throw(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>.timeout(ms)</h1> + <dl> + <section class="suite"> + <h1>when timeout is exceeded</h1> + <dl> + <dt>should error</dt> + <dd><pre><code>request +.get('http://localhost:3009/500') +.timeout(150) +.end(function(err, res){ + assert(err, 'expected an error'); + assert('number' == typeof err.timeout, 'expected an error with .timeout'); + assert('ECONNABORTED' == err.code, 'expected abort error code') + done(); +});</code></pre></dd> + </dl> + </section> + </dl> + </section> + <section class="suite"> + <h1>res.toError()</h1> + <dl> + <dt>should return an Error</dt> + <dd><pre><code>request +.get('http://localhost:' + server.address().port) +.end(function(err, res){ + var err = res.toError(); + assert(err.status == 400); + assert(err.method == 'GET'); + assert(err.path == '/'); + assert(err.message == 'cannot GET / (400)'); + assert(err.text == 'invalid json'); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>req.get()</h1> + <dl> + <dt>should set a default user-agent</dt> + <dd><pre><code>request +.get('http://localhost:3345/ua') +.end(function(err, res){ + assert(res.headers); + assert(res.headers['user-agent']); + assert(/^node-superagent\/\d+\.\d+\.\d+$/.test(res.headers['user-agent'])); + done(); +});</code></pre></dd> + <dt>should be able to override user-agent</dt> + <dd><pre><code>request +.get('http://localhost:3345/ua') +.set('User-Agent', 'foo/bar') +.end(function(err, res){ + assert(res.headers); + assert(res.headers['user-agent'] == 'foo/bar'); + done(); +});</code></pre></dd> + <dt>should be able to wipe user-agent</dt> + <dd><pre><code>request +.get('http://localhost:3345/ua') +.unset('User-Agent') +.end(function(err, res){ + assert(res.headers); + assert(res.headers['user-agent'] == void 0); + done(); +});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>utils.type(str)</h1> + <dl> + <dt>should return the mime type</dt> + <dd><pre><code>utils.type('application/json; charset=utf-8') + .should.equal('application/json'); +utils.type('application/json') + .should.equal('application/json');</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>utils.params(str)</h1> + <dl> + <dt>should return the field parameters</dt> + <dd><pre><code>var str = 'application/json; charset=utf-8; foo = bar'; +var obj = utils.params(str); +obj.charset.should.equal('utf-8'); +obj.foo.should.equal('bar'); +var str = 'application/json'; +utils.params(str).should.eql({});</code></pre></dd> + </dl> + </section> + <section class="suite"> + <h1>utils.parseLinks(str)</h1> + <dl> + <dt>should parse links</dt> + <dd><pre><code>var str = '<https://api.github.com/repos/visionmedia/mocha/issues?page=2>; rel="next", <https://api.github.com/repos/visionmedia/mocha/issues?page=5>; rel="last"'; +var ret = utils.parseLinks(str); +ret.next.should.equal('https://api.github.com/repos/visionmedia/mocha/issues?page=2'); +ret.last.should.equal('https://api.github.com/repos/visionmedia/mocha/issues?page=5');</code></pre></dd> + </dl> + </section> + </div> + <a href="http://github.com/visionmedia/superagent"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_white_ffffff.png" alt="Fork me on GitHub"></a> + </body> +</html>
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/lib/client.js b/node_modules/supertest/node_modules/superagent/lib/client.js new file mode 100644 index 0000000..1c72832 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/client.js @@ -0,0 +1,1077 @@ +/** + * Module dependencies. + */ + +var Emitter = require('emitter'); +var reduce = require('reduce'); +var requestBase = require('./request-base'); +var isObject = require('./is-object'); + +/** + * Root reference for iframes. + */ + +var root; +if (typeof window !== 'undefined') { // Browser window + root = window; +} else if (typeof self !== 'undefined') { // Web Worker + root = self; +} else { // Other environments + root = this; +} + +/** + * Noop. + */ + +function noop(){}; + +/** + * Check if `obj` is a host object, + * we don't want to serialize these :) + * + * TODO: future proof, move to compoent land + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + +function isHost(obj) { + var str = {}.toString.call(obj); + + switch (str) { + case '[object File]': + case '[object Blob]': + case '[object FormData]': + return true; + default: + return false; + } +} + +/** + * Expose `request`. + */ + +var request = module.exports = require('./request').bind(null, Request); + +/** + * Determine XHR. + */ + +request.getXHR = function () { + if (root.XMLHttpRequest + && (!root.location || 'file:' != root.location.protocol + || !root.ActiveXObject)) { + return new XMLHttpRequest; + } else { + try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} + } + return false; +}; + +/** + * Removes leading and trailing whitespace, added to support IE. + * + * @param {String} s + * @return {String} + * @api private + */ + +var trim = ''.trim + ? function(s) { return s.trim(); } + : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); }; + +/** + * Serialize the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api private + */ + +function serialize(obj) { + if (!isObject(obj)) return obj; + var pairs = []; + for (var key in obj) { + if (null != obj[key]) { + pushEncodedKeyValuePair(pairs, key, obj[key]); + } + } + return pairs.join('&'); +} + +/** + * Helps 'serialize' with serializing arrays. + * Mutates the pairs array. + * + * @param {Array} pairs + * @param {String} key + * @param {Mixed} val + */ + +function pushEncodedKeyValuePair(pairs, key, val) { + if (Array.isArray(val)) { + return val.forEach(function(v) { + pushEncodedKeyValuePair(pairs, key, v); + }); + } + pairs.push(encodeURIComponent(key) + + '=' + encodeURIComponent(val)); +} + +/** + * Expose serialization method. + */ + + request.serializeObject = serialize; + + /** + * Parse the given x-www-form-urlencoded `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function parseString(str) { + var obj = {}; + var pairs = str.split('&'); + var parts; + var pair; + + for (var i = 0, len = pairs.length; i < len; ++i) { + pair = pairs[i]; + parts = pair.split('='); + obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); + } + + return obj; +} + +/** + * Expose parser. + */ + +request.parseString = parseString; + +/** + * Default MIME type map. + * + * superagent.types.xml = 'application/xml'; + * + */ + +request.types = { + html: 'text/html', + json: 'application/json', + xml: 'application/xml', + urlencoded: 'application/x-www-form-urlencoded', + 'form': 'application/x-www-form-urlencoded', + 'form-data': 'application/x-www-form-urlencoded' +}; + +/** + * Default serialization map. + * + * superagent.serialize['application/xml'] = function(obj){ + * return 'generated xml here'; + * }; + * + */ + + request.serialize = { + 'application/x-www-form-urlencoded': serialize, + 'application/json': JSON.stringify + }; + + /** + * Default parsers. + * + * superagent.parse['application/xml'] = function(str){ + * return { object parsed from str }; + * }; + * + */ + +request.parse = { + 'application/x-www-form-urlencoded': parseString, + 'application/json': JSON.parse +}; + +/** + * Parse the given header `str` into + * an object containing the mapped fields. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function parseHeader(str) { + var lines = str.split(/\r?\n/); + var fields = {}; + var index; + var line; + var field; + var val; + + lines.pop(); // trailing CRLF + + for (var i = 0, len = lines.length; i < len; ++i) { + line = lines[i]; + index = line.indexOf(':'); + field = line.slice(0, index).toLowerCase(); + val = trim(line.slice(index + 1)); + fields[field] = val; + } + + return fields; +} + +/** + * Check if `mime` is json or has +json structured syntax suffix. + * + * @param {String} mime + * @return {Boolean} + * @api private + */ + +function isJSON(mime) { + return /[\/+]json\b/.test(mime); +} + +/** + * Return the mime type for the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function type(str){ + return str.split(/ *; */).shift(); +}; + +/** + * Return header field parameters. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function params(str){ + return reduce(str.split(/ *; */), function(obj, str){ + var parts = str.split(/ *= */) + , key = parts.shift() + , val = parts.shift(); + + if (key && val) obj[key] = val; + return obj; + }, {}); +}; + +/** + * Initialize a new `Response` with the given `xhr`. + * + * - set flags (.ok, .error, etc) + * - parse header + * + * Examples: + * + * Aliasing `superagent` as `request` is nice: + * + * request = superagent; + * + * We can use the promise-like API, or pass callbacks: + * + * request.get('/').end(function(res){}); + * request.get('/', function(res){}); + * + * Sending data can be chained: + * + * request + * .post('/user') + * .send({ name: 'tj' }) + * .end(function(res){}); + * + * Or passed to `.send()`: + * + * request + * .post('/user') + * .send({ name: 'tj' }, function(res){}); + * + * Or passed to `.post()`: + * + * request + * .post('/user', { name: 'tj' }) + * .end(function(res){}); + * + * Or further reduced to a single call for simple cases: + * + * request + * .post('/user', { name: 'tj' }, function(res){}); + * + * @param {XMLHTTPRequest} xhr + * @param {Object} options + * @api private + */ + +function Response(req, options) { + options = options || {}; + this.req = req; + this.xhr = this.req.xhr; + // responseText is accessible only if responseType is '' or 'text' and on older browsers + this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined') + ? this.xhr.responseText + : null; + this.statusText = this.req.xhr.statusText; + this.setStatusProperties(this.xhr.status); + this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders()); + // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but + // getResponseHeader still works. so we get content-type even if getting + // other headers fails. + this.header['content-type'] = this.xhr.getResponseHeader('content-type'); + this.setHeaderProperties(this.header); + this.body = this.req.method != 'HEAD' + ? this.parseBody(this.text ? this.text : this.xhr.response) + : null; +} + +/** + * Get case-insensitive `field` value. + * + * @param {String} field + * @return {String} + * @api public + */ + +Response.prototype.get = function(field){ + return this.header[field.toLowerCase()]; +}; + +/** + * Set header related properties: + * + * - `.type` the content type without params + * + * A response of "Content-Type: text/plain; charset=utf-8" + * will provide you with a `.type` of "text/plain". + * + * @param {Object} header + * @api private + */ + +Response.prototype.setHeaderProperties = function(header){ + // content-type + var ct = this.header['content-type'] || ''; + this.type = type(ct); + + // params + var obj = params(ct); + for (var key in obj) this[key] = obj[key]; +}; + +/** + * Parse the given body `str`. + * + * Used for auto-parsing of bodies. Parsers + * are defined on the `superagent.parse` object. + * + * @param {String} str + * @return {Mixed} + * @api private + */ + +Response.prototype.parseBody = function(str){ + var parse = request.parse[this.type]; + if (!parse && isJSON(this.type)) { + parse = request.parse['application/json']; + } + return parse && str && (str.length || str instanceof Object) + ? parse(str) + : null; +}; + +/** + * Set flags such as `.ok` based on `status`. + * + * For example a 2xx response will give you a `.ok` of __true__ + * whereas 5xx will be __false__ and `.error` will be __true__. The + * `.clientError` and `.serverError` are also available to be more + * specific, and `.statusType` is the class of error ranging from 1..5 + * sometimes useful for mapping respond colors etc. + * + * "sugar" properties are also defined for common cases. Currently providing: + * + * - .noContent + * - .badRequest + * - .unauthorized + * - .notAcceptable + * - .notFound + * + * @param {Number} status + * @api private + */ + +Response.prototype.setStatusProperties = function(status){ + // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request + if (status === 1223) { + status = 204; + } + + var type = status / 100 | 0; + + // status / class + this.status = this.statusCode = status; + this.statusType = type; + + // basics + this.info = 1 == type; + this.ok = 2 == type; + this.clientError = 4 == type; + this.serverError = 5 == type; + this.error = (4 == type || 5 == type) + ? this.toError() + : false; + + // sugar + this.accepted = 202 == status; + this.noContent = 204 == status; + this.badRequest = 400 == status; + this.unauthorized = 401 == status; + this.notAcceptable = 406 == status; + this.notFound = 404 == status; + this.forbidden = 403 == status; +}; + +/** + * Return an `Error` representative of this response. + * + * @return {Error} + * @api public + */ + +Response.prototype.toError = function(){ + var req = this.req; + var method = req.method; + var url = req.url; + + var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')'; + var err = new Error(msg); + err.status = this.status; + err.method = method; + err.url = url; + + return err; +}; + +/** + * Expose `Response`. + */ + +request.Response = Response; + +/** + * Initialize a new `Request` with the given `method` and `url`. + * + * @param {String} method + * @param {String} url + * @api public + */ + +function Request(method, url) { + var self = this; + this._query = this._query || []; + this.method = method; + this.url = url; + this.header = {}; // preserves header name case + this._header = {}; // coerces header names to lowercase + this.on('end', function(){ + var err = null; + var res = null; + + try { + res = new Response(self); + } catch(e) { + err = new Error('Parser is unable to parse the response'); + err.parse = true; + err.original = e; + // issue #675: return the raw response if the response parsing fails + err.rawResponse = self.xhr && self.xhr.responseText ? self.xhr.responseText : null; + // issue #876: return the http status code if the response parsing fails + err.statusCode = self.xhr && self.xhr.status ? self.xhr.status : null; + return self.callback(err); + } + + self.emit('response', res); + + if (err) { + return self.callback(err, res); + } + + if (res.status >= 200 && res.status < 300) { + return self.callback(err, res); + } + + var new_err = new Error(res.statusText || 'Unsuccessful HTTP response'); + new_err.original = err; + new_err.response = res; + new_err.status = res.status; + + self.callback(new_err, res); + }); +} + +/** + * Mixin `Emitter` and `requestBase`. + */ + +Emitter(Request.prototype); +for (var key in requestBase) { + Request.prototype[key] = requestBase[key]; +} + +/** + * Abort the request, and clear potential timeout. + * + * @return {Request} + * @api public + */ + +Request.prototype.abort = function(){ + if (this.aborted) return; + this.aborted = true; + this.xhr.abort(); + this.clearTimeout(); + this.emit('abort'); + return this; +}; + +/** + * Set Content-Type to `type`, mapping values from `request.types`. + * + * Examples: + * + * superagent.types.xml = 'application/xml'; + * + * request.post('/') + * .type('xml') + * .send(xmlstring) + * .end(callback); + * + * request.post('/') + * .type('application/xml') + * .send(xmlstring) + * .end(callback); + * + * @param {String} type + * @return {Request} for chaining + * @api public + */ + +Request.prototype.type = function(type){ + this.set('Content-Type', request.types[type] || type); + return this; +}; + +/** + * Set responseType to `val`. Presently valid responseTypes are 'blob' and + * 'arraybuffer'. + * + * Examples: + * + * req.get('/') + * .responseType('blob') + * .end(callback); + * + * @param {String} val + * @return {Request} for chaining + * @api public + */ + +Request.prototype.responseType = function(val){ + this._responseType = val; + return this; +}; + +/** + * Set Accept to `type`, mapping values from `request.types`. + * + * Examples: + * + * superagent.types.json = 'application/json'; + * + * request.get('/agent') + * .accept('json') + * .end(callback); + * + * request.get('/agent') + * .accept('application/json') + * .end(callback); + * + * @param {String} accept + * @return {Request} for chaining + * @api public + */ + +Request.prototype.accept = function(type){ + this.set('Accept', request.types[type] || type); + return this; +}; + +/** + * Set Authorization field value with `user` and `pass`. + * + * @param {String} user + * @param {String} pass + * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic') + * @return {Request} for chaining + * @api public + */ + +Request.prototype.auth = function(user, pass, options){ + if (!options) { + options = { + type: 'basic' + } + } + + switch (options.type) { + case 'basic': + var str = btoa(user + ':' + pass); + this.set('Authorization', 'Basic ' + str); + break; + + case 'auto': + this.username = user; + this.password = pass; + break; + } + return this; +}; + +/** +* Add query-string `val`. +* +* Examples: +* +* request.get('/shoes') +* .query('size=10') +* .query({ color: 'blue' }) +* +* @param {Object|String} val +* @return {Request} for chaining +* @api public +*/ + +Request.prototype.query = function(val){ + if ('string' != typeof val) val = serialize(val); + if (val) this._query.push(val); + return this; +}; + +/** + * Queue the given `file` as an attachment to the specified `field`, + * with optional `filename`. + * + * ``` js + * request.post('/upload') + * .attach(new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"})) + * .end(callback); + * ``` + * + * @param {String} field + * @param {Blob|File} file + * @param {String} filename + * @return {Request} for chaining + * @api public + */ + +Request.prototype.attach = function(field, file, filename){ + this._getFormData().append(field, file, filename || file.name); + return this; +}; + +Request.prototype._getFormData = function(){ + if (!this._formData) { + this._formData = new root.FormData(); + } + return this._formData; +}; + +/** + * Send `data` as the request body, defaulting the `.type()` to "json" when + * an object is given. + * + * Examples: + * + * // manual json + * request.post('/user') + * .type('json') + * .send('{"name":"tj"}') + * .end(callback) + * + * // auto json + * request.post('/user') + * .send({ name: 'tj' }) + * .end(callback) + * + * // manual x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send('name=tj') + * .end(callback) + * + * // auto x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send({ name: 'tj' }) + * .end(callback) + * + * // defaults to x-www-form-urlencoded + * request.post('/user') + * .send('name=tobi') + * .send('species=ferret') + * .end(callback) + * + * @param {String|Object} data + * @return {Request} for chaining + * @api public + */ + +Request.prototype.send = function(data){ + var obj = isObject(data); + var type = this._header['content-type']; + + // merge + if (obj && isObject(this._data)) { + for (var key in data) { + this._data[key] = data[key]; + } + } else if ('string' == typeof data) { + if (!type) this.type('form'); + type = this._header['content-type']; + if ('application/x-www-form-urlencoded' == type) { + this._data = this._data + ? this._data + '&' + data + : data; + } else { + this._data = (this._data || '') + data; + } + } else { + this._data = data; + } + + if (!obj || isHost(data)) return this; + if (!type) this.type('json'); + return this; +}; + +/** + * @deprecated + */ +Response.prototype.parse = function serialize(fn){ + if (root.console) { + console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"); + } + this.serialize(fn); + return this; +}; + +Response.prototype.serialize = function serialize(fn){ + this._parser = fn; + return this; +}; + +/** + * Invoke the callback with `err` and `res` + * and handle arity check. + * + * @param {Error} err + * @param {Response} res + * @api private + */ + +Request.prototype.callback = function(err, res){ + var fn = this._callback; + this.clearTimeout(); + fn(err, res); +}; + +/** + * Invoke callback with x-domain error. + * + * @api private + */ + +Request.prototype.crossDomainError = function(){ + var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.'); + err.crossDomain = true; + + err.status = this.status; + err.method = this.method; + err.url = this.url; + + this.callback(err); +}; + +/** + * Invoke callback with timeout error. + * + * @api private + */ + +Request.prototype.timeoutError = function(){ + var timeout = this._timeout; + var err = new Error('timeout of ' + timeout + 'ms exceeded'); + err.timeout = timeout; + this.callback(err); +}; + +/** + * Enable transmission of cookies with x-domain requests. + * + * Note that for this to work the origin must not be + * using "Access-Control-Allow-Origin" with a wildcard, + * and also must set "Access-Control-Allow-Credentials" + * to "true". + * + * @api public + */ + +Request.prototype.withCredentials = function(){ + this._withCredentials = true; + return this; +}; + +/** + * Initiate request, invoking callback `fn(res)` + * with an instanceof `Response`. + * + * @param {Function} fn + * @return {Request} for chaining + * @api public + */ + +Request.prototype.end = function(fn){ + var self = this; + var xhr = this.xhr = request.getXHR(); + var query = this._query.join('&'); + var timeout = this._timeout; + var data = this._formData || this._data; + + // store callback + this._callback = fn || noop; + + // state change + xhr.onreadystatechange = function(){ + if (4 != xhr.readyState) return; + + // In IE9, reads to any property (e.g. status) off of an aborted XHR will + // result in the error "Could not complete the operation due to error c00c023f" + var status; + try { status = xhr.status } catch(e) { status = 0; } + + if (0 == status) { + if (self.timedout) return self.timeoutError(); + if (self.aborted) return; + return self.crossDomainError(); + } + self.emit('end'); + }; + + // progress + var handleProgress = function(e){ + if (e.total > 0) { + e.percent = e.loaded / e.total * 100; + } + e.direction = 'download'; + self.emit('progress', e); + }; + if (this.hasListeners('progress')) { + xhr.onprogress = handleProgress; + } + try { + if (xhr.upload && this.hasListeners('progress')) { + xhr.upload.onprogress = handleProgress; + } + } catch(e) { + // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist. + // Reported here: + // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context + } + + // timeout + if (timeout && !this._timer) { + this._timer = setTimeout(function(){ + self.timedout = true; + self.abort(); + }, timeout); + } + + // querystring + if (query) { + query = request.serializeObject(query); + this.url += ~this.url.indexOf('?') + ? '&' + query + : '?' + query; + } + + // initiate request + if (this.username && this.password) { + xhr.open(this.method, this.url, true, this.username, this.password); + } else { + xhr.open(this.method, this.url, true); + } + + // CORS + if (this._withCredentials) xhr.withCredentials = true; + + // body + if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) { + // serialize stuff + var contentType = this._header['content-type']; + var serialize = this._parser || request.serialize[contentType ? contentType.split(';')[0] : '']; + if (!serialize && isJSON(contentType)) serialize = request.serialize['application/json']; + if (serialize) data = serialize(data); + } + + // set header fields + for (var field in this.header) { + if (null == this.header[field]) continue; + xhr.setRequestHeader(field, this.header[field]); + } + + if (this._responseType) { + xhr.responseType = this._responseType; + } + + // send stuff + this.emit('request', this); + + // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing) + // We need null here if data is undefined + xhr.send(typeof data !== 'undefined' ? data : null); + return this; +}; + + +/** + * Expose `Request`. + */ + +request.Request = Request; + +/** + * GET `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.get = function(url, data, fn){ + var req = request('GET', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.query(data); + if (fn) req.end(fn); + return req; +}; + +/** + * HEAD `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.head = function(url, data, fn){ + var req = request('HEAD', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * DELETE `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Function} fn + * @return {Request} + * @api public + */ + +function del(url, fn){ + var req = request('DELETE', url); + if (fn) req.end(fn); + return req; +}; + +request['del'] = del; +request['delete'] = del; + +/** + * PATCH `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed} data + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.patch = function(url, data, fn){ + var req = request('PATCH', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * POST `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed} data + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.post = function(url, data, fn){ + var req = request('POST', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * PUT `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.put = function(url, data, fn){ + var req = request('PUT', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/is-object.js b/node_modules/supertest/node_modules/superagent/lib/is-object.js new file mode 100644 index 0000000..37499a3 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/is-object.js @@ -0,0 +1,13 @@ +/** + * Check if `obj` is an object. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + +function isObject(obj) { + return null != obj && 'object' == typeof obj; +} + +module.exports = isObject; diff --git a/node_modules/supertest/node_modules/superagent/lib/node/agent.js b/node_modules/supertest/node_modules/superagent/lib/node/agent.js new file mode 100644 index 0000000..a88dfa3 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/agent.js @@ -0,0 +1,82 @@ + +/** + * Module dependencies. + */ + +var CookieJar = require('cookiejar').CookieJar; +var CookieAccess = require('cookiejar').CookieAccessInfo; +var parse = require('url').parse; +var request = require('./index'); +var methods = require('methods'); + +/** + * Expose `Agent`. + */ + +module.exports = Agent; + +/** + * Initialize a new `Agent`. + * + * @api public + */ + +function Agent(options) { + if (!(this instanceof Agent)) return new Agent(options); + if (options) this._ca = options.ca; + this.jar = new CookieJar; +} + +/** + * Save the cookies in the given `res` to + * the agent's cookie jar for persistence. + * + * @param {Response} res + * @api private + */ + +Agent.prototype.saveCookies = function(res){ + var cookies = res.headers['set-cookie']; + if (cookies) this.jar.setCookies(cookies); +}; + +/** + * Attach cookies when available to the given `req`. + * + * @param {Request} req + * @api private + */ + +Agent.prototype.attachCookies = function(req){ + var url = parse(req.url); + var access = CookieAccess(url.hostname, url.pathname, 'https:' == url.protocol); + var cookies = this.jar.getCookies(access).toValueString(); + req.cookies = cookies; +}; + +// generate HTTP verb methods +if (methods.indexOf('del') == -1) { + // create a copy so we don't cause conflicts with + // other packages using the methods package and + // npm 3.x + methods = methods.slice(0); + methods.push('del'); +} +methods.forEach(function(method){ + var name = method; + method = 'del' == method ? 'delete' : method; + + method = method.toUpperCase(); + Agent.prototype[name] = function(url, fn){ + var req = request(method, url); + req.ca(this._ca); + + req.on('response', this.saveCookies.bind(this)); + req.on('redirect', this.saveCookies.bind(this)); + req.on('redirect', this.attachCookies.bind(this, req)); + this.attachCookies(req); + + fn && req.end(fn); + return req; + }; +}); diff --git a/node_modules/supertest/node_modules/superagent/lib/node/index.js b/node_modules/supertest/node_modules/superagent/lib/node/index.js new file mode 100644 index 0000000..b6ddec3 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/index.js @@ -0,0 +1,1093 @@ + +/** + * Module dependencies. + */ + +var debug = require('debug')('superagent'); +var formidable = require('formidable'); +var FormData = require('form-data'); +var Response = require('./response'); +var parse = require('url').parse; +var format = require('url').format; +var resolve = require('url').resolve; +var methods = require('methods'); +var Stream = require('stream'); +var utils = require('./utils'); +var extend = require('extend'); +var Part = require('./part'); +var mime = require('mime'); +var https = require('https'); +var http = require('http'); +var fs = require('fs'); +var qs = require('qs'); +var zlib = require('zlib'); +var util = require('util'); +var pkg = require('../../package.json'); +var requestBase = require('../request-base'); +var isObject = require('../is-object'); + +/** + * Expose the request function. + */ + +var request = exports = module.exports = require('../request').bind(null, Request); + +/** + * Expose the agent function + */ + +exports.agent = require('./agent'); + +/** + * Expose `Part`. + */ + +exports.Part = Part; + +/** + * Noop. + */ + +function noop(){}; + +/** + * Expose `Response`. + */ + +exports.Response = Response; + +/** + * Define "form" mime type. + */ + +mime.define({ + 'application/x-www-form-urlencoded': ['form', 'urlencoded', 'form-data'] +}); + +/** + * Protocol map. + */ + +exports.protocols = { + 'http:': http, + 'https:': https +}; + +/** + * Default serialization map. + * + * superagent.serialize['application/xml'] = function(obj){ + * return 'generated xml here'; + * }; + * + */ + +exports.serialize = { + 'application/x-www-form-urlencoded': qs.stringify, + 'application/json': JSON.stringify +}; + +/** + * Default parsers. + * + * superagent.parse['application/xml'] = function(res, fn){ + * fn(null, res); + * }; + * + */ + +exports.parse = require('./parsers'); + +/** + * Initialize internal header tracking properties on a request instance. + * + * @param {Object} req the instance + * @api private + */ +function _initHeaders(req) { + var ua = 'node-superagent/' + pkg.version; + req._header = { // coerces header names to lowercase + 'user-agent': ua + }; + req.header = { // preserves header name case + 'User-Agent': ua + }; +} + +/** + * Initialize a new `Request` with the given `method` and `url`. + * + * @param {String} method + * @param {String|Object} url + * @api public + */ + +function Request(method, url) { + Stream.call(this); + var self = this; + if ('string' != typeof url) url = format(url); + this._agent = false; + this._formData = null; + this.method = method; + this.url = url; + _initHeaders(this); + this.writable = true; + this._redirects = 0; + this.redirects(5); + this.cookies = ''; + this.qs = {}; + this.qsRaw = []; + this._redirectList = []; + this._streamRequest = false; + this.on('end', this.clearTimeout.bind(this)); +} + +/** + * Inherit from `Stream` (which inherits from `EventEmitter`). + * Mixin `requestBase`. + */ +util.inherits(Request, Stream); +for (var key in requestBase) { + Request.prototype[key] = requestBase[key]; +} + +/** + * Queue the given `file` as an attachment to the specified `field`, + * with optional `filename`. + * + * ``` js + * request.post('http://localhost/upload') + * .attach(new Buffer('<b>Hello world</b>'), 'hello.html') + * .end(callback); + * ``` + * + * A filename may also be used: + * + * ``` js + * request.post('http://localhost/upload') + * .attach('files', 'image.jpg') + * .end(callback); + * ``` + * + * @param {String} field + * @param {String|fs.ReadStream|Buffer} file + * @param {String} filename + * @return {Request} for chaining + * @api public + */ + +Request.prototype.attach = function(field, file, filename){ + if ('string' == typeof file) { + if (!filename) filename = file; + debug('creating `fs.ReadStream` instance for file: %s', file); + file = fs.createReadStream(file); + } else if (!filename && file.path) { + filename = file.path; + } + this._getFormData().append(field, file, { filename: filename }); + return this; +}; + +Request.prototype._getFormData = function() { + if (!this._formData) { + this._formData = new FormData(); + this._formData.on('error', function(err) { + this.emit('error', err); + this.abort(); + }.bind(this)); + } + return this._formData; +}; + +/** + * Set the max redirects to `n`. + * + * @param {Number} n + * @return {Request} for chaining + * @api public + */ + +Request.prototype.redirects = function(n){ + debug('max redirects %s', n); + this._maxRedirects = n; + return this; +}; + +/** + * Return a new `Part` for this request. + * + * @return {Part} + * @api public + * @deprecated pass a readable stream in to `Request#attach()` instead + */ + +Request.prototype.part = util.deprecate(function(){ + return new Part(this); +}, '`Request#part()` is deprecated. ' + + 'Pass a readable stream in to `Request#attach()` instead.'); + +/** + * Gets/sets the `Agent` to use for this HTTP request. The default (if this + * function is not called) is to opt out of connection pooling (`agent: false`). + * + * @param {http.Agent} agent + * @return {http.Agent} + * @api public + */ + +Request.prototype.agent = function(agent){ + if (!arguments.length) return this._agent; + this._agent = agent; + return this; +}; + +/** + * Set _Content-Type_ response header passed through `mime.lookup()`. + * + * Examples: + * + * request.post('/') + * .type('xml') + * .send(xmlstring) + * .end(callback); + * + * request.post('/') + * .type('json') + * .send(jsonstring) + * .end(callback); + * + * request.post('/') + * .type('application/json') + * .send(jsonstring) + * .end(callback); + * + * @param {String} type + * @return {Request} for chaining + * @api public + */ + +Request.prototype.type = function(type){ + return this.set('Content-Type', ~type.indexOf('/') + ? type + : mime.lookup(type)); +}; + +/** + * Set _Accept_ response header passed through `mime.lookup()`. + * + * Examples: + * + * superagent.types.json = 'application/json'; + * + * request.get('/agent') + * .accept('json') + * .end(callback); + * + * request.get('/agent') + * .accept('application/json') + * .end(callback); + * + * @param {String} accept + * @return {Request} for chaining + * @api public + */ + +Request.prototype.accept = function(type){ + return this.set('Accept', ~type.indexOf('/') + ? type + : mime.lookup(type)); +}; + +/** + * Add query-string `val`. + * + * Examples: + * + * request.get('/shoes') + * .query('size=10') + * .query({ color: 'blue' }) + * + * @param {Object|String} val + * @return {Request} for chaining + * @api public + */ + +Request.prototype.query = function(val){ + if ('string' == typeof val) { + this.qsRaw.push(val); + return this; + } + + extend(this.qs, val); + return this; +}; + +/** + * Send `data` as the request body, defaulting the `.type()` to "json" when + * an object is given. + * + * Examples: + * + * // manual json + * request.post('/user') + * .type('json') + * .send('{"name":"tj"}') + * .end(callback) + * + * // auto json + * request.post('/user') + * .send({ name: 'tj' }) + * .end(callback) + * + * // manual x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send('name=tj') + * .end(callback) + * + * // auto x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send({ name: 'tj' }) + * .end(callback) + * + * // string defaults to x-www-form-urlencoded + * request.post('/user') + * .send('name=tj') + * .send('foo=bar') + * .send('bar=baz') + * .end(callback) + * + * @param {String|Object} data + * @return {Request} for chaining + * @api public + */ + +Request.prototype.send = function(data){ + var obj = isObject(data); + var type = this._header['content-type']; + // merge + if (obj && isObject(this._data)) { + for (var key in data) { + this._data[key] = data[key]; + } + // string + } else if ('string' == typeof data) { + // default to x-www-form-urlencoded + if (!type) this.type('form'); + type = this._header['content-type']; + + // concat & + if ('application/x-www-form-urlencoded' == type) { + this._data = this._data + ? this._data + '&' + data + : data; + } else { + this._data = (this._data || '') + data; + } + } else { + this._data = data; + } + + if (!obj) return this; + + // default to json + if (!type) this.type('json'); + return this; +}; + +/** + * Write raw `data` / `encoding` to the socket. + * + * @param {Buffer|String} data + * @param {String} encoding + * @return {Boolean} + * @api public + */ + +Request.prototype.write = function(data, encoding){ + var req = this.request(); + if (!this._streamRequest) { + this._streamRequest = true; + try { + // ensure querystring is appended before headers are sent + this.appendQueryString(req); + } catch (e) { + return this.emit('error', e); + } + } + return req.write(data, encoding); +}; + +/** + * Pipe the request body to `stream`. + * + * @param {Stream} stream + * @param {Object} options + * @return {Stream} + * @api public + */ + +Request.prototype.pipe = function(stream, options){ + this.piped = true; // HACK... + this.buffer(false); + var self = this; + this.end().req.on('response', function(res){ + // redirect + var redirect = isRedirect(res.statusCode); + if (redirect && self._redirects++ != self._maxRedirects) { + return self.redirect(res).pipe(stream, options); + } + + if (self._shouldUnzip(res)) { + res.pipe(zlib.createUnzip()).pipe(stream, options); + } else { + res.pipe(stream, options); + } + res.on('end', function(){ + self.emit('end'); + }); + }); + return stream; +}; + +/** + * Enable / disable buffering. + * + * @return {Boolean} [val] + * @return {Request} for chaining + * @api public + */ + +Request.prototype.buffer = function(val){ + this._buffer = false === val + ? false + : true; + return this; +}; + +/** + * Abort and clear timeout. + * + * @api public + */ + +Request.prototype.abort = function(){ + debug('abort %s %s', this.method, this.url); + this._aborted = true; + this.clearTimeout(); + this.req.abort(); + this.emit('abort'); +}; + +/** + * Redirect to `url + * + * @param {IncomingMessage} res + * @return {Request} for chaining + * @api private + */ + +Request.prototype.redirect = function(res){ + var url = res.headers.location; + if (!url) { + return this.callback(new Error('No location header for redirect'), res); + } + + debug('redirect %s -> %s', this.url, url); + + // location + url = resolve(this.url, url); + + // ensure the response is being consumed + // this is required for Node v0.10+ + res.resume(); + + var headers = this.req._headers; + + var shouldStripCookie = parse(url).host !== parse(this.url).host; + + // implementation of 302 following defacto standard + if (res.statusCode == 301 || res.statusCode == 302){ + // strip Content-* related fields + // in case of POST etc + headers = utils.cleanHeader(this.req._headers, shouldStripCookie); + + // force GET + this.method = 'HEAD' == this.method + ? 'HEAD' + : 'GET'; + + // clear data + this._data = null; + } + // 303 is always GET + if (res.statusCode == 303) { + // strip Content-* related fields + // in case of POST etc + headers = utils.cleanHeader(this.req._headers, shouldStripCookie); + + // force method + this.method = 'GET'; + + // clear data + this._data = null; + } + // 307 preserves method + // 308 preserves method + delete headers.host; + + delete this.req; + delete this._formData; + + // remove all add header except User-Agent + _initHeaders(this) + + // redirect + this.url = url; + this._redirectList.push(url); + this.emit('redirect', res); + this.qs = {}; + this.qsRaw = []; + this.set(headers); + this.end(this._callback); + return this; +}; + +/** + * Set Authorization field value with `user` and `pass`. + * + * Examples: + * + * .auth('tobi', 'learnboost') + * .auth('tobi:learnboost') + * .auth('tobi') + * + * @param {String} user + * @param {String} pass + * @return {Request} for chaining + * @api public + */ + +Request.prototype.auth = function(user, pass){ + if (1 === arguments.length) pass = ''; + if (!~user.indexOf(':')) user = user + ':'; + var str = new Buffer(user + pass).toString('base64'); + return this.set('Authorization', 'Basic ' + str); +}; + +/** + * Set the certificate authority option for https request. + * + * @param {Buffer | Array} cert + * @return {Request} for chaining + * @api public + */ + +Request.prototype.ca = function(cert){ + this._ca = cert; + return this; +}; + +/** + * Return an http[s] request. + * + * @return {OutgoingMessage} + * @api private + */ + +Request.prototype.request = function(){ + if (this.req) return this.req; + + var self = this; + var options = {}; + var data = this._data; + var url = this.url; + + // default to http:// + if (0 != url.indexOf('http')) url = 'http://' + url; + url = parse(url); + + // options + options.method = this.method; + options.port = url.port; + options.path = url.pathname; + options.host = url.hostname; + options.ca = this._ca; + options.agent = this._agent; + + // initiate request + var mod = exports.protocols[url.protocol]; + + // request + var req = this.req = mod.request(options); + if ('HEAD' != options.method) req.setHeader('Accept-Encoding', 'gzip, deflate'); + this.protocol = url.protocol; + this.host = url.host; + + // expose events + req.on('drain', function(){ self.emit('drain'); }); + + req.on('error', function(err){ + // flag abortion here for out timeouts + // because node will emit a faux-error "socket hang up" + // when request is aborted before a connection is made + if (self._aborted) return; + // if we've recieved a response then we don't want to let + // an error in the request blow up the response + if (self.response) return; + self.callback(err); + }); + + // auth + if (url.auth) { + var auth = url.auth.split(':'); + this.auth(auth[0], auth[1]); + } + + // query + if (url.search) + this.query(url.search.substr(1)); + + // add cookies + if (this.cookies) req.setHeader('Cookie', this.cookies); + + for (var key in this.header) { + req.setHeader(key, this.header[key]); + } + + return req; +}; + +/** + * Invoke the callback with `err` and `res` + * and handle arity check. + * + * @param {Error} err + * @param {Response} res + * @api private + */ + +Request.prototype.callback = function(err, res){ + // Avoid the error which is emitted from 'socket hang up' to cause the fn undefined error on JS runtime. + var fn = this._callback || noop; + this.clearTimeout(); + if (this.called) return console.warn('double callback!'); + this.called = true; + + if (err) { + err.response = res; + } + + // only emit error event if there is a listener + // otherwise we assume the callback to `.end()` will get the error + if (err && this.listeners('error').length > 0) this.emit('error', err); + + if (err) { + return fn(err, res); + } + + if (res && res.status >= 200 && res.status < 300) { + return fn(err, res); + } + + var msg = 'Unsuccessful HTTP response'; + if (res) { + msg = http.STATUS_CODES[res.status] || msg; + } + var new_err = new Error(msg); + new_err.original = err; + new_err.response = res; + new_err.status = (res) ? res.status : undefined; + + fn(err || new_err, res); +}; + +/** + * Compose querystring to append to req.path + * + * @return {String} querystring + * @api private + */ + +Request.prototype.appendQueryString = function(req){ + var querystring = qs.stringify(this.qs, { indices: false }); + querystring += ((querystring.length && this.qsRaw.length) ? '&' : '') + this.qsRaw.join('&'); + req.path += querystring.length + ? (~req.path.indexOf('?') ? '&' : '?') + querystring + : ''; +}; + +/** + * Initiate request, invoking callback `fn(err, res)` + * with an instanceof `Response`. + * + * @param {Function} fn + * @return {Request} for chaining + * @api public + */ + +/** +* Client API parity, irrelevant in a Node context. +* +* @api public +*/ + +Request.prototype.withCredentials = function(){ + return this; +}; + +Request.prototype.end = function(fn){ + var self = this; + var data = this._data; + var req = this.request(); + var buffer = this._buffer; + var method = this.method; + var timeout = this._timeout; + debug('%s %s', this.method, this.url); + + // store callback + this._callback = fn || noop; + + // querystring + try { + this.appendQueryString(req); + } catch (e) { + return this.callback(e); + } + + // timeout + if (timeout && !this._timer) { + debug('timeout %sms %s %s', timeout, this.method, this.url); + this._timer = setTimeout(function(){ + var err = new Error('timeout of ' + timeout + 'ms exceeded'); + err.timeout = timeout; + err.code = 'ECONNABORTED'; + self.abort(); + self.callback(err); + }, timeout); + } + + // body + if ('HEAD' != method && !req._headerSent) { + // serialize stuff + if ('string' != typeof data) { + var contentType = req.getHeader('Content-Type') + // Parse out just the content type from the header (ignore the charset) + if (contentType) contentType = contentType.split(';')[0] + var serialize = exports.serialize[contentType]; + if (!serialize && isJSON(contentType)) serialize = exports.serialize['application/json']; + if (serialize) data = serialize(data); + } + + // content-length + if (data && !req.getHeader('Content-Length')) { + req.setHeader('Content-Length', Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)); + } + } + + // response + req.on('response', function(res){ + debug('%s %s -> %s', self.method, self.url, res.statusCode); + var max = self._maxRedirects; + var mime = utils.type(res.headers['content-type'] || '') || 'text/plain'; + var len = res.headers['content-length']; + var type = mime.split('/'); + var subtype = type[1]; + var type = type[0]; + var multipart = 'multipart' == type; + var redirect = isRedirect(res.statusCode); + var parser = self._parser; + + self.res = res; + + if ('HEAD' == self.method) { + var response = new Response(self); + self.response = response; + response.redirects = self._redirectList; + self.emit('response', response); + self.callback(null, response); + self.emit('end'); + return; + } + + if (self.piped) { + return; + } + + // redirect + if (redirect && self._redirects++ != max) { + return self.redirect(res); + } + + // zlib support + if (self._shouldUnzip(res)) { + utils.unzip(req, res); + } + + + // don't buffer multipart + if (multipart) buffer = false; + + // TODO: make all parsers take callbacks + if (!parser && multipart) { + var form = new formidable.IncomingForm; + + form.parse(res, function(err, fields, files){ + if (err) return self.callback(err); + var response = new Response(self); + self.response = response; + response.body = fields; + response.files = files; + response.redirects = self._redirectList; + self.emit('end'); + self.callback(null, response); + }); + return; + } + + // check for images, one more special treatment + if (!parser && isImage(mime)) { + exports.parse.image(res, function(err, obj){ + if (err) return self.callback(err); + var response = new Response(self); + self.response = response; + response.body = obj; + response.redirects = self._redirectList; + self.emit('end'); + self.callback(null, response); + }); + return; + } + + // by default only buffer text/*, json and messed up thing from hell + if (null == buffer && isText(mime) || isJSON(mime)) buffer = true; + + // parser + var parse = 'text' == type + ? exports.parse.text + : exports.parse[mime]; + + // everyone wants their own white-labeled json + if (!parse && isJSON(mime)) parse = exports.parse['application/json']; + + // buffered response + if (buffer) parse = parse || exports.parse.text; + + // explicit parser + if (parser) parse = parser; + + // parse + if (parse) { + try { + parse(res, function(err, obj){ + if (err && !self._aborted) self.callback(err); + res.body = obj; + }); + } catch (err) { + self.callback(err); + return; + } + } + + // unbuffered + if (!buffer) { + debug('unbuffered %s %s', self.method, self.url); + self.res = res; + var response = new Response(self); + self.response = response; + response.redirects = self._redirectList; + self.emit('response', response); + self.callback(null, response); + if (multipart) return // allow multipart to handle end event + res.on('end', function(){ + debug('end %s %s', self.method, self.url); + self.emit('end'); + }) + return; + } + + // terminating events + self.res = res; + res.on('error', function(err){ + self.callback(err, null); + }); + res.on('end', function(){ + debug('end %s %s', self.method, self.url); + // TODO: unless buffering emit earlier to stream + var response = new Response(self); + self.response = response; + response.redirects = self._redirectList; + self.emit('response', response); + self.callback(null, response); + self.emit('end'); + }); + }); + + this.emit('request', this); + + // if a FormData instance got created, then we send that as the request body + var formData = this._formData; + if (formData) { + + // set headers + var headers = formData.getHeaders(); + for (var i in headers) { + debug('setting FormData header: "%s: %s"', i, headers[i]); + req.setHeader(i, headers[i]); + } + + // attempt to get "Content-Length" header + formData.getLength(function(err, length) { + // TODO: Add chunked encoding when no length (if err) + + debug('got FormData Content-Length: %s', length); + if ('number' == typeof length) { + req.setHeader('Content-Length', length); + } + + var getProgressMonitor = function () { + var lengthComputable = true; + var total = req.getHeader('Content-Length'); + var loaded = 0; + + var progress = new Stream.Transform(); + progress._transform = function (chunk, encoding, cb) { + loaded += chunk.length; + self.emit('progress', { + direction: 'upload', + lengthComputable: lengthComputable, + loaded: loaded, + total: total + }); + cb(null, chunk); + }; + return progress; + }; + formData.pipe(getProgressMonitor()).pipe(req); + }); + } else { + req.end(data); + } + + return this; +}; + +/** + * Check whether response has a non-0-sized gzip-encoded body + */ +Request.prototype._shouldUnzip = function(res){ + if (res.statusCode === 204 || res.statusCode === 304) { + // These aren't supposed to have any body + return false; + } + + // header content is a string, and distinction between 0 and no information is crucial + if ('0' === res.headers['content-length']) { + // We know that the body is empty (unfortunately, this check does not cover chunked encoding) + return false; + } + + // console.log(res); + return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']); +}; + +/** + * To json. + * + * @return {Object} + * @api public + */ + +Request.prototype.toJSON = function(){ + return { + method: this.method, + url: this.url, + data: this._data + }; +}; + +/** + * Expose `Request`. + */ + +exports.Request = Request; + +// generate HTTP verb methods +if (methods.indexOf('del') == -1) { + // create a copy so we don't cause conflicts with + // other packages using the methods package and + // npm 3.x + methods = methods.slice(0); + methods.push('del'); +} +methods.forEach(function(method){ + var name = method; + method = 'del' == method ? 'delete' : method; + + method = method.toUpperCase(); + request[name] = function(url, data, fn){ + var req = request(method, url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + fn && req.end(fn); + return req; + }; +}); + +/** + * Check if `mime` is text and should be buffered. + * + * @param {String} mime + * @return {Boolean} + * @api public + */ + +function isText(mime) { + var parts = mime.split('/'); + var type = parts[0]; + var subtype = parts[1]; + + return 'text' == type + || 'x-www-form-urlencoded' == subtype; +} + +/** + * Check if `mime` is image + * + * @param {String} mime + * @return {Boolean} + * @api public + */ + +function isImage(mime) { + var parts = mime.split('/'); + var type = parts[0]; + var subtype = parts[1]; + + return 'image' == type; +} + +/** + * Check if `mime` is json or has +json structured syntax suffix. + * + * @param {String} mime + * @return {Boolean} + * @api private + */ + +function isJSON(mime) { + return /[\/+]json\b/.test(mime); +} + +/** + * Check if we should follow the redirect `code`. + * + * @param {Number} code + * @return {Boolean} + * @api private + */ + +function isRedirect(code) { + return ~[301, 302, 303, 305, 307, 308].indexOf(code); +} diff --git a/node_modules/supertest/node_modules/superagent/lib/node/parsers/image.js b/node_modules/supertest/node_modules/superagent/lib/node/parsers/image.js new file mode 100644 index 0000000..b3e0ebc --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/parsers/image.js @@ -0,0 +1,10 @@ +module.exports = function(res, fn){ + var data = []; // Binary data needs binary storage + + res.on('data', function(chunk){ + data.push(chunk); + }); + res.on('end', function () { + fn(null, Buffer.concat(data)); + }); +};
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/lib/node/parsers/index.js b/node_modules/supertest/node_modules/superagent/lib/node/parsers/index.js new file mode 100644 index 0000000..61a98cd --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/parsers/index.js @@ -0,0 +1,5 @@ + +exports['application/x-www-form-urlencoded'] = require('./urlencoded'); +exports['application/json'] = require('./json'); +exports.text = require('./text'); +exports.image = require('./image'); diff --git a/node_modules/supertest/node_modules/superagent/lib/node/parsers/json.js b/node_modules/supertest/node_modules/superagent/lib/node/parsers/json.js new file mode 100644 index 0000000..b71662d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/parsers/json.js @@ -0,0 +1,19 @@ + +module.exports = function parseJSON(res, fn){ + res.text = ''; + res.setEncoding('utf8'); + res.on('data', function(chunk){ res.text += chunk;}); + res.on('end', function(){ + try { + var body = res.text && JSON.parse(res.text); + } catch (e) { + var err = e; + // issue #675: return the raw response if the response parsing fails + err.rawResponse = res.text || null; + // issue #876: return the http status code if the response parsing fails + err.statusCode = res.statusCode; + } finally { + fn(err, body); + } + }); +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/node/parsers/text.js b/node_modules/supertest/node_modules/superagent/lib/node/parsers/text.js new file mode 100644 index 0000000..03575c6 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/parsers/text.js @@ -0,0 +1,7 @@ + +module.exports = function(res, fn){ + res.text = ''; + res.setEncoding('utf8'); + res.on('data', function(chunk){ res.text += chunk; }); + res.on('end', fn); +};
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/lib/node/parsers/urlencoded.js b/node_modules/supertest/node_modules/superagent/lib/node/parsers/urlencoded.js new file mode 100644 index 0000000..245c665 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/parsers/urlencoded.js @@ -0,0 +1,19 @@ + +/** + * Module dependencies. + */ + +var qs = require('qs'); + +module.exports = function(res, fn){ + res.text = ''; + res.setEncoding('ascii'); + res.on('data', function(chunk){ res.text += chunk; }); + res.on('end', function(){ + try { + fn(null, qs.parse(res.text)); + } catch (err) { + fn(err); + } + }); +};
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/lib/node/part.js b/node_modules/supertest/node_modules/superagent/lib/node/part.js new file mode 100644 index 0000000..d7123bb --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/part.js @@ -0,0 +1,149 @@ + +/** + * Module dependencies. + */ + +var util = require('util'); +var mime = require('mime'); +var FormData = require('form-data'); +var PassThrough = require('readable-stream/passthrough'); + +/** + * Initialize a new `Part` for the given `req`. + * + * @param {Request} req + * @api public + * @deprecated pass a readable stream in to `Request#attach()` instead + */ + +var Part = function (req) { + PassThrough.call(this); + this._req = req; + this._attached = false; + this._name = null; + this._type = null; + this._header = null; + this._filename = null; + + this.once('pipe', this._attach.bind(this)); +}; +Part = util.deprecate(Part, 'The `Part()` constructor is deprecated. ' + + 'Pass a readable stream in to `Request#attach()` instead.'); + +/** + * Inherit from `PassThrough`. + */ + +util.inherits(Part, PassThrough); + +/** + * Expose `Part`. + */ + +module.exports = Part; + +/** + * Set header `field` to `val`. + * + * @param {String} field + * @param {String} val + * @return {Part} for chaining + * @api public + */ + +Part.prototype.set = function(field, val){ + //if (!this._header) this._header = {}; + //this._header[field] = val; + //return this; + throw new TypeError('setting custom form-data part headers is unsupported'); +}; + +/** + * Set _Content-Type_ response header passed through `mime.lookup()`. + * + * Examples: + * + * res.type('html'); + * res.type('.html'); + * + * @param {String} type + * @return {Part} for chaining + * @api public + */ + +Part.prototype.type = function(type){ + var lookup = mime.lookup(type); + this._type = lookup; + //this.set('Content-Type', lookup); + return this; +}; + +/** + * Set the "name" portion for the _Content-Disposition_ header field. + * + * @param {String} name + * @return {Part} for chaining + * @api public + */ + +Part.prototype.name = function(name){ + this._name = name; + return this; +}; + +/** + * Set _Content-Disposition_ header field to _attachment_ with `filename` + * and field `name`. + * + * @param {String} name + * @param {String} filename + * @return {Part} for chaining + * @api public + */ + +Part.prototype.attachment = function(name, filename){ + this.name(name); + if (filename) { + this.type(filename); + this._filename = filename; + } + return this; +}; + +/** + * Calls `FormData#append()` on the Request instance's FormData object. + * + * Gets called implicitly upon the first `write()` call, or the "pipe" event. + * + * @api private + */ + +Part.prototype._attach = function(){ + if (this._attached) return; + this._attached = true; + + if (!this._name) throw new Error('must call `Part#name()` first!'); + + // add `this` Stream's readable side as a stream for this Part + this._req._getFormData().append(this._name, this, { + contentType: this._type, + filename: this._filename + }); + + // restore PassThrough's default `write()` function now that we're setup + this.write = PassThrough.prototype.write; +}; + +/** + * Write `data` with `encoding`. + * + * @param {Buffer|String} data + * @param {String} encoding + * @return {Boolean} + * @api public + */ + +Part.prototype.write = function(){ + this._attach(); + return this.write.apply(this, arguments); +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/node/response.js b/node_modules/supertest/node_modules/superagent/lib/node/response.js new file mode 100644 index 0000000..b30c28b --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/response.js @@ -0,0 +1,210 @@ + +/** + * Module dependencies. + */ + +var util = require('util'); +var utils = require('./utils'); +var Stream = require('stream'); + +/** + * Expose `Response`. + */ + +module.exports = Response; + +/** + * Initialize a new `Response` with the given `xhr`. + * + * - set flags (.ok, .error, etc) + * - parse header + * + * @param {Request} req + * @param {Object} options + * @constructor + * @extends {Stream} + * @implements {ReadableStream} + * @api private + */ + +function Response(req, options) { + Stream.call(this); + options = options || {}; + var res = this.res = req.res; + this.request = req; + this.req = req.req; + this.links = {}; + this.text = res.text; + this.body = res.body !== undefined ? res.body : {}; + this.files = res.files || {}; + this.buffered = 'string' == typeof this.text; + this.header = this.headers = res.headers; + this.setStatusProperties(res.statusCode); + this.setHeaderProperties(this.header); + this.setEncoding = res.setEncoding.bind(res); + res.on('data', this.emit.bind(this, 'data')); + res.on('end', this.emit.bind(this, 'end')); + res.on('close', this.emit.bind(this, 'close')); + res.on('error', this.emit.bind(this, 'error')); +} + +/** + * Inherit from `Stream`. + */ + +util.inherits(Response, Stream); + +/** + * Get case-insensitive `field` value. + * + * @param {String} field + * @return {String} + * @api public + */ + +Response.prototype.get = function(field){ + return this.header[field.toLowerCase()]; +}; + +/** + * Implements methods of a `ReadableStream` + */ + +Response.prototype.destroy = function(err){ + this.res.destroy(err); +}; + +/** + * Pause. + */ + +Response.prototype.pause = function(){ + this.res.pause(); +}; + +/** + * Resume. + */ + +Response.prototype.resume = function(){ + this.res.resume(); +}; + +/** + * Return an `Error` representative of this response. + * + * @return {Error} + * @api public + */ + +Response.prototype.toError = function(){ + var req = this.req; + var method = req.method; + var path = req.path; + + var msg = 'cannot ' + method + ' ' + path + ' (' + this.status + ')'; + var err = new Error(msg); + err.status = this.status; + err.text = this.text; + err.method = method; + err.path = path; + + return err; +}; + +/** + * Set header related properties: + * + * - `.type` the content type without params + * + * A response of "Content-Type: text/plain; charset=utf-8" + * will provide you with a `.type` of "text/plain". + * + * @param {Object} header + * @api private + */ + +Response.prototype.setHeaderProperties = function(header){ + // TODO: moar! + // TODO: make this a util + + // content-type + var ct = this.header['content-type'] || ''; + + // params + var params = utils.params(ct); + for (var key in params) this[key] = params[key]; + + this.type = utils.type(ct); + + // links + try { + if (header.link) this.links = utils.parseLinks(header.link); + } catch (err) { + // ignore + } +}; + +/** + * Set flags such as `.ok` based on `status`. + * + * For example a 2xx response will give you a `.ok` of __true__ + * whereas 5xx will be __false__ and `.error` will be __true__. The + * `.clientError` and `.serverError` are also available to be more + * specific, and `.statusType` is the class of error ranging from 1..5 + * sometimes useful for mapping respond colors etc. + * + * "sugar" properties are also defined for common cases. Currently providing: + * + * - .noContent + * - .badRequest + * - .unauthorized + * - .notAcceptable + * - .notFound + * + * @param {Number} status + * @api private + */ + +Response.prototype.setStatusProperties = function(status){ + var type = status / 100 | 0; + + // status / class + this.status = this.statusCode = status; + this.statusType = type; + + // basics + this.info = 1 == type; + this.ok = 2 == type; + this.redirect = 3 == type; + this.clientError = 4 == type; + this.serverError = 5 == type; + this.error = (4 == type || 5 == type) + ? this.toError() + : false; + + // sugar + this.accepted = 202 == status; + this.noContent = 204 == status; + this.badRequest = 400 == status; + this.unauthorized = 401 == status; + this.notAcceptable = 406 == status; + this.forbidden = 403 == status; + this.notFound = 404 == status; +}; + +/** + * To json. + * + * @return {Object} + * @api public + */ + +Response.prototype.toJSON = function(){ + return { + req: this.request.toJSON(), + header: this.header, + status: this.status, + text: this.text + }; +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/node/utils.js b/node_modules/supertest/node_modules/superagent/lib/node/utils.js new file mode 100644 index 0000000..822929e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/node/utils.js @@ -0,0 +1,142 @@ + +/** + * Module dependencies. + */ + +var StringDecoder = require('string_decoder').StringDecoder; +var Stream = require('stream'); +var zlib; + +/** + * Require zlib module for Node 0.6+ + */ + +try { + zlib = require('zlib'); +} catch (e) { } + +/** + * Return the mime type for the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +exports.type = function(str){ + return str.split(/ *; */).shift(); +}; + +/** + * Return header field parameters. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.params = function(str){ + return str.split(/ *; */).reduce(function(obj, str){ + var parts = str.split(/ *= */); + var key = parts.shift(); + var val = parts.shift(); + + if (key && val) obj[key] = val; + return obj; + }, {}); +}; + +/** + * Parse Link header fields. + * + * @param {String} str + * @return {Object} + * @api private + */ + +exports.parseLinks = function(str){ + return str.split(/ *, */).reduce(function(obj, str){ + var parts = str.split(/ *; */); + var url = parts[0].slice(1, -1); + var rel = parts[1].split(/ *= */)[1].slice(1, -1); + obj[rel] = url; + return obj; + }, {}); +}; + +/** + * Buffers response data events and re-emits when they're unzipped. + * + * @param {Request} req + * @param {Response} res + * @api private + */ + +exports.unzip = function(req, res){ + if (!zlib) return; + + var unzip = zlib.createUnzip(); + var stream = new Stream; + var decoder; + + // make node responseOnEnd() happy + stream.req = req; + + unzip.on('error', function(err){ + stream.emit('error', err); + }); + + // pipe to unzip + res.pipe(unzip); + + // override `setEncoding` to capture encoding + res.setEncoding = function(type){ + decoder = new StringDecoder(type); + }; + + // decode upon decompressing with captured encoding + unzip.on('data', function(buf){ + if (decoder) { + var str = decoder.write(buf); + if (str.length) stream.emit('data', str); + } else { + stream.emit('data', buf); + } + }); + + unzip.on('end', function(){ + stream.emit('end'); + }); + + // override `on` to capture data listeners + var _on = res.on; + res.on = function(type, fn){ + if ('data' == type || 'end' == type) { + stream.on(type, fn); + } else if ('error' == type) { + stream.on(type, fn); + _on.call(res, type, fn); + } else { + _on.call(res, type, fn); + } + }; +}; + +/** + * Strip content related fields from `header`. + * + * @param {Object} header + * @return {Object} header + * @api private + */ + +exports.cleanHeader = function(header, shouldStripCookie){ + delete header['content-type']; + delete header['content-length']; + delete header['transfer-encoding']; + delete header['host']; + if (shouldStripCookie) { + delete header['cookie']; + } + return header; +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/request-base.js b/node_modules/supertest/node_modules/superagent/lib/request-base.js new file mode 100644 index 0000000..e923cef --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/request-base.js @@ -0,0 +1,166 @@ +/** + * Module of mixed-in functions shared between node and client code + */ +var isObject = require('./is-object'); + +/** + * Clear previous timeout. + * + * @return {Request} for chaining + * @api public + */ + +exports.clearTimeout = function _clearTimeout(){ + this._timeout = 0; + clearTimeout(this._timer); + return this; +}; + +/** + * Force given parser + * + * Sets the body parser no matter type. + * + * @param {Function} + * @api public + */ + +exports.parse = function parse(fn){ + this._parser = fn; + return this; +}; + +/** + * Set timeout to `ms`. + * + * @param {Number} ms + * @return {Request} for chaining + * @api public + */ + +exports.timeout = function timeout(ms){ + this._timeout = ms; + return this; +}; + +/** + * Faux promise support + * + * @param {Function} fulfill + * @param {Function} reject + * @return {Request} + */ + +exports.then = function then(fulfill, reject) { + return this.end(function(err, res) { + err ? reject(err) : fulfill(res); + }); +} + +/** + * Allow for extension + */ + +exports.use = function use(fn) { + fn(this); + return this; +} + + +/** + * Get request header `field`. + * Case-insensitive. + * + * @param {String} field + * @return {String} + * @api public + */ + +exports.get = function(field){ + return this._header[field.toLowerCase()]; +}; + +/** + * Get case-insensitive header `field` value. + * This is a deprecated internal API. Use `.get(field)` instead. + * + * (getHeader is no longer used internally by the superagent code base) + * + * @param {String} field + * @return {String} + * @api private + * @deprecated + */ + +exports.getHeader = exports.get; + +/** + * Set header `field` to `val`, or multiple fields with one object. + * Case-insensitive. + * + * Examples: + * + * req.get('/') + * .set('Accept', 'application/json') + * .set('X-API-Key', 'foobar') + * .end(callback); + * + * req.get('/') + * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' }) + * .end(callback); + * + * @param {String|Object} field + * @param {String} val + * @return {Request} for chaining + * @api public + */ + +exports.set = function(field, val){ + if (isObject(field)) { + for (var key in field) { + this.set(key, field[key]); + } + return this; + } + this._header[field.toLowerCase()] = val; + this.header[field] = val; + return this; +}; + +/** + * Remove header `field`. + * Case-insensitive. + * + * Example: + * + * req.get('/') + * .unset('User-Agent') + * .end(callback); + * + * @param {String} field + */ +exports.unset = function(field){ + delete this._header[field.toLowerCase()]; + delete this.header[field]; + return this; +}; + +/** + * Write the field `name` and `val` for "multipart/form-data" + * request bodies. + * + * ``` js + * request.post('/upload') + * .field('foo', 'bar') + * .end(callback); + * ``` + * + * @param {String} name + * @param {String|Blob|File|Buffer|fs.ReadStream} val + * @return {Request} for chaining + * @api public + */ +exports.field = function(name, val) { + this._getFormData().append(name, val); + return this; +}; diff --git a/node_modules/supertest/node_modules/superagent/lib/request.js b/node_modules/supertest/node_modules/superagent/lib/request.js new file mode 100644 index 0000000..53a3e6a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/lib/request.js @@ -0,0 +1,32 @@ +// The node and browser modules expose versions of this with the +// appropriate constructor function bound as first argument +/** + * Issue a request: + * + * Examples: + * + * request('GET', '/users').end(callback) + * request('/users').end(callback) + * request('/users', callback) + * + * @param {String} method + * @param {String|Function} url or callback + * @return {Request} + * @api public + */ + +function request(RequestConstructor, method, url) { + // callback + if ('function' == typeof url) { + return new RequestConstructor('GET', method).end(url); + } + + // url first + if (2 == arguments.length) { + return new RequestConstructor('GET', method); + } + + return new RequestConstructor(method, url); +} + +module.exports = request; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/History.md b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/History.md new file mode 100644 index 0000000..9189c60 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/History.md @@ -0,0 +1,68 @@ +
+1.2.1 / 2016-04-18
+==================
+
+ * enable client side use
+
+1.2.0 / 2014-02-12
+==================
+
+ * prefix events with `$` to support object prototype method names
+
+1.1.3 / 2014-06-20
+==================
+
+ * republish for npm
+ * add LICENSE file
+
+1.1.2 / 2014-02-10
+==================
+
+ * package: rename to "component-emitter"
+ * package: update "main" and "component" fields
+ * Add license to Readme (same format as the other components)
+ * created .npmignore
+ * travis stuff
+
+1.1.1 / 2013-12-01
+==================
+
+ * fix .once adding .on to the listener
+ * docs: Emitter#off()
+ * component: add `.repo` prop
+
+1.1.0 / 2013-10-20
+==================
+
+ * add `.addEventListener()` and `.removeEventListener()` aliases
+
+1.0.1 / 2013-06-27
+==================
+
+ * add support for legacy ie
+
+1.0.0 / 2013-02-26
+==================
+
+ * add `.off()` support for removing all listeners
+
+0.0.6 / 2012-10-08
+==================
+
+ * add `this._callbacks` initialization to prevent funky gotcha
+
+0.0.5 / 2012-09-07
+==================
+
+ * fix `Emitter.call(this)` usage
+
+0.0.3 / 2012-07-11
+==================
+
+ * add `.listeners()`
+ * rename `.has()` to `.hasListeners()`
+
+0.0.2 / 2012-06-28
+==================
+
+ * fix `.off()` with `.once()`-registered callbacks
diff --git a/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/LICENSE new file mode 100644 index 0000000..d6e43f2 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/LICENSE @@ -0,0 +1,24 @@ +(The MIT License)
+
+Copyright (c) 2014 Component contributors <dev@component.io>
+
+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/supertest/node_modules/superagent/node_modules/component-emitter/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/Readme.md new file mode 100644 index 0000000..0466411 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/Readme.md @@ -0,0 +1,74 @@ +# Emitter [](https://travis-ci.org/component/emitter)
+
+ Event emitter component.
+
+## Installation
+
+```
+$ component install component/emitter
+```
+
+## API
+
+### Emitter(obj)
+
+ The `Emitter` may also be used as a mixin. For example
+ a "plain" object may become an emitter, or you may
+ extend an existing prototype.
+
+ As an `Emitter` instance:
+
+```js
+var Emitter = require('emitter');
+var emitter = new Emitter;
+emitter.emit('something');
+```
+
+ As a mixin:
+
+```js
+var Emitter = require('emitter');
+var user = { name: 'tobi' };
+Emitter(user);
+
+user.emit('im a user');
+```
+
+ As a prototype mixin:
+
+```js
+var Emitter = require('emitter');
+Emitter(User.prototype);
+```
+
+### Emitter#on(event, fn)
+
+ Register an `event` handler `fn`.
+
+### Emitter#once(event, fn)
+
+ Register a single-shot `event` handler `fn`,
+ removed immediately after it is invoked the
+ first time.
+
+### Emitter#off(event, fn)
+
+ * Pass `event` and `fn` to remove a listener.
+ * Pass `event` to remove all listeners on that event.
+ * Pass nothing to remove all listeners on all events.
+
+### Emitter#emit(event, ...)
+
+ Emit an `event` with variable option args.
+
+### Emitter#listeners(event)
+
+ Return an array of callbacks, or an empty array.
+
+### Emitter#hasListeners(event)
+
+ Check if this emitter has `event` handlers.
+
+## License
+
+MIT
diff --git a/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/index.js b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/index.js new file mode 100644 index 0000000..df94c78 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/index.js @@ -0,0 +1,163 @@ +
+/**
+ * Expose `Emitter`.
+ */
+
+if (typeof module !== 'undefined') {
+ module.exports = Emitter;
+}
+
+/**
+ * Initialize a new `Emitter`.
+ *
+ * @api public
+ */
+
+function Emitter(obj) {
+ if (obj) return mixin(obj);
+};
+
+/**
+ * Mixin the emitter properties.
+ *
+ * @param {Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+function mixin(obj) {
+ for (var key in Emitter.prototype) {
+ obj[key] = Emitter.prototype[key];
+ }
+ return obj;
+}
+
+/**
+ * Listen on the given `event` with `fn`.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.on =
+Emitter.prototype.addEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
+ .push(fn);
+ return this;
+};
+
+/**
+ * Adds an `event` listener that will be invoked a single
+ * time then automatically removed.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.once = function(event, fn){
+ function on() {
+ this.off(event, on);
+ fn.apply(this, arguments);
+ }
+
+ on.fn = fn;
+ this.on(event, on);
+ return this;
+};
+
+/**
+ * Remove the given callback for `event` or all
+ * registered callbacks.
+ *
+ * @param {String} event
+ * @param {Function} fn
+ * @return {Emitter}
+ * @api public
+ */
+
+Emitter.prototype.off =
+Emitter.prototype.removeListener =
+Emitter.prototype.removeAllListeners =
+Emitter.prototype.removeEventListener = function(event, fn){
+ this._callbacks = this._callbacks || {};
+
+ // all
+ if (0 == arguments.length) {
+ this._callbacks = {};
+ return this;
+ }
+
+ // specific event
+ var callbacks = this._callbacks['$' + event];
+ if (!callbacks) return this;
+
+ // remove all handlers
+ if (1 == arguments.length) {
+ delete this._callbacks['$' + event];
+ return this;
+ }
+
+ // remove specific handler
+ var cb;
+ for (var i = 0; i < callbacks.length; i++) {
+ cb = callbacks[i];
+ if (cb === fn || cb.fn === fn) {
+ callbacks.splice(i, 1);
+ break;
+ }
+ }
+ return this;
+};
+
+/**
+ * Emit `event` with the given args.
+ *
+ * @param {String} event
+ * @param {Mixed} ...
+ * @return {Emitter}
+ */
+
+Emitter.prototype.emit = function(event){
+ this._callbacks = this._callbacks || {};
+ var args = [].slice.call(arguments, 1)
+ , callbacks = this._callbacks['$' + event];
+
+ if (callbacks) {
+ callbacks = callbacks.slice(0);
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
+ callbacks[i].apply(this, args);
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Return array of callbacks for `event`.
+ *
+ * @param {String} event
+ * @return {Array}
+ * @api public
+ */
+
+Emitter.prototype.listeners = function(event){
+ this._callbacks = this._callbacks || {};
+ return this._callbacks['$' + event] || [];
+};
+
+/**
+ * Check if this emitter has `event` handlers.
+ *
+ * @param {String} event
+ * @return {Boolean}
+ * @api public
+ */
+
+Emitter.prototype.hasListeners = function(event){
+ return !! this.listeners(event).length;
+};
diff --git a/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/package.json b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/package.json new file mode 100644 index 0000000..ac6f74e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/component-emitter/package.json @@ -0,0 +1,181 @@ +{ + "name": "component-emitter", + "description": "Event emitter", + "version": "1.2.1", + "license": "MIT", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "emitter/index.js": "index.js" + } + }, + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/component/emitter.git" + }, + "scripts": { + "test": "make test" + }, + "files": [ + "index.js", + "LICENSE" + ], + "gitHead": "187492ab8028c7221b589bdfd482b715149cd868", + "bugs": { + "url": "https://github.com/component/emitter/issues" + }, + "homepage": "https://github.com/component/emitter#readme", + "_id": "component-emitter@1.2.1", + "_shasum": "137918d6d78283f7df7a6b7c5a63e140e69425e6", + "_from": "component-emitter@>=1.2.0 <1.3.0", + "_npmVersion": "2.10.1", + "_nodeVersion": "0.12.4", + "_npmUser": { + "name": "nami-doc", + "email": "karp@hotmail.fr" + }, + "maintainers": [ + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "hughsk", + "email": "hughskennedy@gmail.com" + }, + { + "name": "trevorgerhardt", + "email": "trevorgerhardt@gmail.com" + }, + { + "name": "timaschew", + "email": "timaschew@gmail.com" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "rauchg", + "email": "rauchg@gmail.com" + }, + { + "name": "retrofox", + "email": "rdsuarez@gmail.com" + }, + { + "name": "coreh", + "email": "thecoreh@gmail.com" + }, + { + "name": "forbeslindesay", + "email": "forbes@lindesay.co.uk" + }, + { + "name": "kelonye", + "email": "kelonyemitchel@gmail.com" + }, + { + "name": "mattmueller", + "email": "mattmuelle@gmail.com" + }, + { + "name": "yields", + "email": "yields@icloud.com" + }, + { + "name": "anthonyshort", + "email": "antshort@gmail.com" + }, + { + "name": "jongleberry", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "ianstormtaylor", + "email": "ian@ianstormtaylor.com" + }, + { + "name": "cristiandouce", + "email": "cristian@gravityonmars.com" + }, + { + "name": "swatinem", + "email": "arpad.borsos@googlemail.com" + }, + { + "name": "stagas", + "email": "gstagas@gmail.com" + }, + { + "name": "amasad", + "email": "amjad.masad@gmail.com" + }, + { + "name": "juliangruber", + "email": "julian@juliangruber.com" + }, + { + "name": "calvinfo", + "email": "calvin@calv.info" + }, + { + "name": "dominicbarnes", + "email": "dominic@dbarnes.info" + }, + { + "name": "blakeembrey", + "email": "hello@blakeembrey.com" + }, + { + "name": "timoxley", + "email": "secoif@gmail.com" + }, + { + "name": "jonathanong", + "email": "jonathanrichardong@gmail.com" + }, + { + "name": "queckezz", + "email": "fabian.eichenberger@gmail.com" + }, + { + "name": "nami-doc", + "email": "vendethiel@hotmail.fr" + }, + { + "name": "clintwood", + "email": "clint@anotherway.co.za" + }, + { + "name": "thehydroimpulse", + "email": "dnfagnan@gmail.com" + }, + { + "name": "stephenmathieson", + "email": "me@stephenmathieson.com" + }, + { + "name": "dfcreative", + "email": "df.creative@gmail.com" + }, + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + } + ], + "dist": { + "shasum": "137918d6d78283f7df7a6b7c5a63e140e69425e6", + "tarball": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" + }, + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/component-emitter-1.2.1.tgz_1461005707641_0.14232611074112356" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/LICENSE new file mode 100644 index 0000000..58a23ec --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) +Copyright (c) 2013 Bradley Meck + +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/supertest/node_modules/superagent/node_modules/cookiejar/cookiejar.js b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/cookiejar.js new file mode 100644 index 0000000..ed1e02e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/cookiejar.js @@ -0,0 +1,261 @@ +/* jshint node: true */ +(function () { + "use strict"; + + function CookieAccessInfo(domain, path, secure, script) { + if (this instanceof CookieAccessInfo) { + this.domain = domain || undefined; + this.path = path || "/"; + this.secure = !!secure; + this.script = !!script; + return this; + } + return new CookieAccessInfo(domain, path, secure, script); + } + exports.CookieAccessInfo = CookieAccessInfo; + + function Cookie(cookiestr, request_domain, request_path) { + if (cookiestr instanceof Cookie) { + return cookiestr; + } + if (this instanceof Cookie) { + this.name = null; + this.value = null; + this.expiration_date = Infinity; + this.path = String(request_path || "/"); + this.explicit_path = false; + this.domain = request_domain || null; + this.explicit_domain = false; + this.secure = false; //how to define default? + this.noscript = false; //httponly + if (cookiestr) { + this.parse(cookiestr, request_domain, request_path); + } + return this; + } + return new Cookie(cookiestr, request_domain, request_path); + } + exports.Cookie = Cookie; + + Cookie.prototype.toString = function toString() { + var str = [this.name + "=" + this.value]; + if (this.expiration_date !== Infinity) { + str.push("expires=" + (new Date(this.expiration_date)).toGMTString()); + } + if (this.domain) { + str.push("domain=" + this.domain); + } + if (this.path) { + str.push("path=" + this.path); + } + if (this.secure) { + str.push("secure"); + } + if (this.noscript) { + str.push("httponly"); + } + return str.join("; "); + }; + + Cookie.prototype.toValueString = function toValueString() { + return this.name + "=" + this.value; + }; + + var cookie_str_splitter = /[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g; + Cookie.prototype.parse = function parse(str, request_domain, request_path) { + if (this instanceof Cookie) { + var parts = str.split(";").filter(function (value) { + return !!value; + }), + pair = parts[0].match(/([^=]+)=([\s\S]*)/), + key = pair[1], + value = pair[2], + i; + this.name = key; + this.value = value; + + for (i = 1; i < parts.length; i += 1) { + pair = parts[i].match(/([^=]+)(?:=([\s\S]*))?/); + key = pair[1].trim().toLowerCase(); + value = pair[2]; + switch (key) { + case "httponly": + this.noscript = true; + break; + case "expires": + this.expiration_date = value ? + Number(Date.parse(value)) : + Infinity; + break; + case "path": + this.path = value ? + value.trim() : + ""; + this.explicit_path = true; + break; + case "domain": + this.domain = value ? + value.trim() : + ""; + this.explicit_domain = !!this.domain; + break; + case "secure": + this.secure = true; + break; + } + } + + if (!this.explicit_path) { + this.path = request_path || "/"; + } + if (!this.explicit_domain) { + this.domain = request_domain; + } + + return this; + } + return new Cookie().parse(str, request_domain, request_path); + }; + + Cookie.prototype.matches = function matches(access_info) { + if (this.noscript && access_info.script || + this.secure && !access_info.secure || + !this.collidesWith(access_info)) { + return false; + } + return true; + }; + + Cookie.prototype.collidesWith = function collidesWith(access_info) { + if ((this.path && !access_info.path) || (this.domain && !access_info.domain)) { + return false; + } + if (this.path && access_info.path.indexOf(this.path) !== 0) { + return false; + } + if (this.explicit_path && access_info.path.indexOf( this.path ) !== 0) { + return false; + } + var access_domain = access_info.domain && access_info.domain.replace(/^[\.]/,''); + var cookie_domain = this.domain && this.domain.replace(/^[\.]/,''); + if (cookie_domain === access_domain) { + return true; + } + if (cookie_domain) { + if (!this.explicit_domain) { + return false; // we already checked if the domains were exactly the same + } + var wildcard = access_domain.indexOf(cookie_domain); + if (wildcard === -1 || wildcard !== access_domain.length - cookie_domain.length) { + return false; + } + return true; + } + return true; + }; + + function CookieJar() { + var cookies, cookies_list, collidable_cookie; + if (this instanceof CookieJar) { + cookies = Object.create(null); //name: [Cookie] + + this.setCookie = function setCookie(cookie, request_domain, request_path) { + var remove, i; + cookie = new Cookie(cookie, request_domain, request_path); + //Delete the cookie if the set is past the current time + remove = cookie.expiration_date <= Date.now(); + if (cookies[cookie.name] !== undefined) { + cookies_list = cookies[cookie.name]; + for (i = 0; i < cookies_list.length; i += 1) { + collidable_cookie = cookies_list[i]; + if (collidable_cookie.collidesWith(cookie)) { + if (remove) { + cookies_list.splice(i, 1); + if (cookies_list.length === 0) { + delete cookies[cookie.name]; + } + return false; + } + cookies_list[i] = cookie; + return cookie; + } + } + if (remove) { + return false; + } + cookies_list.push(cookie); + return cookie; + } + if (remove) { + return false; + } + cookies[cookie.name] = [cookie]; + return cookies[cookie.name]; + }; + //returns a cookie + this.getCookie = function getCookie(cookie_name, access_info) { + var cookie, i; + cookies_list = cookies[cookie_name]; + if (!cookies_list) { + return; + } + for (i = 0; i < cookies_list.length; i += 1) { + cookie = cookies_list[i]; + if (cookie.expiration_date <= Date.now()) { + if (cookies_list.length === 0) { + delete cookies[cookie.name]; + } + continue; + } + + if (cookie.matches(access_info)) { + return cookie; + } + } + }; + //returns a list of cookies + this.getCookies = function getCookies(access_info) { + var matches = [], cookie_name, cookie; + for (cookie_name in cookies) { + cookie = this.getCookie(cookie_name, access_info); + if (cookie) { + matches.push(cookie); + } + } + matches.toString = function toString() { + return matches.join(":"); + }; + matches.toValueString = function toValueString() { + return matches.map(function (c) { + return c.toValueString(); + }).join(';'); + }; + return matches; + }; + + return this; + } + return new CookieJar(); + } + exports.CookieJar = CookieJar; + + //returns list of cookies that were set correctly. Cookies that are expired and removed are not returned. + CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) { + cookies = Array.isArray(cookies) ? + cookies : + cookies.split(cookie_str_splitter); + var successful = [], + i, + cookie; + cookies = cookies.map(function(item){ + return new Cookie(item, request_domain, request_path); + }); + for (i = 0; i < cookies.length; i += 1) { + cookie = cookies[i]; + if (this.setCookie(cookie, request_domain, request_path)) { + successful.push(cookie); + } + } + return successful; + }; +}()); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/package.json b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/package.json new file mode 100644 index 0000000..7d874d4 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/package.json @@ -0,0 +1,53 @@ +{ + "name": "cookiejar", + "version": "2.0.6", + "author": { + "name": "bradleymeck" + }, + "main": "cookiejar.js", + "description": "simple persistent cookiejar system", + "license": "MIT", + "jshintConfig": { + "node": true + }, + "scripts": { + "test": "node tests/test.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bmeck/node-cookiejar.git" + }, + "devDependencies": { + "jshint": "^2.8.0" + }, + "gitHead": "3c3d43c39dc3c6928354873d43f3ec2895e26937", + "bugs": { + "url": "https://github.com/bmeck/node-cookiejar/issues" + }, + "homepage": "https://github.com/bmeck/node-cookiejar#readme", + "_id": "cookiejar@2.0.6", + "_shasum": "0abf356ad00d1c5a219d88d44518046dd026acfe", + "_from": "cookiejar@2.0.6", + "_npmVersion": "3.3.12", + "_nodeVersion": "6.0.0-pre", + "_npmUser": { + "name": "bradleymeck", + "email": "bradley.meck@gmail.com" + }, + "dist": { + "shasum": "0abf356ad00d1c5a219d88d44518046dd026acfe", + "tarball": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz" + }, + "maintainers": [ + { + "name": "andyburke", + "email": "aburke@bitflood.org" + }, + { + "name": "bradleymeck", + "email": "bradley.meck@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/readme.md b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/readme.md new file mode 100644 index 0000000..3d39ec6 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/readme.md @@ -0,0 +1,57 @@ +#CookieJar + +Simple robust cookie library + +##Exports + +###CookieAccessInfo(domain,path,secure,script) + + class to determine matching qualities of a cookie + +#####Properties + +* String domain - domain to match +* String path - path to match +* Boolean secure - access is secure (ssl generally) +* Boolean script - access is from a script + + +###Cookie(cookiestr_or_cookie, request_domain, request_path) + + turns input into a Cookie (singleton if given a Cookie) + the `request_domain` argument is used to default the domain if it is not explicit in the cookie string + the `request_path` argument is used to set the path if it is not explicit in a cookie String. + + explicit domains/paths will cascade, implied domains/paths must *exactly* match (see http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Pat) + +#####Properties + +* String name - name of the cookie +* String value - string associated with the cookie +* String domain - domain to match (on a cookie a '.' at the start means a wildcard matching anything ending in the rest) +* Boolean explicit_domain - if the domain was explicitly set via the cookie string +* String path - base path to match (matches any path starting with this '/' is root) +* Boolean explicit_path - if the path was explicitly set via the cookie string +* Boolean noscript - if it should be kept from scripts +* Boolean secure - should it only be transmitted over secure means +* Number expiration_date - number of millis since 1970 at which this should be removed + +#####Methods + +* String toString() - the __set-cookie:__ string for this cookie +* String toValueString() - the __cookie:__ string for this cookie +* Cookie parse(cookiestr, request_domain, request_path) - parses the string onto this cookie or a new one if called directly +* Boolean matches(access_info) - returns true if the access_info allows retrieval of this cookie +* Boolean collidesWith(cookie) - returns true if the cookies cannot exist in the same space (domain and path match) + + +###CookieJar() + + class to hold numerous cookies from multiple domains correctly + +#####Methods + +* Cookie setCookie(cookie, request_domain, request_path) - add a cookie to the jar +* Cookie[] setCookies(cookiestr_or_list, request_domain, request_path) - add a large number of cookies to the jar +* Cookie getCookie(cookie_name,access_info) - get a cookie with the name and access_info matching +* Cookie[] getCookies(access_info) - grab all cookies matching this access_info diff --git a/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/tests/test.js b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/tests/test.js new file mode 100755 index 0000000..80e70f1 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/cookiejar/tests/test.js @@ -0,0 +1,82 @@ +#!/usr/bin/env node +var Cookie=require("../cookiejar"), + CookieAccessInfo = Cookie.CookieAccessInfo, + CookieJar = Cookie.CookieJar, + Cookie = Cookie.Cookie; + +var assert = require('assert'); + +// Test Cookie +var cookie = new Cookie("a=1;domain=.test.com;path=/"); +assert.equal(cookie.name, "a"); +assert.equal(cookie.value, "1"); +assert.equal(cookie.domain, ".test.com"); +assert.equal(cookie.path, "/"); +assert.equal(cookie.secure, false); +assert.equal(cookie.expiration_date, Infinity); + +assert.deepEqual(cookie, new Cookie("a=1;domain=.test.com;path=/")); +assert.ok(cookie.collidesWith(new Cookie("a=1;domain=.test.com;path=/"))); + +var cookie = new Cookie("a=1;path=/", ".test.com"); +assert.equal(cookie.domain, ".test.com"); + + +// Test CookieJar +var test_jar = CookieJar(); +test_jar.setCookies( + "a=1;domain=.test.com;path=/" + +":b=2;domain=test.com;path=/" + +":c=3;domain=test.com;path=/;expires=January 1, 1970"); +var cookies=test_jar.getCookies(CookieAccessInfo("test.com","/")) +assert.equal(cookies.length, 2, "Expires on setCookies fail\n" + cookies.toString()); +assert.equal(cookies.toValueString(), 'a=1;b=2', "Cannot get value string of multiple cookies"); + +cookies=test_jar.getCookies(CookieAccessInfo("www.test.com","/")) +assert.equal(cookies.length, 2, "Wildcard domain fail\n" + cookies.toString()); + +test_jar.setCookies("b=2;domain=test.com;path=/;expires=January 1, 1970"); +cookies=test_jar.getCookies(CookieAccessInfo("test.com","/")) +assert.equal(cookies.length, 1, "Delete cookie fail\n" + cookies.toString()); +assert.equal(String(test_jar.getCookies(CookieAccessInfo("test.com","/"))), "a=1; domain=.test.com; path=/"); + +cookie=Cookie("a=1;domain=test.com;path=/;HttpOnly"); +assert.ok(cookie.noscript, "HttpOnly flag parsing failed\n" + cookie.toString()); + +var test_jar = CookieJar(); +test_jar.setCookies([ + "a=1;domain=.test.com;path=/" + , "a=1;domain=.test.com;path=/" + , "a=2;domain=.test.com;path=/" + , "b=3;domain=.test.com;path=/"]); +var cookies=test_jar.getCookies(CookieAccessInfo("test.com","/")) +assert.equal(cookies.length, 2); +assert.equal(cookies[0].value, 2); + +// Test Ignore Trailing Semicolons (Github Issue #6) +var cookie = new Cookie("a=1;domain=.test.com;path=/;;;;"); +assert.equal(cookie.name, "a"); +assert.equal(cookie.value, "1"); +assert.equal(cookie.domain, ".test.com"); +assert.equal(cookie.path, "/"); +assert.deepEqual(cookie, new Cookie("a=1;domain=.test.com;path=/")); + +// Test request_path and request_domain +test_jar.setCookie(new Cookie("sub=4;path=/", "test.com")); +var cookie = test_jar.getCookie("sub", CookieAccessInfo("sub.test.com", "/")); +assert.equal(cookie, undefined); + +var cookie = test_jar.getCookie("sub", CookieAccessInfo("test.com", "/")); +assert.equal(cookie.name, "sub"); +assert.equal(cookie.domain, "test.com"); + +test_jar.setCookie(new Cookie("sub=4;path=/accounts", "test.com", "/accounts")); +var cookie = test_jar.getCookie("sub", CookieAccessInfo("test.com", "/foo")); +assert.equal(cookie, undefined); + +var cookie = test_jar.getCookie("sub", CookieAccessInfo("test.com", "/accounts")); +assert.equal(cookie.path, "/accounts"); + +test_jar.setCookie(new Cookie("sub=5;path=/", "test.com", "/accounts")); +var cookies = test_jar.getCookies(CookieAccessInfo("test.com")); +assert.equal(cookies.length, 3); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/.eslintrc b/node_modules/supertest/node_modules/superagent/node_modules/extend/.eslintrc new file mode 100644 index 0000000..d49f173 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/.eslintrc @@ -0,0 +1,192 @@ +{ + "env": { + "browser": false, + "node": true, + "amd": false, + "mocha": false, + "jasmine": false + }, + + "rules": { + "accessor-pairs": [2, { getWithoutSet: false, setWithoutGet: true }], + "array-bracket-spacing": [2, "never", { + "singleValue": false, + "objectsInArrays": false, + "arraysInArrays": false + }], + "block-scoped-var": [0], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": [2], + "comma-dangle": [2, "never"], + "comma-spacing": [2], + "comma-style": [2, "last"], + "complexity": [2, 15], + "computed-property-spacing": [2, "never"], + "consistent-return": [2], + "consistent-this": [0, "that"], + "constructor-super": [2], + "curly": [2, "all"], + "default-case": [2], + "dot-notation": [2, { "allowKeywords": true }], + "eol-last": [2], + "eqeqeq": [2], + "func-names": [0], + "func-style": [2, "expression"], + "generator-star-spacing": [2, { "before": false, "after": true }], + "global-strict": [0, "never"], + "guard-for-in": [0], + "handle-callback-err": [0], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "linebreak-style": [2, "unix"], + "lines-around-comment": [2, { + "beforeBlockComment": false, + "afterBlockComment": false, + "beforeLineComment": false, + "beforeLineComment": false, + "allowBlockStart": true, + "allowBlockEnd": true + }], + "quotes": [2, "single", "avoid-escape"], + "max-depth": [1, 4], + "max-len": [0, 80, 4], + "max-nested-callbacks": [2, 2], + "max-params": [2, 2], + "max-statements": [2, 21], + "new-parens": [2], + "new-cap": [2], + "newline-after-var": [0], + "no-alert": [2], + "no-array-constructor": [2], + "no-bitwise": [0], + "no-caller": [2], + "no-catch-shadow": [2], + "no-cond-assign": [2], + "no-console": [2], + "no-constant-condition": [2], + "no-continue": [2], + "no-control-regex": [2], + "no-debugger": [2], + "no-delete-var": [2], + "no-div-regex": [0], + "no-dupe-args": [2], + "no-dupe-keys": [2], + "no-duplicate-case": [2], + "no-else-return": [0], + "no-empty": [2], + "no-empty-character-class": [2], + "no-empty-label": [2], + "no-eq-null": [0], + "no-eval": [2], + "no-ex-assign": [2], + "no-extend-native": [2], + "no-extra-bind": [2], + "no-extra-boolean-cast": [2], + "no-extra-parens": [0], + "no-extra-semi": [2], + "no-fallthrough": [2], + "no-floating-decimal": [2], + "no-func-assign": [2], + "no-implied-eval": [2], + "no-inline-comments": [0], + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": [2], + "no-irregular-whitespace": [2], + "no-iterator": [2], + "no-label-var": [2], + "no-labels": [2], + "no-lone-blocks": [2], + "no-lonely-if": [2], + "no-loop-func": [2], + "no-mixed-requires": [0, false], + "no-mixed-spaces-and-tabs": [2, false], + "no-multi-spaces": [2], + "no-multi-str": [2], + "no-multiple-empty-lines": [2, {"max": 1}], + "no-native-reassign": [2], + "no-negated-in-lhs": [2], + "no-nested-ternary": [0], + "no-new": [2], + "no-new-func": [2], + "no-new-object": [2], + "no-new-require": [0], + "no-new-wrappers": [2], + "no-obj-calls": [2], + "no-octal": [2], + "no-octal-escape": [2], + "no-param-reassign": [2], + "no-path-concat": [0], + "no-plusplus": [0], + "no-process-env": [0], + "no-process-exit": [2], + "no-proto": [2], + "no-redeclare": [2], + "no-regex-spaces": [2], + "no-reserved-keys": [2], + "no-restricted-modules": [0], + "no-return-assign": [2, "always"], + "no-script-url": [2], + "no-self-compare": [0], + "no-sequences": [2], + "no-shadow": [2], + "no-shadow-restricted-names": [2], + "no-space-before-semi": [2], + "no-spaced-func": [2], + "no-sparse-arrays": [2], + "no-sync": [0], + "no-ternary": [0], + "no-this-before-super": [2], + "no-throw-literal": [2], + "no-trailing-spaces": [2, { "skipBlankLines": false }], + "no-undef": [2], + "no-undef-init": [2], + "no-undefined": [0], + "no-underscore-dangle": [2], + "no-unexpected-multiline": [2], + "no-unneeded-ternary": [2], + "no-unreachable": [2], + "no-unused-expressions": [2], + "no-unused-vars": [2, { "vars": "all", "args": "after-used" }], + "no-use-before-define": [2], + "no-void": [0], + "no-warning-comments": [0, { "terms": ["todo", "fixme", "xxx"], "location": "start" }], + "no-with": [2], + "no-wrap-func": [2], + "object-curly-spacing": [2, "always"], + "object-shorthand": [2, "never"], + "one-var": [0], + "operator-assignment": [0, "always"], + "operator-linebreak": [2, "none"], + "padded-blocks": [0], + "prefer-const": [0], + "quote-props": [0], + "radix": [0], + "semi": [2], + "semi-spacing": [2, { "before": false, "after": true }], + "sort-vars": [0], + "space-after-keywords": [2, "always"], + "space-before-function-paren": [2, { "anonymous": "always", "named": "never" }], + "space-before-blocks": [0, "always"], + "space-in-brackets": [0, "never", { + "singleValue": true, + "arraysInArrays": false, + "arraysInObjects": false, + "objectsInArrays": true, + "objectsInObjects": true, + "propertyName": false + }], + "space-in-parens": [2, "never"], + "space-infix-ops": [2], + "space-return-throw-case": [2], + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always"], + "spaced-line-comment": [0, "always"], + "strict": [2, "global"], + "use-isnan": [2], + "valid-jsdoc": [0], + "valid-typeof": [2], + "vars-on-top": [0], + "wrap-iife": [2], + "wrap-regex": [2], + "yoda": [2, "never", { "exceptRange": true, "onlyEquality": false }] + } +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/.jscs.json b/node_modules/supertest/node_modules/superagent/node_modules/extend/.jscs.json new file mode 100644 index 0000000..7e84b28 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/.jscs.json @@ -0,0 +1,104 @@ +{ + "additionalRules": [], + + "requireSemicolons": true, + + "disallowMultipleSpaces": true, + + "disallowIdentifierNames": [], + + "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"], + + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch", "function"], + + "disallowSpaceAfterKeywords": [], + + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningRoundBrace": true, "beforeOpeningCurlyBrace": true }, + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, + + "requireSpaceBetweenArguments": true, + + "disallowSpacesInsideParentheses": true, + + "disallowSpacesInsideArrayBrackets": true, + + "disallowQuotedKeysInObjects": "allButReserved", + + "disallowSpaceAfterObjectKeys": true, + + "requireCommaBeforeLineBreak": true, + + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "requireSpaceAfterPrefixUnaryOperators": [], + + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "requireSpaceBeforePostfixUnaryOperators": [], + + "disallowSpaceBeforeBinaryOperators": [], + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!=="], + "disallowSpaceAfterBinaryOperators": [], + + "disallowImplicitTypeConversion": ["binary", "string"], + + "disallowKeywords": ["with", "eval"], + + "requireKeywordsOnNewLine": [], + "disallowKeywordsOnNewLine": ["else"], + + "requireLineFeedAtFileEnd": true, + + "disallowTrailingWhitespace": true, + + "disallowTrailingComma": true, + + "excludeFiles": ["node_modules/**", "vendor/**"], + + "disallowMultipleLineStrings": true, + + "requireDotNotation": true, + + "requireParenthesesAroundIIFE": true, + + "validateLineBreaks": "LF", + + "validateQuoteMarks": { + "escape": true, + "mark": "'" + }, + + "disallowOperatorBeforeLineBreak": [], + + "requireSpaceBeforeKeywords": [ + "do", + "for", + "if", + "else", + "switch", + "case", + "try", + "catch", + "finally", + "while", + "with", + "return" + ], + + "validateAlignedFunctionParameters": { + "lineBreakAfterOpeningBraces": true, + "lineBreakBeforeClosingBraces": true + }, + + "requirePaddingNewLinesBeforeExport": true, + + "validateNewlineAfterArrayElements": { + "maximum": 6 + }, + + "requirePaddingNewLinesAfterUseStrict": true +} + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/extend/.npmignore new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/.npmignore @@ -0,0 +1 @@ +test
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/.travis.yml b/node_modules/supertest/node_modules/superagent/node_modules/extend/.travis.yml new file mode 100644 index 0000000..ebef644 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/.travis.yml @@ -0,0 +1,44 @@ +language: node_js +node_js: + - "iojs-v2.3" + - "iojs-v2.2" + - "iojs-v2.1" + - "iojs-v2.0" + - "iojs-v1.8" + - "iojs-v1.7" + - "iojs-v1.6" + - "iojs-v1.5" + - "iojs-v1.4" + - "iojs-v1.3" + - "iojs-v1.2" + - "iojs-v1.1" + - "iojs-v1.0" + - "0.12" + - "0.11" + - "0.10" + - "0.9" + - "0.8" + - "0.6" + - "0.4" +before_install: + - '[ "${TRAVIS_NODE_VERSION}" = "0.6" ] || npm install -g npm@1.4.28 && npm install -g npm' +sudo: false +matrix: + fast_finish: true + allow_failures: + - node_js: "iojs-v2.2" + - node_js: "iojs-v2.1" + - node_js: "iojs-v2.0" + - node_js: "iojs-v1.7" + - node_js: "iojs-v1.6" + - node_js: "iojs-v1.5" + - node_js: "iojs-v1.4" + - node_js: "iojs-v1.3" + - node_js: "iojs-v1.2" + - node_js: "iojs-v1.1" + - node_js: "iojs-v1.0" + - node_js: "0.11" + - node_js: "0.9" + - node_js: "0.8" + - node_js: "0.6" + - node_js: "0.4" diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/CHANGELOG.md b/node_modules/supertest/node_modules/superagent/node_modules/extend/CHANGELOG.md new file mode 100644 index 0000000..ee0cfd6 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/CHANGELOG.md @@ -0,0 +1,69 @@ +3.0.0 / 2015-07-01 +================== + * [Possible breaking change] Use global "strict" directive (#32) + * [Tests] `int` is an ES3 reserved word + * [Tests] Test up to `io.js` `v2.3` + * [Tests] Add `npm run eslint` + * [Dev Deps] Update `covert`, `jscs` + +2.0.1 / 2015-04-25 +================== + * Use an inline `isArray` check, for ES3 browsers. (#27) + * Some old browsers fail when an identifier is `toString` + * Test latest `node` and `io.js` versions on `travis-ci`; speed up builds + * Add license info to package.json (#25) + * Update `tape`, `jscs` + * Adding a CHANGELOG + +2.0.0 / 2014-10-01 +================== + * Increase code coverage to 100%; run code coverage as part of tests + * Add `npm run lint`; Run linter as part of tests + * Remove nodeType and setInterval checks in isPlainObject + * Updating `tape`, `jscs`, `covert` + * General style and README cleanup + +1.3.0 / 2014-06-20 +================== + * Add component.json for browser support (#18) + * Use SVG for badges in README (#16) + * Updating `tape`, `covert` + * Updating travis-ci to work with multiple node versions + * Fix `deep === false` bug (returning target as {}) (#14) + * Fixing constructor checks in isPlainObject + * Adding additional test coverage + * Adding `npm run coverage` + * Add LICENSE (#13) + * Adding a warning about `false`, per #11 + * General style and whitespace cleanup + +1.2.1 / 2013-09-14 +================== + * Fixing hasOwnProperty bugs that would only have shown up in specific browsers. Fixes #8 + * Updating `tape` + +1.2.0 / 2013-09-02 +================== + * Updating the README: add badges + * Adding a missing variable reference. + * Using `tape` instead of `buster` for tests; add more tests (#7) + * Adding node 0.10 to Travis CI (#6) + * Enabling "npm test" and cleaning up package.json (#5) + * Add Travis CI. + +1.1.3 / 2012-12-06 +================== + * Added unit tests. + * Ensure extend function is named. (Looks nicer in a stack trace.) + * README cleanup. + +1.1.1 / 2012-11-07 +================== + * README cleanup. + * Added installation instructions. + * Added a missing semicolon + +1.0.0 / 2012-04-08 +================== + * Initial commit + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/extend/LICENSE new file mode 100644 index 0000000..e16d6a5 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2014 Stefan Thomas + +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/supertest/node_modules/superagent/node_modules/extend/README.md b/node_modules/supertest/node_modules/superagent/node_modules/extend/README.md new file mode 100644 index 0000000..632fb0f --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/README.md @@ -0,0 +1,62 @@ +[![Build Status][travis-svg]][travis-url] +[![dependency status][deps-svg]][deps-url] +[![dev dependency status][dev-deps-svg]][dev-deps-url] + +# extend() for Node.js <sup>[![Version Badge][npm-version-png]][npm-url]</sup> + +`node-extend` is a port of the classic extend() method from jQuery. It behaves as you expect. It is simple, tried and true. + +## Installation + +This package is available on [npm][npm-url] as: `extend` + +``` sh +npm install extend +``` + +## Usage + +**Syntax:** extend **(** [`deep`], `target`, `object1`, [`objectN`] **)** + +*Extend one object with one or more others, returning the modified object.* + +Keep in mind that the target object will be modified, and will be returned from extend(). + +If a boolean true is specified as the first argument, extend performs a deep copy, recursively copying any objects it finds. Otherwise, the copy will share structure with the original object(s). +Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over. +Warning: passing `false` as the first argument is not supported. + +### Arguments + +* `deep` *Boolean* (optional) +If set, the merge becomes recursive (i.e. deep copy). +* `target` *Object* +The object to extend. +* `object1` *Object* +The object that will be merged into the first. +* `objectN` *Object* (Optional) +More objects to merge into the first. + +## License + +`node-extend` is licensed under the [MIT License][mit-license-url]. + +## Acknowledgements + +All credit to the jQuery authors for perfecting this amazing utility. + +Ported to Node.js by [Stefan Thomas][github-justmoon] with contributions by [Jonathan Buchanan][github-insin] and [Jordan Harband][github-ljharb]. + +[travis-svg]: https://travis-ci.org/justmoon/node-extend.svg +[travis-url]: https://travis-ci.org/justmoon/node-extend +[npm-url]: https://npmjs.org/package/extend +[mit-license-url]: http://opensource.org/licenses/MIT +[github-justmoon]: https://github.com/justmoon +[github-insin]: https://github.com/insin +[github-ljharb]: https://github.com/ljharb +[npm-version-png]: http://vb.teelaun.ch/justmoon/node-extend.svg +[deps-svg]: https://david-dm.org/justmoon/node-extend.svg +[deps-url]: https://david-dm.org/justmoon/node-extend +[dev-deps-svg]: https://david-dm.org/justmoon/node-extend/dev-status.svg +[dev-deps-url]: https://david-dm.org/justmoon/node-extend#info=devDependencies + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/component.json b/node_modules/supertest/node_modules/superagent/node_modules/extend/component.json new file mode 100644 index 0000000..1500a2f --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/component.json @@ -0,0 +1,32 @@ +{ + "name": "extend", + "author": "Stefan Thomas <justmoon@members.fsf.org> (http://www.justmoon.net)", + "version": "3.0.0", + "description": "Port of jQuery.extend for node.js and the browser.", + "scripts": [ + "index.js" + ], + "contributors": [ + { + "name": "Jordan Harband", + "url": "https://github.com/ljharb" + } + ], + "keywords": [ + "extend", + "clone", + "merge" + ], + "repository" : { + "type": "git", + "url": "https://github.com/justmoon/node-extend.git" + }, + "dependencies": { + }, + "devDependencies": { + "tape" : "~3.0.0", + "covert": "~0.4.0", + "jscs": "~1.6.2" + } +} + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/index.js b/node_modules/supertest/node_modules/superagent/node_modules/extend/index.js new file mode 100644 index 0000000..f5ec75d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/index.js @@ -0,0 +1,86 @@ +'use strict'; + +var hasOwn = Object.prototype.hasOwnProperty; +var toStr = Object.prototype.toString; + +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); + } + + return toStr.call(arr) === '[object Array]'; +}; + +var isPlainObject = function isPlainObject(obj) { + if (!obj || toStr.call(obj) !== '[object Object]') { + return false; + } + + var hasOwnConstructor = hasOwn.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); + // Not own constructor property must be Object + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) {/**/} + + return typeof key === 'undefined' || hasOwn.call(obj, key); +}; + +module.exports = function extend() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0], + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) { + target = {}; + } + + for (; i < length; ++i) { + options = arguments[i]; + // Only deal with non-null/undefined values + if (options != null) { + // Extend the base object + for (name in options) { + src = target[name]; + copy = options[name]; + + // Prevent never-ending loop + if (target !== copy) { + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[name] = extend(deep, clone, copy); + + // Don't bring in undefined values + } else if (typeof copy !== 'undefined') { + target[name] = copy; + } + } + } + } + } + + // Return the modified object + return target; +}; + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/extend/package.json b/node_modules/supertest/node_modules/superagent/node_modules/extend/package.json new file mode 100644 index 0000000..1761010 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/extend/package.json @@ -0,0 +1,73 @@ +{ + "name": "extend", + "author": { + "name": "Stefan Thomas", + "email": "justmoon@members.fsf.org", + "url": "http://www.justmoon.net" + }, + "version": "3.0.0", + "description": "Port of jQuery.extend for node.js and the browser", + "main": "index", + "scripts": { + "test": "npm run lint && node test/index.js && npm run coverage-quiet", + "coverage": "covert test/index.js", + "coverage-quiet": "covert test/index.js --quiet", + "lint": "npm run jscs && npm run eslint", + "jscs": "jscs *.js */*.js", + "eslint": "eslint *.js */*.js" + }, + "contributors": [ + { + "name": "Jordan Harband", + "url": "https://github.com/ljharb" + } + ], + "keywords": [ + "extend", + "clone", + "merge" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/justmoon/node-extend.git" + }, + "dependencies": {}, + "devDependencies": { + "tape": "^4.0.0", + "covert": "^1.1.0", + "jscs": "^1.13.1", + "eslint": "^0.24.0" + }, + "license": "MIT", + "gitHead": "148e7270cab2e9413af2cd0cab147070d755ed6d", + "bugs": { + "url": "https://github.com/justmoon/node-extend/issues" + }, + "homepage": "https://github.com/justmoon/node-extend#readme", + "_id": "extend@3.0.0", + "_shasum": "5a474353b9f3353ddd8176dfd37b91c83a46f1d4", + "_from": "extend@3.0.0", + "_npmVersion": "2.11.3", + "_nodeVersion": "2.3.1", + "_npmUser": { + "name": "ljharb", + "email": "ljharb@gmail.com" + }, + "dist": { + "shasum": "5a474353b9f3353ddd8176dfd37b91c83a46f1d4", + "tarball": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "maintainers": [ + { + "name": "justmoon", + "email": "justmoon@members.fsf.org" + }, + { + "name": "ljharb", + "email": "ljharb@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/License b/node_modules/supertest/node_modules/superagent/node_modules/form-data/License new file mode 100644 index 0000000..c7ff12a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/License @@ -0,0 +1,19 @@ +Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors + + 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/supertest/node_modules/superagent/node_modules/form-data/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/form-data/Readme.md new file mode 100644 index 0000000..4927732 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/Readme.md @@ -0,0 +1,210 @@ +# Form-Data [](https://gitter.im/form-data/form-data) [](https://travis-ci.org/form-data/form-data) [](https://david-dm.org/form-data/form-data) + +A library to create readable ```"multipart/form-data"``` streams. Can be used to submit forms and file uploads to other web applications. + +The API of this library is inspired by the [XMLHttpRequest-2 FormData Interface][xhr2-fd]. + +[xhr2-fd]: http://dev.w3.org/2006/webapi/XMLHttpRequest-2/Overview.html#the-formdata-interface +[streams2-thing]: http://nodejs.org/api/stream.html#stream_compatibility_with_older_node_versions + +## Install + +``` +npm install form-data +``` + +## Usage + +In this example we are constructing a form with 3 fields that contain a string, +a buffer and a file stream. + +``` javascript +var FormData = require('form-data'); +var fs = require('fs'); + +var form = new FormData(); +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_file', fs.createReadStream('/foo/bar.jpg')); +``` + +Also you can use http-response stream: + +``` javascript +var FormData = require('form-data'); +var http = require('http'); + +var form = new FormData(); + +http.request('http://nodejs.org/images/logo.png', function(response) { + form.append('my_field', 'my value'); + form.append('my_buffer', new Buffer(10)); + form.append('my_logo', response); +}); +``` + +Or @mikeal's [request](https://github.com/request/request) stream: + +``` javascript +var FormData = require('form-data'); +var request = require('request'); + +var form = new FormData(); + +form.append('my_field', 'my value'); +form.append('my_buffer', new Buffer(10)); +form.append('my_logo', request('http://nodejs.org/images/logo.png')); +``` + +In order to submit this form to a web application, call ```submit(url, [callback])``` method: + +``` javascript +form.submit('http://example.org/', function(err, res) { + // res – response object (http.IncomingMessage) // + res.resume(); +}); + +``` + +For more advanced request manipulations ```submit()``` method returns ```http.ClientRequest``` object, or you can choose from one of the alternative submission methods. + +### Alternative submission methods + +You can use node's http client interface: + +``` javascript +var http = require('http'); + +var request = http.request({ + method: 'post', + host: 'example.org', + path: '/upload', + headers: form.getHeaders() +}); + +form.pipe(request); + +request.on('response', function(res) { + console.log(res.statusCode); +}); +``` + +Or if you would prefer the `'Content-Length'` header to be set for you: + +``` javascript +form.submit('example.org/upload', function(err, res) { + console.log(res.statusCode); +}); +``` + +To use custom headers and pre-known length in parts: + +``` javascript +var CRLF = '\r\n'; +var form = new FormData(); + +var options = { + header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF, + knownLength: 1 +}; + +form.append('my_buffer', buffer, options); + +form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); +}); +``` + +Form-Data can recognize and fetch all the required information from common types of streams (```fs.readStream```, ```http.response``` and ```mikeal's request```), for some other types of streams you'd need to provide "file"-related information manually: + +``` javascript +someModule.stream(function(err, stdout, stderr) { + if (err) throw err; + + var form = new FormData(); + + form.append('file', stdout, { + filename: 'unicycle.jpg', + contentType: 'image/jpg', + knownLength: 19806 + }); + + form.submit('http://example.com/', function(err, res) { + if (err) throw err; + console.log('Done'); + }); +}); +``` + +For edge cases, like POST request to URL with query string or to pass HTTP auth credentials, object can be passed to `form.submit()` as first parameter: + +``` javascript +form.submit({ + host: 'example.com', + path: '/probably.php?extra=params', + auth: 'username:password' +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +In case you need to also send custom HTTP headers with the POST request, you can use the `headers` key in first parameter of `form.submit()`: + +``` javascript +form.submit({ + host: 'example.com', + path: '/surelynot.php', + headers: {'x-test-header': 'test-header-value'} +}, function(err, res) { + console.log(res.statusCode); +}); +``` + +### Integration with other libraries + +#### Request + +Form submission using [request](https://github.com/request/request): + +```javascript +var formData = { + my_field: 'my_value', + my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), +}; + +request.post({url:'http://service.com/upload', formData: formData}, function(err, httpResponse, body) { + if (err) { + return console.error('upload failed:', err); + } + console.log('Upload successful! Server responded with:', body); +}); +``` + +For more details see [request readme](https://github.com/request/request#multipartform-data-multipart-form-uploads). + +#### node-fetch + +You can also submit a form using [node-fetch](https://github.com/bitinn/node-fetch): + +```javascript +var form = new FormData(); + +form.append('a', 1); + +fetch('http://example.com', { method: 'POST', body: form }) + .then(function(res) { + return res.json(); + }).then(function(json) { + console.log(json); + }); +``` + +## Notes + +- ```getLengthSync()``` method DOESN'T calculate length for streams, use ```knownLength``` options as workaround. +- If it feels like FormData hangs after submit and you're on ```node-0.10```, please check [Compatibility with Older Node Versions][streams2-thing] + +## License + +Form-Data is licensed under the MIT license. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/browser.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/browser.js new file mode 100644 index 0000000..1e7717d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/browser.js @@ -0,0 +1 @@ +module.exports = FormData;
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/form_data.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/form_data.js new file mode 100644 index 0000000..524f392 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/lib/form_data.js @@ -0,0 +1,374 @@ +var CombinedStream = require('combined-stream'); +var util = require('util'); +var path = require('path'); +var http = require('http'); +var https = require('https'); +var parseUrl = require('url').parse; +var fs = require('fs'); +var mime = require('mime-types'); +var async = require('async'); + +module.exports = FormData; +function FormData() { + this._overheadLength = 0; + this._valueLength = 0; + this._lengthRetrievers = []; + + CombinedStream.call(this); +} +util.inherits(FormData, CombinedStream); + +FormData.LINE_BREAK = '\r\n'; +FormData.DEFAULT_CONTENT_TYPE = 'application/octet-stream'; + +FormData.prototype.append = function(field, value, options) { + options = (typeof options === 'string') + ? { filename: options } + : options || {}; + + var append = CombinedStream.prototype.append.bind(this); + + // all that streamy business can't handle numbers + if (typeof value == 'number') value = ''+value; + + // https://github.com/felixge/node-form-data/issues/38 + if (util.isArray(value)) { + // Please convert your array into string + // the way web server expects it + this._error(new Error('Arrays are not supported.')); + return; + } + + var header = this._multiPartHeader(field, value, options); + var footer = this._multiPartFooter(field, value, options); + + append(header); + append(value); + append(footer); + + // pass along options.knownLength + this._trackLength(header, value, options); +}; + +FormData.prototype._trackLength = function(header, value, options) { + var valueLength = 0; + + // used w/ getLengthSync(), when length is known. + // e.g. for streaming directly from a remote server, + // w/ a known file a size, and not wanting to wait for + // incoming file to finish to get its size. + if (options.knownLength != null) { + valueLength += +options.knownLength; + } else if (Buffer.isBuffer(value)) { + valueLength = value.length; + } else if (typeof value === 'string') { + valueLength = Buffer.byteLength(value); + } + + this._valueLength += valueLength; + + // @check why add CRLF? does this account for custom/multiple CRLFs? + this._overheadLength += + Buffer.byteLength(header) + + FormData.LINE_BREAK.length; + + // empty or either doesn't have path or not an http response + if (!value || ( !value.path && !(value.readable && value.hasOwnProperty('httpVersion')) )) { + return; + } + + // no need to bother with the length + if (!options.knownLength) + this._lengthRetrievers.push(function(next) { + + if (value.hasOwnProperty('fd')) { + + // take read range into a account + // `end` = Infinity –> read file till the end + // + // TODO: Looks like there is bug in Node fs.createReadStream + // it doesn't respect `end` options without `start` options + // Fix it when node fixes it. + // https://github.com/joyent/node/issues/7819 + if (value.end != undefined && value.end != Infinity && value.start != undefined) { + + // when end specified + // no need to calculate range + // inclusive, starts with 0 + next(null, value.end+1 - (value.start ? value.start : 0)); + + // not that fast snoopy + } else { + // still need to fetch file size from fs + fs.stat(value.path, function(err, stat) { + + var fileSize; + + if (err) { + next(err); + return; + } + + // update final size based on the range options + fileSize = stat.size - (value.start ? value.start : 0); + next(null, fileSize); + }); + } + + // or http response + } else if (value.hasOwnProperty('httpVersion')) { + next(null, +value.headers['content-length']); + + // or request stream http://github.com/mikeal/request + } else if (value.hasOwnProperty('httpModule')) { + // wait till response come back + value.on('response', function(response) { + value.pause(); + next(null, +response.headers['content-length']); + }); + value.resume(); + + // something else + } else { + next('Unknown stream'); + } + }); +}; + +FormData.prototype._multiPartHeader = function(field, value, options) { + // custom header specified (as string)? + // it becomes responsible for boundary + // (e.g. to handle extra CRLFs on .NET servers) + if (options.header != null) { + return options.header; + } + + var contents = ''; + var headers = { + 'Content-Disposition': ['form-data', 'name="' + field + '"'], + 'Content-Type': [] + }; + + // fs- and request- streams have path property + // or use custom filename and/or contentType + // TODO: Use request's response mime-type + if (options.filename || value.path) { + headers['Content-Disposition'].push( + 'filename="' + path.basename(options.filename || value.path) + '"' + ); + headers['Content-Type'].push( + options.contentType || + mime.lookup(options.filename || value.path) || + FormData.DEFAULT_CONTENT_TYPE + ); + // http response has not + } else if (value.readable && value.hasOwnProperty('httpVersion')) { + headers['Content-Disposition'].push( + 'filename="' + path.basename(value.client._httpMessage.path) + '"' + ); + headers['Content-Type'].push( + options.contentType || + value.headers['content-type'] || + FormData.DEFAULT_CONTENT_TYPE + ); + } else if (Buffer.isBuffer(value)) { + headers['Content-Type'].push( + options.contentType || + FormData.DEFAULT_CONTENT_TYPE + ); + } else if (options.contentType) { + headers['Content-Type'].push(options.contentType); + } + + for (var prop in headers) { + if (headers[prop].length) { + contents += prop + ': ' + headers[prop].join('; ') + FormData.LINE_BREAK; + } + } + + return '--' + this.getBoundary() + FormData.LINE_BREAK + contents + FormData.LINE_BREAK; +}; + +FormData.prototype._multiPartFooter = function(field, value, options) { + return function(next) { + var footer = FormData.LINE_BREAK; + + var lastPart = (this._streams.length === 0); + if (lastPart) { + footer += this._lastBoundary(); + } + + next(footer); + }.bind(this); +}; + +FormData.prototype._lastBoundary = function() { + return '--' + this.getBoundary() + '--' + FormData.LINE_BREAK; +}; + +FormData.prototype.getHeaders = function(userHeaders) { + var formHeaders = { + 'content-type': 'multipart/form-data; boundary=' + this.getBoundary() + }; + + for (var header in userHeaders) { + formHeaders[header.toLowerCase()] = userHeaders[header]; + } + + return formHeaders; +} + +FormData.prototype.getCustomHeaders = function(contentType) { + contentType = contentType ? contentType : 'multipart/form-data'; + + var formHeaders = { + 'content-type': contentType + '; boundary=' + this.getBoundary(), + 'content-length': this.getLengthSync() + }; + + return formHeaders; +} + +FormData.prototype.getBoundary = function() { + if (!this._boundary) { + this._generateBoundary(); + } + + return this._boundary; +}; + +FormData.prototype._generateBoundary = function() { + // This generates a 50 character boundary similar to those used by Firefox. + // They are optimized for boyer-moore parsing. + var boundary = '--------------------------'; + for (var i = 0; i < 24; i++) { + boundary += Math.floor(Math.random() * 10).toString(16); + } + + this._boundary = boundary; +}; + +// Note: getLengthSync DOESN'T calculate streams length +// As workaround one can calculate file size manually +// and add it as knownLength option +FormData.prototype.getLengthSync = function(debug) { + var knownLength = this._overheadLength + this._valueLength; + + // Don't get confused, there are 3 "internal" streams for each keyval pair + // so it basically checks if there is any value added to the form + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + // https://github.com/felixge/node-form-data/issues/40 + if (this._lengthRetrievers.length) { + // Some async length retrivers are present + // therefore synchronous length calculation is false. + // Please use getLength(callback) to get proper length + this._error(new Error('Cannot calculate proper length in synchronous way.')); + } + + return knownLength; +}; + +FormData.prototype.getLength = function(cb) { + var knownLength = this._overheadLength + this._valueLength; + + if (this._streams.length) { + knownLength += this._lastBoundary().length; + } + + if (!this._lengthRetrievers.length) { + process.nextTick(cb.bind(this, null, knownLength)); + return; + } + + async.parallel(this._lengthRetrievers, function(err, values) { + if (err) { + cb(err); + return; + } + + values.forEach(function(length) { + knownLength += length; + }); + + cb(null, knownLength); + }); +}; + +FormData.prototype.submit = function(params, cb) { + + var request + , options + , defaults = { + method : 'post' + }; + + // parse provided url if it's string + // or treat it as options object + if (typeof params == 'string') { + params = parseUrl(params); + + options = populate({ + port: params.port, + path: params.pathname, + host: params.hostname + }, defaults); + } + else // use custom params + { + options = populate(params, defaults); + // if no port provided use default one + if (!options.port) { + options.port = options.protocol == 'https:' ? 443 : 80; + } + } + + // put that good code in getHeaders to some use + options.headers = this.getHeaders(params.headers); + + // https if specified, fallback to http in any other case + if (options.protocol == 'https:') { + request = https.request(options); + } else { + request = http.request(options); + } + + // get content length and fire away + this.getLength(function(err, length) { + + // TODO: Add chunked encoding when no length (if err) + + // add content length + request.setHeader('Content-Length', length); + + this.pipe(request); + if (cb) { + request.on('error', cb); + request.on('response', cb.bind(this, null)); + } + }.bind(this)); + + return request; +}; + +FormData.prototype._error = function(err) { + if (this.error) return; + + this.error = err; + this.pause(); + this.emit('error', err); +}; + +/* + * Santa's little helpers + */ + +// populates missing values +function populate(dst, src) { + for (var prop in src) { + if (!dst[prop]) dst[prop] = src[prop]; + } + return dst; +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/CHANGELOG.md b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/CHANGELOG.md new file mode 100644 index 0000000..f15e081 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/CHANGELOG.md @@ -0,0 +1,125 @@ +# v1.5.2 +- Allow using `"consructor"` as an argument in `memoize` (#998) +- Give a better error messsage when `auto` dependency checking fails (#994) +- Various doc updates (#936, #956, #979, #1002) + +# v1.5.1 +- Fix issue with `pause` in `queue` with concurrency enabled (#946) +- `while` and `until` now pass the final result to callback (#963) +- `auto` will properly handle concurrency when there is no callback (#966) +- `auto` will now properly stop execution when an error occurs (#988, #993) +- Various doc fixes (#971, #980) + +# v1.5.0 + +- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) (#892) +- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. (#873) +- `auto` now accepts an optional `concurrency` argument to limit the number of running tasks (#637) +- Added `queue#workersList()`, to retrieve the list of currently running tasks. (#891) +- Various code simplifications (#896, #904) +- Various doc fixes :scroll: (#890, #894, #903, #905, #912) + +# v1.4.2 + +- Ensure coverage files don't get published on npm (#879) + +# v1.4.1 + +- Add in overlooked `detectLimit` method (#866) +- Removed unnecessary files from npm releases (#861) +- Removed usage of a reserved word to prevent :boom: in older environments (#870) + +# v1.4.0 + +- `asyncify` now supports promises (#840) +- Added `Limit` versions of `filter` and `reject` (#836) +- Add `Limit` versions of `detect`, `some` and `every` (#828, #829) +- `some`, `every` and `detect` now short circuit early (#828, #829) +- Improve detection of the global object (#804), enabling use in WebWorkers +- `whilst` now called with arguments from iterator (#823) +- `during` now gets called with arguments from iterator (#824) +- Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0)) + + +# v1.3.0 + +New Features: +- Added `constant` +- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. (#671, #806) +- Added `during` and `doDuring`, which are like `whilst` with an async truth test. (#800) +- `retry` now accepts an `interval` parameter to specify a delay between retries. (#793) +- `async` should work better in Web Workers due to better `root` detection (#804) +- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` (#642) +- Various internal updates (#786, #801, #802, #803) +- Various doc fixes (#790, #794) + +Bug Fixes: +- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. (#740, #744, #783) + + +# v1.2.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) + + +# v1.2.0 + +New Features: + +- Added `timesLimit` (#743) +- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. (#747, #772) + +Bug Fixes: + +- Fixed a regression in `each` and family with empty arrays that have additional properties. (#775, #777) + + +# v1.1.1 + +Bug Fix: + +- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. (#782) + + +# v1.1.0 + +New Features: + +- `cargo` now supports all of the same methods and event callbacks as `queue`. +- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. (#769) +- Optimized `map`, `eachOf`, and `waterfall` families of functions +- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array (#667). +- The callback is now optional for the composed results of `compose` and `seq`. (#618) +- Reduced file size by 4kb, (minified version by 1kb) +- Added code coverage through `nyc` and `coveralls` (#768) + +Bug Fixes: + +- `forever` will no longer stack overflow with a synchronous iterator (#622) +- `eachLimit` and other limit functions will stop iterating once an error occurs (#754) +- Always pass `null` in callbacks when there is no error (#439) +- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue (#668) +- `each` and family will properly handle an empty array (#578) +- `eachSeries` and family will finish if the underlying array is modified during execution (#557) +- `queue` will throw if a non-function is passed to `q.push()` (#593) +- Doc fixes (#629, #766) + + +# v1.0.0 + +No known breaking changes, we are simply complying with semver from here on out. + +Changes: + +- Start using a changelog! +- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) (#168 #704 #321) +- Detect deadlocks in `auto` (#663) +- Better support for require.js (#527) +- Throw if queue created with concurrency `0` (#714) +- Fix unneeded iteration in `queue.resume()` (#758) +- Guard against timer mocking overriding `setImmediate` (#609 #611) +- Miscellaneous doc fixes (#542 #596 #615 #628 #631 #690 #729) +- Use single noop function internally (#546) +- Optimize internal `_each`, `_map` and `_keys` functions. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/LICENSE new file mode 100644 index 0000000..8f29698 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2014 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. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/README.md b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/README.md new file mode 100644 index 0000000..316c405 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/README.md @@ -0,0 +1,1877 @@ +# Async.js + +[](https://travis-ci.org/caolan/async) +[](https://www.npmjs.org/package/async) +[](https://coveralls.io/r/caolan/async?branch=master) +[](https://gitter.im/caolan/async?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + +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) and installable via `npm install async`, +it can also be used directly in the browser. + +Async is also installable via: + +- [bower](http://bower.io/): `bower install async` +- [component](https://github.com/component/component): `component install + caolan/async` +- [jam](http://jamjs.org/): `jam install async` +- [spm](http://spmjs.io/): `spm install async` + +Async provides around 20 functions that include the usual 'functional' +suspects (`map`, `reduce`, `filter`, `each`…) 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 + +```javascript +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'], fs.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. + +## Common Pitfalls <sub>[(StackOverflow)](http://stackoverflow.com/questions/tagged/async.js)</sub> +### Synchronous iteration functions + +If you get an error like `RangeError: Maximum call stack size exceeded.` or other stack overflow issues when using async, you are likely using a synchronous iterator. By *synchronous* we mean a function that calls its callback on the same tick in the javascript event loop, without doing any I/O or using any timers. Calling many callbacks iteratively will quickly overflow the stack. If you run into this issue, just defer your callback with `async.setImmediate` to start a new call stack on the next tick of the event loop. + +This can also arise by accident if you callback early in certain cases: + +```js +async.eachSeries(hugeArray, function iterator(item, callback) { + if (inCache(item)) { + callback(null, cache[item]); // if many items are cached, you'll overflow + } else { + doSomeIO(item, callback); + } +}, function done() { + //... +}); +``` + +Just change it to: + +```js +async.eachSeries(hugeArray, function iterator(item, callback) { + if (inCache(item)) { + async.setImmediate(function () { + callback(null, cache[item]); + }); + } else { + doSomeIO(item, callback); + //... +``` + +Async guards against synchronous functions in some, but not all, cases. If you are still running into stack overflows, you can defer as suggested above, or wrap functions with [`async.ensureAsync`](#ensureAsync) Functions that are asynchronous by their nature do not have this problem and don't need the extra callback deferral. + +If JavaScript's event loop is still a bit nebulous, check out [this article](http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/) or [this talk](http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html) for more detailed information about how it works. + + +### Multiple callbacks + +Make sure to always `return` when calling a callback early, otherwise you will cause multiple callbacks and unpredictable behavior in many cases. + +```js +async.waterfall([ + function (callback) { + getSomething(options, function (err, result) { + if (err) { + callback(new Error("failed getting something:" + err.message)); + // we should return here + } + // since we did not return, this callback still will be called and + // `processData` will be called twice + callback(null, result); + }); + }, + processData +], done) +``` + +It is always good practice to `return callback(err, result)` whenever a callback call is not the last statement of a function. + + +### Binding a context to an iterator + +This section is really about `bind`, not about `async`. If you are wondering how to +make `async` execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](https://github.com/caolan/async/blob/master/lib/async.js). +Alternatively, you can install using Node Package Manager (`npm`): + + npm install async + +As well as using Bower: + + bower install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. + +Usage: + +```html +<script type="text/javascript" src="async.js"></script> +<script type="text/javascript"> + + async.map(data, asyncProcess, function(err, results){ + alert(results); + }); + +</script> +``` + +## Documentation + +Some functions are also available in the following forms: +* `<name>Series` - the same as `<name>` but runs only a single async operation at a time +* `<name>Limit` - the same as `<name>` but runs a maximum of `limit` async operations at a time + +### Collections + +* [`each`](#each), `eachSeries`, `eachLimit` +* [`forEachOf`](#forEachOf), `forEachOfSeries`, `forEachOfLimit` +* [`map`](#map), `mapSeries`, `mapLimit` +* [`filter`](#filter), `filterSeries`, `filterLimit` +* [`reject`](#reject), `rejectSeries`, `rejectLimit` +* [`reduce`](#reduce), [`reduceRight`](#reduceRight) +* [`detect`](#detect), `detectSeries`, `detectLimit` +* [`sortBy`](#sortBy) +* [`some`](#some), `someLimit` +* [`every`](#every), `everyLimit` +* [`concat`](#concat), `concatSeries` + +### Control Flow + +* [`series`](#seriestasks-callback) +* [`parallel`](#parallel), `parallelLimit` +* [`whilst`](#whilst), [`doWhilst`](#doWhilst) +* [`until`](#until), [`doUntil`](#doUntil) +* [`during`](#during), [`doDuring`](#doDuring) +* [`forever`](#forever) +* [`waterfall`](#waterfall) +* [`compose`](#compose) +* [`seq`](#seq) +* [`applyEach`](#applyEach), `applyEachSeries` +* [`queue`](#queue), [`priorityQueue`](#priorityQueue) +* [`cargo`](#cargo) +* [`auto`](#auto) +* [`retry`](#retry) +* [`iterator`](#iterator) +* [`times`](#times), `timesSeries`, `timesLimit` + +### Utils + +* [`apply`](#apply) +* [`nextTick`](#nextTick) +* [`memoize`](#memoize) +* [`unmemoize`](#unmemoize) +* [`ensureAsync`](#ensureAsync) +* [`constant`](#constant) +* [`asyncify`](#asyncify) +* [`wrapSync`](#wrapSync) +* [`log`](#log) +* [`dir`](#dir) +* [`noConflict`](#noConflict) + +## Collections + +<a name="forEach" /> +<a name="each" /> +### each(arr, iterator, [callback]) + +Applies the function `iterator` to each item in `arr`, 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 its `callback`, the main +`callback` (for the `each` function) is immediately called with the error. + +Note, that since this function applies `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 `arr`. + The iterator is passed a `callback(err)` which must be called once it has + completed. If no error has occurred, the `callback` should be run without + arguments or with an explicit `null` argument. The array index is not passed + to the iterator. If you need the index, use [`forEachOf`](#forEachOf). +* `callback(err)` - *Optional* A callback which is called when all `iterator` functions + have finished, or an error occurs. + +__Examples__ + + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +```js +// assuming openFiles is an array of file names + +async.each(openFiles, function(file, callback) { + + // Perform operation on file here. + console.log('Processing file ' + file); + + if( file.length > 32 ) { + console.log('This file name is too long'); + callback('File name too long'); + } else { + // Do work to process file here + console.log('File processed'); + callback(); + } +}, function(err){ + // if any of the file processing produced an error, err would equal that error + if( err ) { + // One of the iterations produced an error. + // All processing will now stop. + console.log('A file failed to process'); + } else { + console.log('All files have been processed successfully'); + } +}); +``` + +__Related__ + +* eachSeries(arr, iterator, [callback]) +* eachLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + +<a name="forEachOf" /> +<a name="eachOf" /> + +### forEachOf(obj, iterator, [callback]) + +Like `each`, except that it iterates over objects, and passes the key as the second argument to the iterator. + +__Arguments__ + +* `obj` - An object or array to iterate over. +* `iterator(item, key, callback)` - A function to apply to each item in `obj`. +The `key` is the item's key, or index in the case of an array. The iterator is +passed a `callback(err)` which must be called once it has completed. If no +error has occurred, the callback should be run without arguments or with an +explicit `null` argument. +* `callback(err)` - *Optional* A callback which is called when all `iterator` functions have finished, or an error occurs. + +__Example__ + +```js +var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"}; +var configs = {}; + +async.forEachOf(obj, function (value, key, callback) { + fs.readFile(__dirname + value, "utf8", function (err, data) { + if (err) return callback(err); + try { + configs[key] = JSON.parse(data); + } catch (e) { + return callback(e); + } + callback(); + }) +}, function (err) { + if (err) console.error(err.message); + // configs is now a map of JSON data + doSomethingWith(configs); +}) +``` + +__Related__ + +* forEachOfSeries(obj, iterator, [callback]) +* forEachOfLimit(obj, limit, iterator, [callback]) + +--------------------------------------- + +<a name="map" /> +### map(arr, iterator, [callback]) + +Produces a new array of values by mapping each value in `arr` through +the `iterator` function. The `iterator` is called with an item from `arr` and a +callback for when it has finished processing. Each of these callback takes 2 arguments: +an `error`, and the transformed item from `arr`. If `iterator` passes an error to its +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 `arr`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, transformed)` which must be called once + it has completed with an error (which can be `null`) and a transformed item. +* `callback(err, results)` - *Optional* A callback which is called when all `iterator` + functions have finished, or an error occurs. Results is an array of the + transformed items from the `arr`. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +__Related__ +* mapSeries(arr, iterator, [callback]) +* mapLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + +<a name="select" /> +<a name="filter" /> +### filter(arr, iterator, [callback]) + +__Alias:__ `select` + +Returns a new array of all the values in `arr` 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 `fs.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 `arr`. + The `iterator` is passed a `callback(truthValue)`, which must be called with a + boolean argument once it has completed. +* `callback(results)` - *Optional* A callback which is called after all the `iterator` + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +__Related__ + +* filterSeries(arr, iterator, [callback]) +* filterLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + +<a name="reject" /> +### reject(arr, iterator, [callback]) + +The opposite of [`filter`](#filter). Removes values that pass an `async` truth test. + +__Related__ + +* rejectSeries(arr, iterator, [callback]) +* rejectLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + +<a name="reduce" /> +### reduce(arr, memo, iterator, [callback]) + +__Aliases:__ `inject`, `foldl` + +Reduces `arr` 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, and 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 it's 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(err, reduction)` 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)` - *Optional* A callback which is called after all the `iterator` + functions have finished. Result is the reduced value. + +__Example__ + +```js +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`](#reduce), only operates on `arr` in reverse order. + + +--------------------------------------- + +<a name="detect" /> +### detect(arr, iterator, [callback]) + +Returns the first value in `arr` 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 `arr` (in terms of order) that passes the test. + +If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries). + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in `arr`. + The iterator is passed a `callback(truthValue)` which must be called with a + boolean argument once it has completed. **Note: this callback does not take an error as its first argument.** +* `callback(result)` - *Optional* 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. **Note: this callback does not take an error as its first argument.** + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +__Related__ + +* detectSeries(arr, iterator, [callback]) +* detectLimit(arr, limit, iterator, [callback]) + +--------------------------------------- + +<a name="sortBy" /> +### sortBy(arr, iterator, [callback]) + +Sorts a list by the results of running each `arr` value through an async `iterator`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, sortValue)` 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)` - *Optional* A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is the items from + the original `arr` sorted by the values returned by the `iterator` calls. + +__Example__ + +```js +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 +}); +``` + +__Sort Order__ + +By modifying the callback parameter the sorting order can be influenced: + +```js +//ascending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x); +}, function(err,result){ + //result callback +} ); + +//descending order +async.sortBy([1,9,3,5], function(x, callback){ + callback(null, x*-1); //<- x*-1 instead of x, turns the order around +}, function(err,result){ + //result callback +} ); +``` + +--------------------------------------- + +<a name="some" /> +### some(arr, iterator, [callback]) + +__Alias:__ `any` + +Returns `true` if at least one element in the `arr` 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 `fs.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 + in parallel. The iterator is passed a `callback(truthValue)`` which must be + called with a boolean argument once it has completed. +* `callback(result)` - *Optional* 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. + + **Note: the callbacks do not take an error as their first argument.** +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +__Related__ + +* someLimit(arr, limit, iterator, callback) + +--------------------------------------- + +<a name="every" /> +### every(arr, iterator, [callback]) + +__Alias:__ `all` + +Returns `true` if every element in `arr` 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 `fs.exists`. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A truth test to apply to each item in the array + in parallel. The iterator is passed a `callback(truthValue)` which must be + called with a boolean argument once it has completed. +* `callback(result)` - *Optional* A callback which is called as soon as any iterator returns + `false`, or after all the iterator functions have finished. Result will be + either `true` or `false` depending on the values of the async tests. + + **Note: the callbacks do not take an error as their first argument.** + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +__Related__ + +* everyLimit(arr, limit, iterator, callback) + +--------------------------------------- + +<a name="concat" /> +### concat(arr, iterator, [callback]) + +Applies `iterator` to each item in `arr`, concatenating the results. Returns the +concatenated list. The `iterator`s 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 `arr` passed to the `iterator` function. + +__Arguments__ + +* `arr` - An array to iterate over. +* `iterator(item, callback)` - A function to apply to each item in `arr`. + The iterator is passed a `callback(err, results)` which must be called once it + has completed with an error (which can be `null`) and an array of results. +* `callback(err, results)` - *Optional* A callback which is called after all the `iterator` + functions have finished, or an error occurs. Results is an array containing + the concatenated results of the `iterator` function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +__Related__ + +* concatSeries(arr, iterator, [callback]) + + +## Control Flow + +<a name="series" /> +### series(tasks, [callback]) + +Run the functions in the `tasks` array 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 `callback` is immediately called with the value of the error. +Otherwise, `callback` receives an array of results when `tasks` have completed. + +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 +[`series`](#series). + +**Note** that while many implementations preserve the order of object properties, the +[ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) +explicitly states that + +> The mechanics and order of enumerating the properties is not specified. + +So if you rely on the order in which your series of functions are executed, and want +this to work on all platforms, consider using an array. + +__Arguments__ + +* `tasks` - An array or object containing functions to run, each function is passed + a `callback(err, result)` it must call on completion with an error `err` (which can + be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the `task` callbacks. + +__Example__ + +```js +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 the `tasks` 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. + +**Note:** `parallel` is about kicking-off I/O tasks in parallel, not about parallel execution of code. If your tasks do not use any timers or perform any I/O, they will actually be executed in series. Any synchronous setup sections for each task will happen one after the other. JavaScript remains single-threaded. + +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 +[`parallel`](#parallel). + + +__Arguments__ + +* `tasks` - An array or object containing functions to run. Each function is passed + a `callback(err, result)` which it must call on completion with an error `err` + (which can be `null`) and an optional `result` value. +* `callback(err, results)` - An optional callback to run once all the functions + have completed successfully. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// 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} +}); +``` + +__Related__ + +* parallelLimit(tasks, limit, [callback]) + +--------------------------------------- + +<a name="whilst" /> +### whilst(test, fn, callback) + +Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped, +or an error occurs. + +__Arguments__ + +* `test()` - synchronous truth test to perform before each execution of `fn`. +* `fn(callback)` - A function which is called each time `test` passes. The function is + passed a `callback(err)`, which must be called once it has completed with an + optional `err` argument. +* `callback(err, [results])` - A callback which is called after the test + function has failed and repeated execution of `fn` has stopped. `callback` + will be passed an error and any arguments passed to the final `fn`'s callback. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(function () { + callback(null, count); + }, 1000); + }, + function (err, n) { + // 5 seconds have passed, n = 5 + } +); +``` + +--------------------------------------- + +<a name="doWhilst" /> +### doWhilst(fn, test, callback) + +The post-check version of [`whilst`](#whilst). To reflect the difference in +the order of operations, the arguments `test` and `fn` are switched. + +`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + +<a name="until" /> +### until(test, fn, callback) + +Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped, +or an error occurs. `callback` will be passed an error and any arguments passed +to the final `fn`'s callback. + +The inverse of [`whilst`](#whilst). + +--------------------------------------- + +<a name="doUntil" /> +### doUntil(fn, test, callback) + +Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + +<a name="during" /> +### during(test, fn, callback) + +Like [`whilst`](#whilst), except the `test` is an asynchronous function that is passed a callback in the form of `function (err, truth)`. If error is passed to `test` or `fn`, the main callback is immediately called with the value of the error. + +__Example__ + +```js +var count = 0; + +async.during( + function (callback) { + return callback(null, count < 5); + }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + +<a name="doDuring" /> +### doDuring(fn, test, callback) + +The post-check version of [`during`](#during). To reflect the difference in +the order of operations, the arguments `test` and `fn` are switched. + +Also a version of [`doWhilst`](#doWhilst) with asynchronous `test` function. + +--------------------------------------- + +<a name="forever" /> +### forever(fn, [errback]) + +Calls the asynchronous function `fn` with a callback parameter that allows it to +call itself again, in series, indefinitely. + +If an error is passed to the callback then `errback` is called with the +error, and execution stops, otherwise it will never be called. + +```js +async.forever( + function(next) { + // next is suitable for passing to things that need a callback(err [, whatever]); + // it will result in this function being called again. + }, + function(err) { + // if next is called with a value in its first parameter, it will appear + // in here as 'err', and execution will stop. + } +); +``` + +--------------------------------------- + +<a name="waterfall" /> +### waterfall(tasks, [callback]) + +Runs the `tasks` array of functions in series, each passing their results to the next in +the array. However, if any of the `tasks` pass an error to their own 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(err, result1, result2, ...)` it must call on completion. The first + argument is an error (which can be `null`) and any further arguments will be + passed as arguments in order to the next task. +* `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__ + +```js +async.waterfall([ + function(callback) { + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); + }, + function(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` +Or, with named functions: + +```js +async.waterfall([ + myFirstFunction, + mySecondFunction, + myLastFunction, +], function (err, result) { + // result now equals 'done' +}); +function myFirstFunction(callback) { + callback(null, 'one', 'two'); +} +function mySecondFunction(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); +} +function myLastFunction(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); +} +``` + +Or, if you need to pass any argument to the first function: + +```js +async.waterfall([ + async.apply(myFirstFunction, 'zero'), + mySecondFunction, + myLastFunction, +], function (err, result) { + // result now equals 'done' +}); +function myFirstFunction(arg1, callback) { + // arg1 now equals 'zero' + callback(null, 'one', 'two'); +} +function mySecondFunction(arg1, arg2, callback) { + // arg1 now equals 'one' and arg2 now equals 'two' + callback(null, 'three'); +} +function myLastFunction(arg1, callback) { + // arg1 now equals 'three' + callback(null, 'done'); +} +``` + +--------------------------------------- +<a name="compose" /> +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions `f()`, `g()`, and `h()` would produce the result of +`f(g(h()))`, only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* `functions...` - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- +<a name="seq" /> +### seq(fn1, fn2...) + +Version of the compose function that is more natural to read. +Each function consumes the return value of the previous function. +It is the equivalent of [`compose`](#compose) with the arguments reversed. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* `functions...` - the asynchronous functions to compose + + +__Example__ + +```js +// Requires lodash (or underscore), express3 and dresende's orm2. +// Part of an app, that fetches cats of the logged user. +// This example uses `seq` function to avoid overnesting and error +// handling clutter. +app.get('/cats', function(request, response) { + var User = request.models.User; + async.seq( + _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) + function(user, fn) { + user.getCats(fn); // 'getCats' has signature (callback(err, data)) + } + )(req.session.user_id, function (err, cats) { + if (err) { + console.error(err); + response.json({ status: 'error', message: err.message }); + } else { + response.json({ status: 'ok', message: 'Cats found', data: cats }); + } + }); +}); +``` + +--------------------------------------- +<a name="applyEach" /> +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling +`callback` after all functions have completed. If you only provide the first +argument, then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* `fns` - the asynchronous functions to all call with the same arguments +* `args...` - any number of separate arguments to pass to the function +* `callback` - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +__Related__ + +* applyEachSeries(tasks, args..., [callback]) + +--------------------------------------- + +<a name="queue" /> +### queue(worker, [concurrency]) + +Creates a `queue` object with the specified `concurrency`. Tasks added to the +`queue` are processed in parallel (up to the `concurrency` limit). If all +`worker`s are in progress, the task is queued until one becomes available. +Once a `worker` completes a `task`, that `task`'s callback is called. + +__Arguments__ + +* `worker(task, callback)` - An asynchronous function for processing a queued + task, which must call its `callback(err)` argument when finished, with an + optional `error` as an argument. If you want to handle errors from an individual task, pass a callback to `q.push()`. +* `concurrency` - An `integer` for determining how many `worker` functions should be + run in parallel. If omitted, the concurrency defaults to `1`. If the concurrency is `0`, an error is thrown. + +__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. +* `started` - a function returning whether or not any items have been pushed and processed by the queue +* `running()` - a function returning the number of items currently being processed. +* `workersList()` - a function returning the array of items currently being processed. +* `idle()` - a function returning false if there are items waiting or being processed, or true if not. +* `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`. Calls `callback` once + the `worker` has finished processing the task. Instead of a single task, a `tasks` array + can be submitted. The respective callback is used for every task in the list. +* `unshift(task, [callback])` - add a new task to the front of the `queue`. +* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, + 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`. +* `paused` - a boolean for determining whether the queue is in a paused state +* `pause()` - a function that pauses the processing of tasks until `resume()` is called. +* `resume()` - a function that resumes the processing of queued tasks when the queue is paused. +* `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle. + +__Example__ + +```js +// 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 item'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + + +--------------------------------------- + +<a name="priorityQueue" /> +### priorityQueue(worker, concurrency) + +The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects: + +* `push(task, priority, [callback])` - `priority` should be a number. If an array of + `tasks` is given, all tasks will be assigned the same priority. +* The `unshift` method was removed. + +--------------------------------------- + +<a name="cargo" /> +### cargo(worker, [payload]) + +Creates a `cargo` object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the `payload` limit). If the +`worker` is in progress, the task is queued until it becomes available. Once +the `worker` has completed some tasks, each callback of those tasks is called. +Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966) for how `cargo` and `queue` work. + +While [queue](#queue) passes only one task to one of a group of workers +at a time, cargo passes an array of tasks to a single worker, repeating +when the worker is finished. + +__Arguments__ + +* `worker(tasks, callback)` - An asynchronous function for processing an array of + queued tasks, which must call its `callback(err)` argument when finished, with + an optional `err` argument. +* `payload` - An optional `integer` for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The `cargo` object returned by this function has the following properties and +methods: + +* `length()` - A function returning the number of items waiting to be processed. +* `payload` - An `integer` for determining how many tasks should be + process per round. This property can be changed after a `cargo` is created to + alter the payload on-the-fly. +* `push(task, [callback])` - Adds `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`. +* `idle()`, `pause()`, `resume()`, `kill()` - cargo inherits all of the same methods and event calbacks as [`queue`](#queue) + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i<tasks.length; i++){ + console.log('hello ' + tasks[i].name); + } + callback(); +}, 2); + + +// add some items + +cargo.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +cargo.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +cargo.push({name: 'baz'}, function (err) { + console.log('finished processing baz'); +}); +``` + +--------------------------------------- + +<a name="auto" /> +### auto(tasks, [concurrency], [callback]) + +Determines the best order for running the functions in `tasks`, 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, the `auto` sequence will stop. Further tasks will not execute (so any other functions depending on it will not run), and the main `callback` is immediately called with the error. Functions also receive an object containing the results of functions which have completed so far. + +Note, all functions are called with a `results` object as a second argument, +so it is unsafe to pass functions in the `tasks` object which cannot handle the +extra argument. + +For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8') +}, callback); +``` + +will have the effect of calling `readFile` with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to `readFile` in a function which does not forward the +`results` object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* `tasks` - An object. Each of its properties is either a function or an array of + requirements, with the function itself the last item in the array. The object's key + of a property serves as the name of the task defined by that property, + i.e. can be used when specifying requirements for other tasks. + The function receives two arguments: (1) a `callback(err, result)` which must be + called when finished, passing an `error` (which can be `null`) and the result of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions. +* `concurrency` - An optional `integer` for determining the maximum number of tasks that can be run in parallel. By default, as many as possible. +* `callback(err, results)` - An optional callback which is called when all the + tasks have been completed. It receives the `err` argument if any `tasks` + pass an error to their callback. Results are always returned; however, if + an error occurs, no further `tasks` will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + make_folder: function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + }, + write_file: ['get_data', 'make_folder', function(callback, results){ + console.log('in write_file', JSON.stringify(results)); + // 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){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + callback(null, {'file':results.write_file, 'email':'user@example.com'}); + }] +}, function(err, results) { + console.log('err = ', err); + console.log('results = ', results); +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + console.log('in get_data'); + // async code to get some data + callback(null, 'data', 'converted to array'); + }, + function(callback){ + console.log('in make_folder'); + // async code to create a directory to store a file in + // this is run at the same time as getting the data + callback(null, 'folder'); + } +], +function(err, results){ + async.series([ + function(callback){ + console.log('in write_file', JSON.stringify(results)); + // once there is some data and the directory exists, + // write the data to a file in the directory + results.push('filename'); + callback(null); + }, + function(callback){ + console.log('in email_link', JSON.stringify(results)); + // once the file is written let's email a link to it... + callback(null, {'file':results.pop(), 'email':'user@example.com'}); + } + ]); +}); +``` + +For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding +new tasks much easier (and the code more readable). + + +--------------------------------------- + +<a name="retry" /> +### retry([opts = {times: 5, interval: 0}| 5], task, [callback]) + +Attempts to get a successful response from `task` no more than `times` times before +returning an error. If the task is successful, the `callback` will be passed the result +of the successful task. If all attempts fail, the callback will be passed the error and +result (if any) of the final attempt. + +__Arguments__ + +* `opts` - Can be either an object with `times` and `interval` or a number. + * `times` - The number of attempts to make before giving up. The default is `5`. + * `interval` - The time to wait between retries, in milliseconds. The default is `0`. + * If `opts` is a number, the number specifies the number of times to retry, with the default interval of `0`. +* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)` + which must be called when finished, passing `err` (which can be `null`) and the `result` of + the function's execution, and (2) a `results` object, containing the results of + the previously executed functions (if nested inside another control flow). +* `callback(err, results)` - An optional callback which is called when the + task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`. + +The [`retry`](#retry) function can be used as a stand-alone control flow by passing a callback, as shown below: + +```js +// try calling apiMethod 3 times +async.retry(3, apiMethod, function(err, result) { + // do something with the result +}); +``` + +```js +// try calling apiMethod 3 times, waiting 200 ms between each retry +async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { + // do something with the result +}); +``` + +```js +// try calling apiMethod the default 5 times no delay between each retry +async.retry(apiMethod, function(err, result) { + // do something with the result +}); +``` + +It can also be embedded within other control flow functions to retry individual methods +that are not as reliable, like this: + +```js +async.auto({ + users: api.getUsers.bind(api), + payments: async.retry(3, api.getPayments.bind(api)) +}, function(err, results) { + // do something with the results +}); +``` + + +--------------------------------------- + +<a name="iterator" /> +### iterator(tasks) + +Creates an iterator function which calls the next function in the `tasks` array, +returning a continuation to call the next one after that. It's also possible to +“peek” at the next iterator with `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. + +__Example__ + +```js +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. + +Useful as a 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__ + +```js +// 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: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + +<a name="nextTick" /> +### nextTick(callback), setImmediate(callback) + +Calls `callback` on a later loop around the event loop. In Node.js this just +calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)` +if available, otherwise `setTimeout(callback, 0)`, which means other higher priority +events may precede the execution of `callback`. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* `callback` - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + +<a name="times" /> +### times(n, iterator, [callback]) + +Calls the `iterator` function `n` times, and accumulates results in the same manner +you would use with [`map`](#map). + +__Arguments__ + +* `n` - The number of times to run the function. +* `iterator` - The function to call `n` times. +* `callback` - see [`map`](#map) + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + +__Related__ + +* timesSeries(n, iterator, [callback]) +* timesLimit(n, limit, iterator, [callback]) + + +## 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. + +If no hash function is specified, the first argument is used as a hash key, which may work reasonably if it is a string or a data type that converts to a distinct string. Note that objects and arrays will not behave reasonably. Neither will cases where the other arguments are significant. In such cases, specify your own hash function. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* `fn` - The function 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__ + +```js +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 [`memoize`](#memoize)d function, reverting it to the original, unmemoized +form. Handy for testing. + +__Arguments__ + +* `fn` - the memoized function + +--------------------------------------- + +<a name="ensureAsync" /> +### ensureAsync(fn) + +Wrap an async function and ensure it calls its callback on a later tick of the event loop. If the function already calls its callback on a next tick, no extra deferral is added. This is useful for preventing stack overflows (`RangeError: Maximum call stack size exceeded`) and generally keeping [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony) contained. + +__Arguments__ + +* `fn` - an async function, one that expects a node-style callback as its last argument + +Returns a wrapped function with the exact same call signature as the function passed in. + +__Example__ + +```js +function sometimesAsync(arg, callback) { + if (cache[arg]) { + return callback(null, cache[arg]); // this would be synchronous!! + } else { + doSomeIO(arg, callback); // this IO would be asynchronous + } +} + +// this has a risk of stack overflows if many results are cached in a row +async.mapSeries(args, sometimesAsync, done); + +// this will defer sometimesAsync's callback if necessary, +// preventing stack overflows +async.mapSeries(args, async.ensureAsync(sometimesAsync), done); + +``` + +--------------------------------------- + +<a name="constant"> +### constant(values...) + +Returns a function that when called, calls-back with the values provided. Useful as the first function in a `waterfall`, or for plugging values in to `auto`. + +__Example__ + +```js +async.waterfall([ + async.constant(42), + function (value, next) { + // value === 42 + }, + //... +], callback); + +async.waterfall([ + async.constant(filename, "utf8"), + fs.readFile, + function (fileData, next) { + //... + } + //... +], callback); + +async.auto({ + hostname: async.constant("https://server.net/"), + port: findFreePort, + launchServer: ["hostname", "port", function (cb, options) { + startServer(options, cb); + }], + //... +}, callback); + +``` + +--------------------------------------- + +<a name="asyncify"> +<a name="wrapSync"> +### asyncify(func) + +__Alias:__ `wrapSync` + +Take a sync function and make it async, passing its return value to a callback. This is useful for plugging sync functions into a waterfall, series, or other async functions. Any arguments passed to the generated function will be passed to the wrapped function (except for the final callback argument). Errors thrown will be passed to the callback. + +__Example__ + +```js +async.waterfall([ + async.apply(fs.readFile, filename, "utf8"), + async.asyncify(JSON.parse), + function (data, next) { + // data is the result of parsing the text. + // If there was a parsing error, it would have been caught. + } +], callback) +``` + +If the function passed to `asyncify` returns a Promise, that promises's resolved/rejected state will be used to call the callback, rather than simply the synchronous return value. Example: + +```js +async.waterfall([ + async.apply(fs.readFile, filename, "utf8"), + async.asyncify(function (contents) { + return db.model.create(contents); + }), + function (model, next) { + // `model` is the instantiated model object. + // If there was an error, this function would be skipped. + } +], callback) +``` + +This also means you can asyncify ES2016 `async` functions. + +```js +var q = async.queue(async.asyncify(async function (file) { + var intermediateStep = await processFile(file); + return await somePromise(intermediateStep) +})); + +q.push(files); +``` + +--------------------------------------- + +<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__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +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__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +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. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.js new file mode 100644 index 0000000..31e7620 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.js @@ -0,0 +1,1265 @@ +/*! + * async + * https://github.com/caolan/async + * + * Copyright 2010-2014 Caolan McMahon + * Released under the MIT license + */ +(function () { + + var async = {}; + function noop() {} + function identity(v) { + return v; + } + function toBool(v) { + return !!v; + } + function notId(v) { + return !v; + } + + // global on the server, window in the browser + var previous_async; + + // Establish the root object, `window` (`self`) in the browser, `global` + // on the server, or `this` in some virtual machines. We use `self` + // instead of `window` for `WebWorker` support. + var root = typeof self === 'object' && self.self === self && self || + typeof global === 'object' && global.global === global && global || + this; + + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + return function() { + if (fn === null) throw new Error("Callback was already called."); + fn.apply(this, arguments); + fn = null; + }; + } + + function _once(fn) { + return function() { + if (fn === null) return; + fn.apply(this, arguments); + fn = null; + }; + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString; + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]'; + }; + + // Ported from underscore.js isObject + var _isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + function _isArrayLike(arr) { + return _isArray(arr) || ( + // has a positive integer length property + typeof arr.length === "number" && + arr.length >= 0 && + arr.length % 1 === 0 + ); + } + + function _arrayEach(arr, iterator) { + var index = -1, + length = arr.length; + + while (++index < length) { + iterator(arr[index], index, arr); + } + } + + function _map(arr, iterator) { + var index = -1, + length = arr.length, + result = Array(length); + + while (++index < length) { + result[index] = iterator(arr[index], index, arr); + } + return result; + } + + function _range(count) { + return _map(Array(count), function (v, i) { return i; }); + } + + function _reduce(arr, iterator, memo) { + _arrayEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + } + + function _forEachOf(object, iterator) { + _arrayEach(_keys(object), function (key) { + iterator(object[key], key); + }); + } + + function _indexOf(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === item) return i; + } + return -1; + } + + var _keys = Object.keys || function (obj) { + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + function _keyIterator(coll) { + var i = -1; + var len; + var keys; + if (_isArrayLike(coll)) { + len = coll.length; + return function next() { + i++; + return i < len ? i : null; + }; + } else { + keys = _keys(coll); + len = keys.length; + return function next() { + i++; + return i < len ? keys[i] : null; + }; + } + } + + // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) + // This accumulates the arguments passed into an array, after a given index. + // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). + function _restParam(func, startIndex) { + startIndex = startIndex == null ? func.length - 1 : +startIndex; + return function() { + var length = Math.max(arguments.length - startIndex, 0); + var rest = Array(length); + for (var index = 0; index < length; index++) { + rest[index] = arguments[index + startIndex]; + } + switch (startIndex) { + case 0: return func.call(this, rest); + case 1: return func.call(this, arguments[0], rest); + } + // Currently unused but handle cases outside of the switch statement: + // var args = Array(startIndex + 1); + // for (index = 0; index < startIndex; index++) { + // args[index] = arguments[index]; + // } + // args[startIndex] = rest; + // return func.apply(this, args); + }; + } + + function _withoutIndex(iterator) { + return function (value, index, callback) { + return iterator(value, callback); + }; + } + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + + // capture the global reference to guard against fakeTimer mocks + var _setImmediate = typeof setImmediate === 'function' && setImmediate; + + var _delay = _setImmediate ? function(fn) { + // not a direct alias for IE10 compatibility + _setImmediate(fn); + } : function(fn) { + setTimeout(fn, 0); + }; + + if (typeof process === 'object' && typeof process.nextTick === 'function') { + async.nextTick = process.nextTick; + } else { + async.nextTick = _delay; + } + async.setImmediate = _setImmediate ? _delay : async.nextTick; + + + async.forEach = + async.each = function (arr, iterator, callback) { + return async.eachOf(arr, _withoutIndex(iterator), callback); + }; + + async.forEachSeries = + async.eachSeries = function (arr, iterator, callback) { + return async.eachOfSeries(arr, _withoutIndex(iterator), callback); + }; + + + async.forEachLimit = + async.eachLimit = function (arr, limit, iterator, callback) { + return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); + }; + + async.forEachOf = + async.eachOf = function (object, iterator, callback) { + callback = _once(callback || noop); + object = object || []; + + var iter = _keyIterator(object); + var key, completed = 0; + + while ((key = iter()) != null) { + completed += 1; + iterator(object[key], key, only_once(done)); + } + + if (completed === 0) callback(null); + + function done(err) { + completed--; + if (err) { + callback(err); + } + // Check key is null in case iterator isn't exhausted + // and done resolved synchronously. + else if (key === null && completed <= 0) { + callback(null); + } + } + }; + + async.forEachOfSeries = + async.eachOfSeries = function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + var key = nextKey(); + function iterate() { + var sync = true; + if (key === null) { + return callback(null); + } + iterator(obj[key], key, only_once(function (err) { + if (err) { + callback(err); + } + else { + key = nextKey(); + if (key === null) { + return callback(null); + } else { + if (sync) { + async.setImmediate(iterate); + } else { + iterate(); + } + } + } + })); + sync = false; + } + iterate(); + }; + + + + async.forEachOfLimit = + async.eachOfLimit = function (obj, limit, iterator, callback) { + _eachOfLimit(limit)(obj, iterator, callback); + }; + + function _eachOfLimit(limit) { + + return function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + if (limit <= 0) { + return callback(null); + } + var done = false; + var running = 0; + var errored = false; + + (function replenish () { + if (done && running <= 0) { + return callback(null); + } + + while (running < limit && !errored) { + var key = nextKey(); + if (key === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iterator(obj[key], key, only_once(function (err) { + running -= 1; + if (err) { + callback(err); + errored = true; + } + else { + replenish(); + } + })); + } + })(); + }; + } + + + function doParallel(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOf, obj, iterator, callback); + }; + } + function doParallelLimit(fn) { + return function (obj, limit, iterator, callback) { + return fn(_eachOfLimit(limit), obj, iterator, callback); + }; + } + function doSeries(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOfSeries, obj, iterator, callback); + }; + } + + function _asyncMap(eachfn, arr, iterator, callback) { + callback = _once(callback || noop); + arr = arr || []; + var results = _isArrayLike(arr) ? [] : {}; + eachfn(arr, function (value, index, callback) { + iterator(value, function (err, v) { + results[index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = doParallelLimit(_asyncMap); + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.inject = + async.foldl = + async.reduce = function (arr, memo, iterator, callback) { + async.eachOfSeries(arr, function (x, i, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + + async.foldr = + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, identity).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + + async.transform = function (arr, memo, iterator, callback) { + if (arguments.length === 3) { + callback = iterator; + iterator = memo; + memo = _isArray(arr) ? [] : {}; + } + + async.eachOf(arr, function(v, k, cb) { + iterator(memo, v, k, cb); + }, function(err) { + callback(err, memo); + }); + }; + + function _filter(eachfn, arr, iterator, callback) { + var results = []; + eachfn(arr, function (x, index, callback) { + iterator(x, function (v) { + if (v) { + results.push({index: index, value: x}); + } + callback(); + }); + }, function () { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + } + + async.select = + async.filter = doParallel(_filter); + + async.selectLimit = + async.filterLimit = doParallelLimit(_filter); + + async.selectSeries = + async.filterSeries = doSeries(_filter); + + function _reject(eachfn, arr, iterator, callback) { + _filter(eachfn, arr, function(value, cb) { + iterator(value, function(v) { + cb(!v); + }); + }, callback); + } + async.reject = doParallel(_reject); + async.rejectLimit = doParallelLimit(_reject); + async.rejectSeries = doSeries(_reject); + + function _createTester(eachfn, check, getResult) { + return function(arr, limit, iterator, cb) { + function done() { + if (cb) cb(getResult(false, void 0)); + } + function iteratee(x, _, callback) { + if (!cb) return callback(); + iterator(x, function (v) { + if (cb && check(v)) { + cb(getResult(true, x)); + cb = iterator = false; + } + callback(); + }); + } + if (arguments.length > 3) { + eachfn(arr, limit, iteratee, done); + } else { + cb = iterator; + iterator = limit; + eachfn(arr, iteratee, done); + } + }; + } + + async.any = + async.some = _createTester(async.eachOf, toBool, identity); + + async.someLimit = _createTester(async.eachOfLimit, toBool, identity); + + async.all = + async.every = _createTester(async.eachOf, notId, notId); + + async.everyLimit = _createTester(async.eachOfLimit, notId, notId); + + function _findGetResult(v, x) { + return x; + } + async.detect = _createTester(async.eachOf, identity, _findGetResult); + async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); + async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); + + 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 { + callback(null, _map(results.sort(comparator), function (x) { + return x.value; + })); + } + + }); + + function comparator(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } + }; + + async.auto = function (tasks, concurrency, callback) { + if (typeof arguments[1] === 'function') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = _once(callback || noop); + var keys = _keys(tasks); + var remainingTasks = keys.length; + if (!remainingTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = remainingTasks; + } + + var results = {}; + var runningTasks = 0; + + var hasError = false; + + var listeners = []; + function addListener(fn) { + listeners.unshift(fn); + } + function removeListener(fn) { + var idx = _indexOf(listeners, fn); + if (idx >= 0) listeners.splice(idx, 1); + } + function taskComplete() { + remainingTasks--; + _arrayEach(listeners.slice(0), function (fn) { + fn(); + }); + } + + addListener(function () { + if (!remainingTasks) { + callback(null, results); + } + }); + + _arrayEach(keys, function (k) { + if (hasError) return; + var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; + var taskCallback = _restParam(function(err, args) { + runningTasks--; + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _forEachOf(results, function(val, rkey) { + safeResults[rkey] = val; + }); + safeResults[k] = args; + hasError = true; + + callback(err, safeResults); + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }); + var requires = task.slice(0, task.length - 1); + // prevent dead-locks + var len = requires.length; + var dep; + while (len--) { + if (!(dep = tasks[requires[len]])) { + throw new Error('Has nonexistent dependency in ' + requires.join(', ')); + } + if (_isArray(dep) && _indexOf(dep, k) >= 0) { + throw new Error('Has cyclic dependencies'); + } + } + function ready() { + return runningTasks < concurrency && _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + } + if (ready()) { + runningTasks++; + task[task.length - 1](taskCallback, results); + } + else { + addListener(listener); + } + function listener() { + if (ready()) { + runningTasks++; + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + } + }); + }; + + + + async.retry = function(times, task, callback) { + var DEFAULT_TIMES = 5; + var DEFAULT_INTERVAL = 0; + + var attempts = []; + + var opts = { + times: DEFAULT_TIMES, + interval: DEFAULT_INTERVAL + }; + + function parseTimes(acc, t){ + if(typeof t === 'number'){ + acc.times = parseInt(t, 10) || DEFAULT_TIMES; + } else if(typeof t === 'object'){ + acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; + acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; + } else { + throw new Error('Unsupported argument type for \'times\': ' + typeof t); + } + } + + var length = arguments.length; + if (length < 1 || length > 3) { + throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); + } else if (length <= 2 && typeof times === 'function') { + callback = task; + task = times; + } + if (typeof times !== 'function') { + parseTimes(opts, times); + } + opts.callback = callback; + opts.task = task; + + function wrappedTask(wrappedCallback, wrappedResults) { + function retryAttempt(task, finalAttempt) { + return function(seriesCallback) { + task(function(err, result){ + seriesCallback(!err || finalAttempt, {err: err, result: result}); + }, wrappedResults); + }; + } + + function retryInterval(interval){ + return function(seriesCallback){ + setTimeout(function(){ + seriesCallback(null); + }, interval); + }; + } + + while (opts.times) { + + var finalAttempt = !(opts.times-=1); + attempts.push(retryAttempt(opts.task, finalAttempt)); + if(!finalAttempt && opts.interval > 0){ + attempts.push(retryInterval(opts.interval)); + } + } + + async.series(attempts, function(done, data){ + data = data[data.length - 1]; + (wrappedCallback || opts.callback)(data.err, data.result); + }); + } + + // If a callback is passed, run this as a controll flow + return opts.callback ? wrappedTask() : wrappedTask; + }; + + async.waterfall = function (tasks, callback) { + callback = _once(callback || noop); + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + function wrapIterator(iterator) { + return _restParam(function (err, args) { + if (err) { + callback.apply(null, [err].concat(args)); + } + else { + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + ensureAsync(iterator).apply(null, args); + } + }); + } + wrapIterator(async.iterator(tasks))(); + }; + + function _parallel(eachfn, tasks, callback) { + callback = callback || noop; + var results = _isArrayLike(tasks) ? [] : {}; + + eachfn(tasks, function (task, key, callback) { + task(_restParam(function (err, args) { + if (args.length <= 1) { + args = args[0]; + } + results[key] = args; + callback(err); + })); + }, function (err) { + callback(err, results); + }); + } + + async.parallel = function (tasks, callback) { + _parallel(async.eachOf, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel(_eachOfLimit(limit), tasks, callback); + }; + + async.series = function(tasks, callback) { + _parallel(async.eachOfSeries, tasks, callback); + }; + + async.iterator = function (tasks) { + function makeCallback(index) { + function fn() { + 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 = _restParam(function (fn, args) { + return _restParam(function (callArgs) { + return fn.apply( + null, args.concat(callArgs) + ); + }); + }); + + function _concat(eachfn, arr, fn, callback) { + var result = []; + eachfn(arr, function (x, index, cb) { + fn(x, function (err, y) { + result = result.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, result); + }); + } + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + callback = callback || noop; + if (test()) { + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else if (test.apply(this, args)) { + iterator(next); + } else { + callback.apply(null, [null].concat(args)); + } + }); + iterator(next); + } else { + callback(null); + } + }; + + async.doWhilst = function (iterator, test, callback) { + var calls = 0; + return async.whilst(function() { + return ++calls <= 1 || test.apply(this, arguments); + }, iterator, callback); + }; + + async.until = function (test, iterator, callback) { + return async.whilst(function() { + return !test.apply(this, arguments); + }, iterator, callback); + }; + + async.doUntil = function (iterator, test, callback) { + return async.doWhilst(iterator, function() { + return !test.apply(this, arguments); + }, callback); + }; + + async.during = function (test, iterator, callback) { + callback = callback || noop; + + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else { + args.push(check); + test.apply(this, args); + } + }); + + var check = function(err, truth) { + if (err) { + callback(err); + } else if (truth) { + iterator(next); + } else { + callback(null); + } + }; + + test(check); + }; + + async.doDuring = function (iterator, test, callback) { + var calls = 0; + async.during(function(next) { + if (calls++ < 1) { + next(null, true); + } else { + test.apply(this, arguments); + } + }, iterator, callback); + }; + + function _queue(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } + else if(concurrency === 0) { + throw new Error('Concurrency must not be zero'); + } + function _insert(q, data, pos, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + callback: callback || noop + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + }); + async.setImmediate(q.process); + } + function _next(q, tasks) { + return function(){ + workers -= 1; + + var removed = false; + var args = arguments; + _arrayEach(tasks, function (task) { + _arrayEach(workersList, function (worker, index) { + if (worker === task && !removed) { + workersList.splice(index, 1); + removed = true; + } + }); + + task.callback.apply(task, args); + }); + if (q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + } + + var workers = 0; + var workersList = []; + var q = { + tasks: [], + concurrency: concurrency, + payload: payload, + saturated: noop, + empty: noop, + drain: noop, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + kill: function () { + q.drain = noop; + q.tasks = []; + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + while(!q.paused && workers < q.concurrency && q.tasks.length){ + + var tasks = q.payload ? + q.tasks.splice(0, q.payload) : + q.tasks.splice(0, q.tasks.length); + + var data = _map(tasks, function (task) { + return task.data; + }); + + if (q.tasks.length === 0) { + q.empty(); + } + workers += 1; + workersList.push(tasks[0]); + var cb = only_once(_next(q, tasks)); + worker(data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + }, + workersList: function () { + return workersList; + }, + idle: function() { + return q.tasks.length + workers === 0; + }, + pause: function () { + q.paused = true; + }, + resume: function () { + if (q.paused === false) { return; } + q.paused = false; + var resumeCount = Math.min(q.concurrency, q.tasks.length); + // Need to call q.process once per concurrent + // worker to preserve full concurrency after pause + for (var w = 1; w <= resumeCount; w++) { + async.setImmediate(q.process); + } + } + }; + return q; + } + + async.queue = function (worker, concurrency) { + var q = _queue(function (items, cb) { + worker(items[0], cb); + }, concurrency, 1); + + return q; + }; + + async.priorityQueue = function (worker, concurrency) { + + function _compareTasks(a, b){ + return a.priority - b.priority; + } + + function _binarySearch(sequence, item, compare) { + var beg = -1, + end = sequence.length - 1; + while (beg < end) { + var mid = beg + ((end - beg + 1) >>> 1); + if (compare(item, sequence[mid]) >= 0) { + beg = mid; + } else { + end = mid - 1; + } + } + return beg; + } + + function _insert(q, data, priority, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + priority: priority, + callback: typeof callback === 'function' ? callback : noop + }; + + q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + // Start with a normal queue + var q = async.queue(worker, concurrency); + + // Override push to accept second parameter representing priority + q.push = function (data, priority, callback) { + _insert(q, data, priority, callback); + }; + + // Remove unshift function + delete q.unshift; + + return q; + }; + + async.cargo = function (worker, payload) { + return _queue(worker, 1, payload); + }; + + function _console_fn(name) { + return _restParam(function (fn, args) { + fn.apply(null, args.concat([_restParam(function (err, args) { + if (typeof console === 'object') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _arrayEach(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 = {}; + var has = Object.prototype.hasOwnProperty; + hasher = hasher || identity; + var memoized = _restParam(function memoized(args) { + var callback = args.pop(); + var key = hasher.apply(null, args); + if (has.call(memo, key)) { + async.setImmediate(function () { + callback.apply(null, memo[key]); + }); + } + else if (has.call(queues, key)) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([_restParam(function (args) { + memo[key] = args; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, args); + } + })])); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + function _times(mapper) { + return function (count, iterator, callback) { + mapper(_range(count), iterator, callback); + }; + } + + async.times = _times(async.map); + async.timesSeries = _times(async.mapSeries); + async.timesLimit = function (count, limit, iterator, callback) { + return async.mapLimit(_range(count), limit, iterator, callback); + }; + + async.seq = function (/* functions... */) { + var fns = arguments; + return _restParam(function (args) { + var that = this; + + var callback = args[args.length - 1]; + if (typeof callback == 'function') { + args.pop(); + } else { + callback = noop; + } + + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { + cb(err, nextargs); + })])); + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }); + }; + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)); + }; + + + function _applyEach(eachfn) { + return _restParam(function(fns, args) { + var go = _restParam(function(args) { + var that = this; + var callback = args.pop(); + return eachfn(fns, function (fn, _, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }); + if (args.length) { + return go.apply(this, args); + } + else { + return go; + } + }); + } + + async.applyEach = _applyEach(async.eachOf); + async.applyEachSeries = _applyEach(async.eachOfSeries); + + + async.forever = function (fn, callback) { + var done = only_once(callback || noop); + var task = ensureAsync(fn); + function next(err) { + if (err) { + return done(err); + } + task(next); + } + next(); + }; + + function ensureAsync(fn) { + return _restParam(function (args) { + var callback = args.pop(); + args.push(function () { + var innerArgs = arguments; + if (sync) { + async.setImmediate(function () { + callback.apply(null, innerArgs); + }); + } else { + callback.apply(null, innerArgs); + } + }); + var sync = true; + fn.apply(this, args); + sync = false; + }); + } + + async.ensureAsync = ensureAsync; + + async.constant = _restParam(function(values) { + var args = [null].concat(values); + return function (callback) { + return callback.apply(this, args); + }; + }); + + async.wrapSync = + async.asyncify = function asyncify(func) { + return _restParam(function (args) { + var callback = args.pop(); + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (_isObject(result) && typeof result.then === "function") { + result.then(function(value) { + callback(null, value); + })["catch"](function(err) { + callback(err.message ? err : new Error(err)); + }); + } else { + callback(null, result); + } + }); + }; + + // Node.js + if (typeof module === 'object' && module.exports) { + module.exports = async; + } + // AMD / RequireJS + else if (typeof define === 'function' && define.amd) { + define([], function () { + return async; + }); + } + // included directly via <script> tag + else { + root.async = async; + } + +}()); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.min.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.min.js new file mode 100644 index 0000000..2490016 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/dist/async.min.js @@ -0,0 +1,2 @@ +!function(){function n(){}function t(n){return n}function e(n){return!!n}function r(n){return!n}function u(n){return function(){if(null===n)throw new Error("Callback was already called.");n.apply(this,arguments),n=null}}function i(n){return function(){null!==n&&(n.apply(this,arguments),n=null)}}function o(n){return M(n)||"number"==typeof n.length&&n.length>=0&&n.length%1===0}function c(n,t){for(var e=-1,r=n.length;++e<r;)t(n[e],e,n)}function a(n,t){for(var e=-1,r=n.length,u=Array(r);++e<r;)u[e]=t(n[e],e,n);return u}function f(n){return a(Array(n),function(n,t){return t})}function l(n,t,e){return c(n,function(n,r,u){e=t(e,n,r,u)}),e}function s(n,t){c(W(n),function(e){t(n[e],e)})}function p(n,t){for(var e=0;e<n.length;e++)if(n[e]===t)return e;return-1}function h(n){var t,e,r=-1;return o(n)?(t=n.length,function(){return r++,t>r?r:null}):(e=W(n),t=e.length,function(){return r++,t>r?e[r]:null})}function m(n,t){return t=null==t?n.length-1:+t,function(){for(var e=Math.max(arguments.length-t,0),r=Array(e),u=0;e>u;u++)r[u]=arguments[u+t];switch(t){case 0:return n.call(this,r);case 1:return n.call(this,arguments[0],r)}}}function y(n){return function(t,e,r){return n(t,r)}}function v(t){return function(e,r,o){o=i(o||n),e=e||[];var c=h(e);if(0>=t)return o(null);var a=!1,f=0,l=!1;!function s(){if(a&&0>=f)return o(null);for(;t>f&&!l;){var n=c();if(null===n)return a=!0,void(0>=f&&o(null));f+=1,r(e[n],n,u(function(n){f-=1,n?(o(n),l=!0):s()}))}}()}}function d(n){return function(t,e,r){return n(P.eachOf,t,e,r)}}function g(n){return function(t,e,r,u){return n(v(e),t,r,u)}}function k(n){return function(t,e,r){return n(P.eachOfSeries,t,e,r)}}function b(t,e,r,u){u=i(u||n),e=e||[];var c=o(e)?[]:{};t(e,function(n,t,e){r(n,function(n,r){c[t]=r,e(n)})},function(n){u(n,c)})}function w(n,t,e,r){var u=[];n(t,function(n,t,r){e(n,function(e){e&&u.push({index:t,value:n}),r()})},function(){r(a(u.sort(function(n,t){return n.index-t.index}),function(n){return n.value}))})}function O(n,t,e,r){w(n,t,function(n,t){e(n,function(n){t(!n)})},r)}function S(n,t,e){return function(r,u,i,o){function c(){o&&o(e(!1,void 0))}function a(n,r,u){return o?void i(n,function(r){o&&t(r)&&(o(e(!0,n)),o=i=!1),u()}):u()}arguments.length>3?n(r,u,a,c):(o=i,i=u,n(r,a,c))}}function E(n,t){return t}function L(t,e,r){r=r||n;var u=o(e)?[]:{};t(e,function(n,t,e){n(m(function(n,r){r.length<=1&&(r=r[0]),u[t]=r,e(n)}))},function(n){r(n,u)})}function j(n,t,e,r){var u=[];n(t,function(n,t,r){e(n,function(n,t){u=u.concat(t||[]),r(n)})},function(n){r(n,u)})}function I(t,e,r){function i(t,e,r,u){if(null!=u&&"function"!=typeof u)throw new Error("task callback must be a function");return t.started=!0,M(e)||(e=[e]),0===e.length&&t.idle()?P.setImmediate(function(){t.drain()}):(c(e,function(e){var i={data:e,callback:u||n};r?t.tasks.unshift(i):t.tasks.push(i),t.tasks.length===t.concurrency&&t.saturated()}),void P.setImmediate(t.process))}function o(n,t){return function(){f-=1;var e=!1,r=arguments;c(t,function(n){c(l,function(t,r){t!==n||e||(l.splice(r,1),e=!0)}),n.callback.apply(n,r)}),n.tasks.length+f===0&&n.drain(),n.process()}}if(null==e)e=1;else if(0===e)throw new Error("Concurrency must not be zero");var f=0,l=[],s={tasks:[],concurrency:e,payload:r,saturated:n,empty:n,drain:n,started:!1,paused:!1,push:function(n,t){i(s,n,!1,t)},kill:function(){s.drain=n,s.tasks=[]},unshift:function(n,t){i(s,n,!0,t)},process:function(){for(;!s.paused&&f<s.concurrency&&s.tasks.length;){var n=s.payload?s.tasks.splice(0,s.payload):s.tasks.splice(0,s.tasks.length),e=a(n,function(n){return n.data});0===s.tasks.length&&s.empty(),f+=1,l.push(n[0]);var r=u(o(s,n));t(e,r)}},length:function(){return s.tasks.length},running:function(){return f},workersList:function(){return l},idle:function(){return s.tasks.length+f===0},pause:function(){s.paused=!0},resume:function(){if(s.paused!==!1){s.paused=!1;for(var n=Math.min(s.concurrency,s.tasks.length),t=1;n>=t;t++)P.setImmediate(s.process)}}};return s}function x(n){return m(function(t,e){t.apply(null,e.concat([m(function(t,e){"object"==typeof console&&(t?console.error&&console.error(t):console[n]&&c(e,function(t){console[n](t)}))})]))})}function A(n){return function(t,e,r){n(f(t),e,r)}}function T(n){return m(function(t,e){var r=m(function(e){var r=this,u=e.pop();return n(t,function(n,t,u){n.apply(r,e.concat([u]))},u)});return e.length?r.apply(this,e):r})}function z(n){return m(function(t){var e=t.pop();t.push(function(){var n=arguments;r?P.setImmediate(function(){e.apply(null,n)}):e.apply(null,n)});var r=!0;n.apply(this,t),r=!1})}var q,P={},C="object"==typeof self&&self.self===self&&self||"object"==typeof global&&global.global===global&&global||this;null!=C&&(q=C.async),P.noConflict=function(){return C.async=q,P};var H=Object.prototype.toString,M=Array.isArray||function(n){return"[object Array]"===H.call(n)},U=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},W=Object.keys||function(n){var t=[];for(var e in n)n.hasOwnProperty(e)&&t.push(e);return t},B="function"==typeof setImmediate&&setImmediate,D=B?function(n){B(n)}:function(n){setTimeout(n,0)};"object"==typeof process&&"function"==typeof process.nextTick?P.nextTick=process.nextTick:P.nextTick=D,P.setImmediate=B?D:P.nextTick,P.forEach=P.each=function(n,t,e){return P.eachOf(n,y(t),e)},P.forEachSeries=P.eachSeries=function(n,t,e){return P.eachOfSeries(n,y(t),e)},P.forEachLimit=P.eachLimit=function(n,t,e,r){return v(t)(n,y(e),r)},P.forEachOf=P.eachOf=function(t,e,r){function o(n){f--,n?r(n):null===c&&0>=f&&r(null)}r=i(r||n),t=t||[];for(var c,a=h(t),f=0;null!=(c=a());)f+=1,e(t[c],c,u(o));0===f&&r(null)},P.forEachOfSeries=P.eachOfSeries=function(t,e,r){function o(){var n=!0;return null===a?r(null):(e(t[a],a,u(function(t){if(t)r(t);else{if(a=c(),null===a)return r(null);n?P.setImmediate(o):o()}})),void(n=!1))}r=i(r||n),t=t||[];var c=h(t),a=c();o()},P.forEachOfLimit=P.eachOfLimit=function(n,t,e,r){v(t)(n,e,r)},P.map=d(b),P.mapSeries=k(b),P.mapLimit=g(b),P.inject=P.foldl=P.reduce=function(n,t,e,r){P.eachOfSeries(n,function(n,r,u){e(t,n,function(n,e){t=e,u(n)})},function(n){r(n,t)})},P.foldr=P.reduceRight=function(n,e,r,u){var i=a(n,t).reverse();P.reduce(i,e,r,u)},P.transform=function(n,t,e,r){3===arguments.length&&(r=e,e=t,t=M(n)?[]:{}),P.eachOf(n,function(n,r,u){e(t,n,r,u)},function(n){r(n,t)})},P.select=P.filter=d(w),P.selectLimit=P.filterLimit=g(w),P.selectSeries=P.filterSeries=k(w),P.reject=d(O),P.rejectLimit=g(O),P.rejectSeries=k(O),P.any=P.some=S(P.eachOf,e,t),P.someLimit=S(P.eachOfLimit,e,t),P.all=P.every=S(P.eachOf,r,r),P.everyLimit=S(P.eachOfLimit,r,r),P.detect=S(P.eachOf,t,E),P.detectSeries=S(P.eachOfSeries,t,E),P.detectLimit=S(P.eachOfLimit,t,E),P.sortBy=function(n,t,e){function r(n,t){var e=n.criteria,r=t.criteria;return r>e?-1:e>r?1:0}P.map(n,function(n,e){t(n,function(t,r){t?e(t):e(null,{value:n,criteria:r})})},function(n,t){return n?e(n):void e(null,a(t.sort(r),function(n){return n.value}))})},P.auto=function(t,e,r){function u(n){g.unshift(n)}function o(n){var t=p(g,n);t>=0&&g.splice(t,1)}function a(){h--,c(g.slice(0),function(n){n()})}"function"==typeof arguments[1]&&(r=e,e=null),r=i(r||n);var f=W(t),h=f.length;if(!h)return r(null);e||(e=h);var y={},v=0,d=!1,g=[];u(function(){h||r(null,y)}),c(f,function(n){function i(){return e>v&&l(k,function(n,t){return n&&y.hasOwnProperty(t)},!0)&&!y.hasOwnProperty(n)}function c(){i()&&(v++,o(c),h[h.length-1](g,y))}if(!d){for(var f,h=M(t[n])?t[n]:[t[n]],g=m(function(t,e){if(v--,e.length<=1&&(e=e[0]),t){var u={};s(y,function(n,t){u[t]=n}),u[n]=e,d=!0,r(t,u)}else y[n]=e,P.setImmediate(a)}),k=h.slice(0,h.length-1),b=k.length;b--;){if(!(f=t[k[b]]))throw new Error("Has nonexistent dependency in "+k.join(", "));if(M(f)&&p(f,n)>=0)throw new Error("Has cyclic dependencies")}i()?(v++,h[h.length-1](g,y)):u(c)}})},P.retry=function(n,t,e){function r(n,t){if("number"==typeof t)n.times=parseInt(t,10)||i;else{if("object"!=typeof t)throw new Error("Unsupported argument type for 'times': "+typeof t);n.times=parseInt(t.times,10)||i,n.interval=parseInt(t.interval,10)||o}}function u(n,t){function e(n,e){return function(r){n(function(n,t){r(!n||e,{err:n,result:t})},t)}}function r(n){return function(t){setTimeout(function(){t(null)},n)}}for(;a.times;){var u=!(a.times-=1);c.push(e(a.task,u)),!u&&a.interval>0&&c.push(r(a.interval))}P.series(c,function(t,e){e=e[e.length-1],(n||a.callback)(e.err,e.result)})}var i=5,o=0,c=[],a={times:i,interval:o},f=arguments.length;if(1>f||f>3)throw new Error("Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)");return 2>=f&&"function"==typeof n&&(e=t,t=n),"function"!=typeof n&&r(a,n),a.callback=e,a.task=t,a.callback?u():u},P.waterfall=function(t,e){function r(n){return m(function(t,u){if(t)e.apply(null,[t].concat(u));else{var i=n.next();i?u.push(r(i)):u.push(e),z(n).apply(null,u)}})}if(e=i(e||n),!M(t)){var u=new Error("First argument to waterfall must be an array of functions");return e(u)}return t.length?void r(P.iterator(t))():e()},P.parallel=function(n,t){L(P.eachOf,n,t)},P.parallelLimit=function(n,t,e){L(v(t),n,e)},P.series=function(n,t){L(P.eachOfSeries,n,t)},P.iterator=function(n){function t(e){function r(){return n.length&&n[e].apply(null,arguments),r.next()}return r.next=function(){return e<n.length-1?t(e+1):null},r}return t(0)},P.apply=m(function(n,t){return m(function(e){return n.apply(null,t.concat(e))})}),P.concat=d(j),P.concatSeries=k(j),P.whilst=function(t,e,r){if(r=r||n,t()){var u=m(function(n,i){n?r(n):t.apply(this,i)?e(u):r.apply(null,[null].concat(i))});e(u)}else r(null)},P.doWhilst=function(n,t,e){var r=0;return P.whilst(function(){return++r<=1||t.apply(this,arguments)},n,e)},P.until=function(n,t,e){return P.whilst(function(){return!n.apply(this,arguments)},t,e)},P.doUntil=function(n,t,e){return P.doWhilst(n,function(){return!t.apply(this,arguments)},e)},P.during=function(t,e,r){r=r||n;var u=m(function(n,e){n?r(n):(e.push(i),t.apply(this,e))}),i=function(n,t){n?r(n):t?e(u):r(null)};t(i)},P.doDuring=function(n,t,e){var r=0;P.during(function(n){r++<1?n(null,!0):t.apply(this,arguments)},n,e)},P.queue=function(n,t){var e=I(function(t,e){n(t[0],e)},t,1);return e},P.priorityQueue=function(t,e){function r(n,t){return n.priority-t.priority}function u(n,t,e){for(var r=-1,u=n.length-1;u>r;){var i=r+(u-r+1>>>1);e(t,n[i])>=0?r=i:u=i-1}return r}function i(t,e,i,o){if(null!=o&&"function"!=typeof o)throw new Error("task callback must be a function");return t.started=!0,M(e)||(e=[e]),0===e.length?P.setImmediate(function(){t.drain()}):void c(e,function(e){var c={data:e,priority:i,callback:"function"==typeof o?o:n};t.tasks.splice(u(t.tasks,c,r)+1,0,c),t.tasks.length===t.concurrency&&t.saturated(),P.setImmediate(t.process)})}var o=P.queue(t,e);return o.push=function(n,t,e){i(o,n,t,e)},delete o.unshift,o},P.cargo=function(n,t){return I(n,1,t)},P.log=x("log"),P.dir=x("dir"),P.memoize=function(n,e){var r={},u={},i=Object.prototype.hasOwnProperty;e=e||t;var o=m(function(t){var o=t.pop(),c=e.apply(null,t);i.call(r,c)?P.setImmediate(function(){o.apply(null,r[c])}):i.call(u,c)?u[c].push(o):(u[c]=[o],n.apply(null,t.concat([m(function(n){r[c]=n;var t=u[c];delete u[c];for(var e=0,i=t.length;i>e;e++)t[e].apply(null,n)})])))});return o.memo=r,o.unmemoized=n,o},P.unmemoize=function(n){return function(){return(n.unmemoized||n).apply(null,arguments)}},P.times=A(P.map),P.timesSeries=A(P.mapSeries),P.timesLimit=function(n,t,e,r){return P.mapLimit(f(n),t,e,r)},P.seq=function(){var t=arguments;return m(function(e){var r=this,u=e[e.length-1];"function"==typeof u?e.pop():u=n,P.reduce(t,e,function(n,t,e){t.apply(r,n.concat([m(function(n,t){e(n,t)})]))},function(n,t){u.apply(r,[n].concat(t))})})},P.compose=function(){return P.seq.apply(null,Array.prototype.reverse.call(arguments))},P.applyEach=T(P.eachOf),P.applyEachSeries=T(P.eachOfSeries),P.forever=function(t,e){function r(n){return n?i(n):void o(r)}var i=u(e||n),o=z(t);r()},P.ensureAsync=z,P.constant=m(function(n){var t=[null].concat(n);return function(n){return n.apply(this,t)}}),P.wrapSync=P.asyncify=function(n){return m(function(t){var e,r=t.pop();try{e=n.apply(this,t)}catch(u){return r(u)}U(e)&&"function"==typeof e.then?e.then(function(n){r(null,n)})["catch"](function(n){r(n.message?n:new Error(n))}):r(null,e)})},"object"==typeof module&&module.exports?module.exports=P:"function"==typeof define&&define.amd?define([],function(){return P}):C.async=P}(); +//# sourceMappingURL=dist/async.min.map
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/lib/async.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/lib/async.js new file mode 100644 index 0000000..31e7620 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/lib/async.js @@ -0,0 +1,1265 @@ +/*! + * async + * https://github.com/caolan/async + * + * Copyright 2010-2014 Caolan McMahon + * Released under the MIT license + */ +(function () { + + var async = {}; + function noop() {} + function identity(v) { + return v; + } + function toBool(v) { + return !!v; + } + function notId(v) { + return !v; + } + + // global on the server, window in the browser + var previous_async; + + // Establish the root object, `window` (`self`) in the browser, `global` + // on the server, or `this` in some virtual machines. We use `self` + // instead of `window` for `WebWorker` support. + var root = typeof self === 'object' && self.self === self && self || + typeof global === 'object' && global.global === global && global || + this; + + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + return function() { + if (fn === null) throw new Error("Callback was already called."); + fn.apply(this, arguments); + fn = null; + }; + } + + function _once(fn) { + return function() { + if (fn === null) return; + fn.apply(this, arguments); + fn = null; + }; + } + + //// cross-browser compatiblity functions //// + + var _toString = Object.prototype.toString; + + var _isArray = Array.isArray || function (obj) { + return _toString.call(obj) === '[object Array]'; + }; + + // Ported from underscore.js isObject + var _isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; + }; + + function _isArrayLike(arr) { + return _isArray(arr) || ( + // has a positive integer length property + typeof arr.length === "number" && + arr.length >= 0 && + arr.length % 1 === 0 + ); + } + + function _arrayEach(arr, iterator) { + var index = -1, + length = arr.length; + + while (++index < length) { + iterator(arr[index], index, arr); + } + } + + function _map(arr, iterator) { + var index = -1, + length = arr.length, + result = Array(length); + + while (++index < length) { + result[index] = iterator(arr[index], index, arr); + } + return result; + } + + function _range(count) { + return _map(Array(count), function (v, i) { return i; }); + } + + function _reduce(arr, iterator, memo) { + _arrayEach(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + } + + function _forEachOf(object, iterator) { + _arrayEach(_keys(object), function (key) { + iterator(object[key], key); + }); + } + + function _indexOf(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === item) return i; + } + return -1; + } + + var _keys = Object.keys || function (obj) { + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + function _keyIterator(coll) { + var i = -1; + var len; + var keys; + if (_isArrayLike(coll)) { + len = coll.length; + return function next() { + i++; + return i < len ? i : null; + }; + } else { + keys = _keys(coll); + len = keys.length; + return function next() { + i++; + return i < len ? keys[i] : null; + }; + } + } + + // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) + // This accumulates the arguments passed into an array, after a given index. + // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). + function _restParam(func, startIndex) { + startIndex = startIndex == null ? func.length - 1 : +startIndex; + return function() { + var length = Math.max(arguments.length - startIndex, 0); + var rest = Array(length); + for (var index = 0; index < length; index++) { + rest[index] = arguments[index + startIndex]; + } + switch (startIndex) { + case 0: return func.call(this, rest); + case 1: return func.call(this, arguments[0], rest); + } + // Currently unused but handle cases outside of the switch statement: + // var args = Array(startIndex + 1); + // for (index = 0; index < startIndex; index++) { + // args[index] = arguments[index]; + // } + // args[startIndex] = rest; + // return func.apply(this, args); + }; + } + + function _withoutIndex(iterator) { + return function (value, index, callback) { + return iterator(value, callback); + }; + } + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + + // capture the global reference to guard against fakeTimer mocks + var _setImmediate = typeof setImmediate === 'function' && setImmediate; + + var _delay = _setImmediate ? function(fn) { + // not a direct alias for IE10 compatibility + _setImmediate(fn); + } : function(fn) { + setTimeout(fn, 0); + }; + + if (typeof process === 'object' && typeof process.nextTick === 'function') { + async.nextTick = process.nextTick; + } else { + async.nextTick = _delay; + } + async.setImmediate = _setImmediate ? _delay : async.nextTick; + + + async.forEach = + async.each = function (arr, iterator, callback) { + return async.eachOf(arr, _withoutIndex(iterator), callback); + }; + + async.forEachSeries = + async.eachSeries = function (arr, iterator, callback) { + return async.eachOfSeries(arr, _withoutIndex(iterator), callback); + }; + + + async.forEachLimit = + async.eachLimit = function (arr, limit, iterator, callback) { + return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); + }; + + async.forEachOf = + async.eachOf = function (object, iterator, callback) { + callback = _once(callback || noop); + object = object || []; + + var iter = _keyIterator(object); + var key, completed = 0; + + while ((key = iter()) != null) { + completed += 1; + iterator(object[key], key, only_once(done)); + } + + if (completed === 0) callback(null); + + function done(err) { + completed--; + if (err) { + callback(err); + } + // Check key is null in case iterator isn't exhausted + // and done resolved synchronously. + else if (key === null && completed <= 0) { + callback(null); + } + } + }; + + async.forEachOfSeries = + async.eachOfSeries = function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + var key = nextKey(); + function iterate() { + var sync = true; + if (key === null) { + return callback(null); + } + iterator(obj[key], key, only_once(function (err) { + if (err) { + callback(err); + } + else { + key = nextKey(); + if (key === null) { + return callback(null); + } else { + if (sync) { + async.setImmediate(iterate); + } else { + iterate(); + } + } + } + })); + sync = false; + } + iterate(); + }; + + + + async.forEachOfLimit = + async.eachOfLimit = function (obj, limit, iterator, callback) { + _eachOfLimit(limit)(obj, iterator, callback); + }; + + function _eachOfLimit(limit) { + + return function (obj, iterator, callback) { + callback = _once(callback || noop); + obj = obj || []; + var nextKey = _keyIterator(obj); + if (limit <= 0) { + return callback(null); + } + var done = false; + var running = 0; + var errored = false; + + (function replenish () { + if (done && running <= 0) { + return callback(null); + } + + while (running < limit && !errored) { + var key = nextKey(); + if (key === null) { + done = true; + if (running <= 0) { + callback(null); + } + return; + } + running += 1; + iterator(obj[key], key, only_once(function (err) { + running -= 1; + if (err) { + callback(err); + errored = true; + } + else { + replenish(); + } + })); + } + })(); + }; + } + + + function doParallel(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOf, obj, iterator, callback); + }; + } + function doParallelLimit(fn) { + return function (obj, limit, iterator, callback) { + return fn(_eachOfLimit(limit), obj, iterator, callback); + }; + } + function doSeries(fn) { + return function (obj, iterator, callback) { + return fn(async.eachOfSeries, obj, iterator, callback); + }; + } + + function _asyncMap(eachfn, arr, iterator, callback) { + callback = _once(callback || noop); + arr = arr || []; + var results = _isArrayLike(arr) ? [] : {}; + eachfn(arr, function (value, index, callback) { + iterator(value, function (err, v) { + results[index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = doParallelLimit(_asyncMap); + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.inject = + async.foldl = + async.reduce = function (arr, memo, iterator, callback) { + async.eachOfSeries(arr, function (x, i, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + + async.foldr = + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, identity).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + + async.transform = function (arr, memo, iterator, callback) { + if (arguments.length === 3) { + callback = iterator; + iterator = memo; + memo = _isArray(arr) ? [] : {}; + } + + async.eachOf(arr, function(v, k, cb) { + iterator(memo, v, k, cb); + }, function(err) { + callback(err, memo); + }); + }; + + function _filter(eachfn, arr, iterator, callback) { + var results = []; + eachfn(arr, function (x, index, callback) { + iterator(x, function (v) { + if (v) { + results.push({index: index, value: x}); + } + callback(); + }); + }, function () { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + } + + async.select = + async.filter = doParallel(_filter); + + async.selectLimit = + async.filterLimit = doParallelLimit(_filter); + + async.selectSeries = + async.filterSeries = doSeries(_filter); + + function _reject(eachfn, arr, iterator, callback) { + _filter(eachfn, arr, function(value, cb) { + iterator(value, function(v) { + cb(!v); + }); + }, callback); + } + async.reject = doParallel(_reject); + async.rejectLimit = doParallelLimit(_reject); + async.rejectSeries = doSeries(_reject); + + function _createTester(eachfn, check, getResult) { + return function(arr, limit, iterator, cb) { + function done() { + if (cb) cb(getResult(false, void 0)); + } + function iteratee(x, _, callback) { + if (!cb) return callback(); + iterator(x, function (v) { + if (cb && check(v)) { + cb(getResult(true, x)); + cb = iterator = false; + } + callback(); + }); + } + if (arguments.length > 3) { + eachfn(arr, limit, iteratee, done); + } else { + cb = iterator; + iterator = limit; + eachfn(arr, iteratee, done); + } + }; + } + + async.any = + async.some = _createTester(async.eachOf, toBool, identity); + + async.someLimit = _createTester(async.eachOfLimit, toBool, identity); + + async.all = + async.every = _createTester(async.eachOf, notId, notId); + + async.everyLimit = _createTester(async.eachOfLimit, notId, notId); + + function _findGetResult(v, x) { + return x; + } + async.detect = _createTester(async.eachOf, identity, _findGetResult); + async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); + async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); + + 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 { + callback(null, _map(results.sort(comparator), function (x) { + return x.value; + })); + } + + }); + + function comparator(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + } + }; + + async.auto = function (tasks, concurrency, callback) { + if (typeof arguments[1] === 'function') { + // concurrency is optional, shift the args. + callback = concurrency; + concurrency = null; + } + callback = _once(callback || noop); + var keys = _keys(tasks); + var remainingTasks = keys.length; + if (!remainingTasks) { + return callback(null); + } + if (!concurrency) { + concurrency = remainingTasks; + } + + var results = {}; + var runningTasks = 0; + + var hasError = false; + + var listeners = []; + function addListener(fn) { + listeners.unshift(fn); + } + function removeListener(fn) { + var idx = _indexOf(listeners, fn); + if (idx >= 0) listeners.splice(idx, 1); + } + function taskComplete() { + remainingTasks--; + _arrayEach(listeners.slice(0), function (fn) { + fn(); + }); + } + + addListener(function () { + if (!remainingTasks) { + callback(null, results); + } + }); + + _arrayEach(keys, function (k) { + if (hasError) return; + var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; + var taskCallback = _restParam(function(err, args) { + runningTasks--; + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _forEachOf(results, function(val, rkey) { + safeResults[rkey] = val; + }); + safeResults[k] = args; + hasError = true; + + callback(err, safeResults); + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }); + var requires = task.slice(0, task.length - 1); + // prevent dead-locks + var len = requires.length; + var dep; + while (len--) { + if (!(dep = tasks[requires[len]])) { + throw new Error('Has nonexistent dependency in ' + requires.join(', ')); + } + if (_isArray(dep) && _indexOf(dep, k) >= 0) { + throw new Error('Has cyclic dependencies'); + } + } + function ready() { + return runningTasks < concurrency && _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + } + if (ready()) { + runningTasks++; + task[task.length - 1](taskCallback, results); + } + else { + addListener(listener); + } + function listener() { + if (ready()) { + runningTasks++; + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + } + }); + }; + + + + async.retry = function(times, task, callback) { + var DEFAULT_TIMES = 5; + var DEFAULT_INTERVAL = 0; + + var attempts = []; + + var opts = { + times: DEFAULT_TIMES, + interval: DEFAULT_INTERVAL + }; + + function parseTimes(acc, t){ + if(typeof t === 'number'){ + acc.times = parseInt(t, 10) || DEFAULT_TIMES; + } else if(typeof t === 'object'){ + acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; + acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; + } else { + throw new Error('Unsupported argument type for \'times\': ' + typeof t); + } + } + + var length = arguments.length; + if (length < 1 || length > 3) { + throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); + } else if (length <= 2 && typeof times === 'function') { + callback = task; + task = times; + } + if (typeof times !== 'function') { + parseTimes(opts, times); + } + opts.callback = callback; + opts.task = task; + + function wrappedTask(wrappedCallback, wrappedResults) { + function retryAttempt(task, finalAttempt) { + return function(seriesCallback) { + task(function(err, result){ + seriesCallback(!err || finalAttempt, {err: err, result: result}); + }, wrappedResults); + }; + } + + function retryInterval(interval){ + return function(seriesCallback){ + setTimeout(function(){ + seriesCallback(null); + }, interval); + }; + } + + while (opts.times) { + + var finalAttempt = !(opts.times-=1); + attempts.push(retryAttempt(opts.task, finalAttempt)); + if(!finalAttempt && opts.interval > 0){ + attempts.push(retryInterval(opts.interval)); + } + } + + async.series(attempts, function(done, data){ + data = data[data.length - 1]; + (wrappedCallback || opts.callback)(data.err, data.result); + }); + } + + // If a callback is passed, run this as a controll flow + return opts.callback ? wrappedTask() : wrappedTask; + }; + + async.waterfall = function (tasks, callback) { + callback = _once(callback || noop); + if (!_isArray(tasks)) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + function wrapIterator(iterator) { + return _restParam(function (err, args) { + if (err) { + callback.apply(null, [err].concat(args)); + } + else { + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + ensureAsync(iterator).apply(null, args); + } + }); + } + wrapIterator(async.iterator(tasks))(); + }; + + function _parallel(eachfn, tasks, callback) { + callback = callback || noop; + var results = _isArrayLike(tasks) ? [] : {}; + + eachfn(tasks, function (task, key, callback) { + task(_restParam(function (err, args) { + if (args.length <= 1) { + args = args[0]; + } + results[key] = args; + callback(err); + })); + }, function (err) { + callback(err, results); + }); + } + + async.parallel = function (tasks, callback) { + _parallel(async.eachOf, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel(_eachOfLimit(limit), tasks, callback); + }; + + async.series = function(tasks, callback) { + _parallel(async.eachOfSeries, tasks, callback); + }; + + async.iterator = function (tasks) { + function makeCallback(index) { + function fn() { + 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 = _restParam(function (fn, args) { + return _restParam(function (callArgs) { + return fn.apply( + null, args.concat(callArgs) + ); + }); + }); + + function _concat(eachfn, arr, fn, callback) { + var result = []; + eachfn(arr, function (x, index, cb) { + fn(x, function (err, y) { + result = result.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, result); + }); + } + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + callback = callback || noop; + if (test()) { + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else if (test.apply(this, args)) { + iterator(next); + } else { + callback.apply(null, [null].concat(args)); + } + }); + iterator(next); + } else { + callback(null); + } + }; + + async.doWhilst = function (iterator, test, callback) { + var calls = 0; + return async.whilst(function() { + return ++calls <= 1 || test.apply(this, arguments); + }, iterator, callback); + }; + + async.until = function (test, iterator, callback) { + return async.whilst(function() { + return !test.apply(this, arguments); + }, iterator, callback); + }; + + async.doUntil = function (iterator, test, callback) { + return async.doWhilst(iterator, function() { + return !test.apply(this, arguments); + }, callback); + }; + + async.during = function (test, iterator, callback) { + callback = callback || noop; + + var next = _restParam(function(err, args) { + if (err) { + callback(err); + } else { + args.push(check); + test.apply(this, args); + } + }); + + var check = function(err, truth) { + if (err) { + callback(err); + } else if (truth) { + iterator(next); + } else { + callback(null); + } + }; + + test(check); + }; + + async.doDuring = function (iterator, test, callback) { + var calls = 0; + async.during(function(next) { + if (calls++ < 1) { + next(null, true); + } else { + test.apply(this, arguments); + } + }, iterator, callback); + }; + + function _queue(worker, concurrency, payload) { + if (concurrency == null) { + concurrency = 1; + } + else if(concurrency === 0) { + throw new Error('Concurrency must not be zero'); + } + function _insert(q, data, pos, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0 && q.idle()) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + callback: callback || noop + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + }); + async.setImmediate(q.process); + } + function _next(q, tasks) { + return function(){ + workers -= 1; + + var removed = false; + var args = arguments; + _arrayEach(tasks, function (task) { + _arrayEach(workersList, function (worker, index) { + if (worker === task && !removed) { + workersList.splice(index, 1); + removed = true; + } + }); + + task.callback.apply(task, args); + }); + if (q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + } + + var workers = 0; + var workersList = []; + var q = { + tasks: [], + concurrency: concurrency, + payload: payload, + saturated: noop, + empty: noop, + drain: noop, + started: false, + paused: false, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + kill: function () { + q.drain = noop; + q.tasks = []; + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + while(!q.paused && workers < q.concurrency && q.tasks.length){ + + var tasks = q.payload ? + q.tasks.splice(0, q.payload) : + q.tasks.splice(0, q.tasks.length); + + var data = _map(tasks, function (task) { + return task.data; + }); + + if (q.tasks.length === 0) { + q.empty(); + } + workers += 1; + workersList.push(tasks[0]); + var cb = only_once(_next(q, tasks)); + worker(data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + }, + workersList: function () { + return workersList; + }, + idle: function() { + return q.tasks.length + workers === 0; + }, + pause: function () { + q.paused = true; + }, + resume: function () { + if (q.paused === false) { return; } + q.paused = false; + var resumeCount = Math.min(q.concurrency, q.tasks.length); + // Need to call q.process once per concurrent + // worker to preserve full concurrency after pause + for (var w = 1; w <= resumeCount; w++) { + async.setImmediate(q.process); + } + } + }; + return q; + } + + async.queue = function (worker, concurrency) { + var q = _queue(function (items, cb) { + worker(items[0], cb); + }, concurrency, 1); + + return q; + }; + + async.priorityQueue = function (worker, concurrency) { + + function _compareTasks(a, b){ + return a.priority - b.priority; + } + + function _binarySearch(sequence, item, compare) { + var beg = -1, + end = sequence.length - 1; + while (beg < end) { + var mid = beg + ((end - beg + 1) >>> 1); + if (compare(item, sequence[mid]) >= 0) { + beg = mid; + } else { + end = mid - 1; + } + } + return beg; + } + + function _insert(q, data, priority, callback) { + if (callback != null && typeof callback !== "function") { + throw new Error("task callback must be a function"); + } + q.started = true; + if (!_isArray(data)) { + data = [data]; + } + if(data.length === 0) { + // call drain immediately if there are no tasks + return async.setImmediate(function() { + q.drain(); + }); + } + _arrayEach(data, function(task) { + var item = { + data: task, + priority: priority, + callback: typeof callback === 'function' ? callback : noop + }; + + q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); + + if (q.tasks.length === q.concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + // Start with a normal queue + var q = async.queue(worker, concurrency); + + // Override push to accept second parameter representing priority + q.push = function (data, priority, callback) { + _insert(q, data, priority, callback); + }; + + // Remove unshift function + delete q.unshift; + + return q; + }; + + async.cargo = function (worker, payload) { + return _queue(worker, 1, payload); + }; + + function _console_fn(name) { + return _restParam(function (fn, args) { + fn.apply(null, args.concat([_restParam(function (err, args) { + if (typeof console === 'object') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _arrayEach(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 = {}; + var has = Object.prototype.hasOwnProperty; + hasher = hasher || identity; + var memoized = _restParam(function memoized(args) { + var callback = args.pop(); + var key = hasher.apply(null, args); + if (has.call(memo, key)) { + async.setImmediate(function () { + callback.apply(null, memo[key]); + }); + } + else if (has.call(queues, key)) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([_restParam(function (args) { + memo[key] = args; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, args); + } + })])); + } + }); + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + function _times(mapper) { + return function (count, iterator, callback) { + mapper(_range(count), iterator, callback); + }; + } + + async.times = _times(async.map); + async.timesSeries = _times(async.mapSeries); + async.timesLimit = function (count, limit, iterator, callback) { + return async.mapLimit(_range(count), limit, iterator, callback); + }; + + async.seq = function (/* functions... */) { + var fns = arguments; + return _restParam(function (args) { + var that = this; + + var callback = args[args.length - 1]; + if (typeof callback == 'function') { + args.pop(); + } else { + callback = noop; + } + + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { + cb(err, nextargs); + })])); + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }); + }; + + async.compose = function (/* functions... */) { + return async.seq.apply(null, Array.prototype.reverse.call(arguments)); + }; + + + function _applyEach(eachfn) { + return _restParam(function(fns, args) { + var go = _restParam(function(args) { + var that = this; + var callback = args.pop(); + return eachfn(fns, function (fn, _, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }); + if (args.length) { + return go.apply(this, args); + } + else { + return go; + } + }); + } + + async.applyEach = _applyEach(async.eachOf); + async.applyEachSeries = _applyEach(async.eachOfSeries); + + + async.forever = function (fn, callback) { + var done = only_once(callback || noop); + var task = ensureAsync(fn); + function next(err) { + if (err) { + return done(err); + } + task(next); + } + next(); + }; + + function ensureAsync(fn) { + return _restParam(function (args) { + var callback = args.pop(); + args.push(function () { + var innerArgs = arguments; + if (sync) { + async.setImmediate(function () { + callback.apply(null, innerArgs); + }); + } else { + callback.apply(null, innerArgs); + } + }); + var sync = true; + fn.apply(this, args); + sync = false; + }); + } + + async.ensureAsync = ensureAsync; + + async.constant = _restParam(function(values) { + var args = [null].concat(values); + return function (callback) { + return callback.apply(this, args); + }; + }); + + async.wrapSync = + async.asyncify = function asyncify(func) { + return _restParam(function (args) { + var callback = args.pop(); + var result; + try { + result = func.apply(this, args); + } catch (e) { + return callback(e); + } + // if result is Promise object + if (_isObject(result) && typeof result.then === "function") { + result.then(function(value) { + callback(null, value); + })["catch"](function(err) { + callback(err.message ? err : new Error(err)); + }); + } else { + callback(null, result); + } + }); + }; + + // Node.js + if (typeof module === 'object' && module.exports) { + module.exports = async; + } + // AMD / RequireJS + else if (typeof define === 'function' && define.amd) { + define([], function () { + return async; + }); + } + // included directly via <script> tag + else { + root.async = async; + } + +}()); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/package.json b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/package.json new file mode 100644 index 0000000..4bcdc92 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/async/package.json @@ -0,0 +1,123 @@ +{ + "name": "async", + "description": "Higher-order functions and common patterns for asynchronous code", + "main": "lib/async.js", + "files": [ + "lib", + "dist/async.js", + "dist/async.min.js" + ], + "author": { + "name": "Caolan McMahon" + }, + "version": "1.5.2", + "keywords": [ + "async", + "callback", + "utility", + "module" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/caolan/async.git" + }, + "bugs": { + "url": "https://github.com/caolan/async/issues" + }, + "license": "MIT", + "devDependencies": { + "benchmark": "github:bestiejs/benchmark.js", + "bluebird": "^2.9.32", + "chai": "^3.1.0", + "coveralls": "^2.11.2", + "es6-promise": "^2.3.0", + "jscs": "^1.13.1", + "jshint": "~2.8.0", + "karma": "^0.13.2", + "karma-browserify": "^4.2.1", + "karma-firefox-launcher": "^0.1.6", + "karma-mocha": "^0.2.0", + "karma-mocha-reporter": "^1.0.2", + "lodash": "^3.9.0", + "mkdirp": "~0.5.1", + "mocha": "^2.2.5", + "native-promise-only": "^0.8.0-a", + "nodeunit": ">0.0.0", + "nyc": "^2.1.0", + "rsvp": "^3.0.18", + "semver": "^4.3.6", + "uglify-js": "~2.4.0", + "xyz": "^0.5.0", + "yargs": "~3.9.1" + }, + "jam": { + "main": "lib/async.js", + "include": [ + "lib/async.js", + "README.md", + "LICENSE" + ], + "categories": [ + "Utilities" + ] + }, + "scripts": { + "mocha-node-test": "mocha mocha_test/", + "mocha-browser-test": "karma start", + "mocha-test": "npm run mocha-node-test && npm run mocha-browser-test", + "nodeunit-test": "nodeunit test/test-async.js", + "test": "npm run-script lint && npm run nodeunit-test && npm run mocha-test", + "lint": "jshint lib/*.js test/*.js perf/*.js && jscs lib/*.js test/*.js perf/*.js", + "coverage": "nyc npm test && nyc report", + "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls" + }, + "spm": { + "main": "lib/async.js" + }, + "volo": { + "main": "lib/async.js", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] + }, + "gitHead": "9ab5c67b7cb3a4c3dad4a2d4552a2f6775545d6c", + "homepage": "https://github.com/caolan/async#readme", + "_id": "async@1.5.2", + "_shasum": "ec6a61ae56480c0c3cb241c95618e20892f9672a", + "_from": "async@>=1.4.0 <2.0.0", + "_npmVersion": "3.5.2", + "_nodeVersion": "4.2.3", + "_npmUser": { + "name": "aearly", + "email": "alexander.early@gmail.com" + }, + "maintainers": [ + { + "name": "caolan", + "email": "caolan.mcmahon@gmail.com" + }, + { + "name": "beaugunderson", + "email": "beau@beaugunderson.com" + }, + { + "name": "aearly", + "email": "alexander.early@gmail.com" + }, + { + "name": "megawac", + "email": "megawac@gmail.com" + } + ], + "dist": { + "shasum": "ec6a61ae56480c0c3cb241c95618e20892f9672a", + "tarball": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/License b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited <felix@debuggable.com> + +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/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/Readme.md new file mode 100644 index 0000000..3a9e025 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/Readme.md @@ -0,0 +1,138 @@ +# combined-stream + +A stream that emits multiple other streams one after another. + +**NB** Currently `combined-stream` works with streams vesrion 1 only. There is ongoing effort to switch this library to streams version 2. Any help is welcome. :) Meanwhile you can explore other libraries that provide streams2 support with more or less compatability with `combined-stream`. + +- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module. + +- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another. + +## Installation + +``` bash +npm install combined-stream +``` + +## Usage + +Here is a simple example that shows how you can use combined-stream to combine +two files into one: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +While the example above works great, it will pause all source streams until +they are needed. If you don't want that to happen, you can set `pauseStreams` +to `false`: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create({pauseStreams: false}); +combinedStream.append(fs.createReadStream('file1.txt')); +combinedStream.append(fs.createReadStream('file2.txt')); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +However, what if you don't have all the source streams yet, or you don't want +to allocate the resources (file descriptors, memory, etc.) for them right away? +Well, in that case you can simply provide a callback that supplies the stream +by calling a `next()` function: + +``` javascript +var CombinedStream = require('combined-stream'); +var fs = require('fs'); + +var combinedStream = CombinedStream.create(); +combinedStream.append(function(next) { + next(fs.createReadStream('file1.txt')); +}); +combinedStream.append(function(next) { + next(fs.createReadStream('file2.txt')); +}); + +combinedStream.pipe(fs.createWriteStream('combined.txt')); +``` + +## API + +### CombinedStream.create([options]) + +Returns a new combined stream object. Available options are: + +* `maxDataSize` +* `pauseStreams` + +The effect of those options is described below. + +### combinedStream.pauseStreams = `true` + +Whether to apply back pressure to the underlaying streams. If set to `false`, +the underlaying streams will never be paused. If set to `true`, the +underlaying streams will be paused right after being appended, as well as when +`delayedStream.pipe()` wants to throttle. + +### combinedStream.maxDataSize = `2 * 1024 * 1024` + +The maximum amount of bytes (or characters) to buffer for all source streams. +If this value is exceeded, `combinedStream` emits an `'error'` event. + +### combinedStream.dataSize = `0` + +The amount of bytes (or characters) currently buffered by `combinedStream`. + +### combinedStream.append(stream) + +Appends the given `stream` to the combinedStream object. If `pauseStreams` is +set to `true, this stream will also be paused right away. + +`streams` can also be a function that takes one parameter called `next`. `next` +is a function that must be invoked in order to provide the `next` stream, see +example above. + +Regardless of how the `stream` is appended, combined-stream always attaches an +`'error'` listener to it, so you don't have to do that manually. + +Special case: `stream` can also be a String or Buffer. + +### combinedStream.write(data) + +You should not call this, `combinedStream` takes care of piping the appended +streams into itself for you. + +### combinedStream.resume() + +Causes `combinedStream` to start drain the streams it manages. The function is +idempotent, and also emits a `'resume'` event each time which usually goes to +the stream that is currently being drained. + +### combinedStream.pause(); + +If `combinedStream.pauseStreams` is set to `false`, this does nothing. +Otherwise a `'pause'` event is emitted, this goes to the stream that is +currently being drained, so you can use it to apply back pressure. + +### combinedStream.end(); + +Sets `combinedStream.writable` to false, emits an `'end'` event, and removes +all streams from the queue. + +### combinedStream.destroy(); + +Same as `combinedStream.end()`, except it emits a `'close'` event instead of +`'end'`. + +## License + +combined-stream is licensed under the MIT license. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js new file mode 100644 index 0000000..6b5c21b --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/lib/combined_stream.js @@ -0,0 +1,188 @@ +var util = require('util'); +var Stream = require('stream').Stream; +var DelayedStream = require('delayed-stream'); + +module.exports = CombinedStream; +function CombinedStream() { + this.writable = false; + this.readable = true; + this.dataSize = 0; + this.maxDataSize = 2 * 1024 * 1024; + this.pauseStreams = true; + + this._released = false; + this._streams = []; + this._currentStream = null; +} +util.inherits(CombinedStream, Stream); + +CombinedStream.create = function(options) { + var combinedStream = new this(); + + options = options || {}; + for (var option in options) { + combinedStream[option] = options[option]; + } + + return combinedStream; +}; + +CombinedStream.isStreamLike = function(stream) { + return (typeof stream !== 'function') + && (typeof stream !== 'string') + && (typeof stream !== 'boolean') + && (typeof stream !== 'number') + && (!Buffer.isBuffer(stream)); +}; + +CombinedStream.prototype.append = function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + + if (isStreamLike) { + if (!(stream instanceof DelayedStream)) { + var newStream = DelayedStream.create(stream, { + maxDataSize: Infinity, + pauseStream: this.pauseStreams, + }); + stream.on('data', this._checkDataSize.bind(this)); + stream = newStream; + } + + this._handleErrors(stream); + + if (this.pauseStreams) { + stream.pause(); + } + } + + this._streams.push(stream); + return this; +}; + +CombinedStream.prototype.pipe = function(dest, options) { + Stream.prototype.pipe.call(this, dest, options); + this.resume(); + return dest; +}; + +CombinedStream.prototype._getNext = function() { + this._currentStream = null; + var stream = this._streams.shift(); + + + if (typeof stream == 'undefined') { + this.end(); + return; + } + + if (typeof stream !== 'function') { + this._pipeNext(stream); + return; + } + + var getStream = stream; + getStream(function(stream) { + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('data', this._checkDataSize.bind(this)); + this._handleErrors(stream); + } + + this._pipeNext(stream); + }.bind(this)); +}; + +CombinedStream.prototype._pipeNext = function(stream) { + this._currentStream = stream; + + var isStreamLike = CombinedStream.isStreamLike(stream); + if (isStreamLike) { + stream.on('end', this._getNext.bind(this)); + stream.pipe(this, {end: false}); + return; + } + + var value = stream; + this.write(value); + this._getNext(); +}; + +CombinedStream.prototype._handleErrors = function(stream) { + var self = this; + stream.on('error', function(err) { + self._emitError(err); + }); +}; + +CombinedStream.prototype.write = function(data) { + this.emit('data', data); +}; + +CombinedStream.prototype.pause = function() { + if (!this.pauseStreams) { + return; + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause(); + this.emit('pause'); +}; + +CombinedStream.prototype.resume = function() { + if (!this._released) { + this._released = true; + this.writable = true; + this._getNext(); + } + + if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume(); + this.emit('resume'); +}; + +CombinedStream.prototype.end = function() { + this._reset(); + this.emit('end'); +}; + +CombinedStream.prototype.destroy = function() { + this._reset(); + this.emit('close'); +}; + +CombinedStream.prototype._reset = function() { + this.writable = false; + this._streams = []; + this._currentStream = null; +}; + +CombinedStream.prototype._checkDataSize = function() { + this._updateDataSize(); + if (this.dataSize <= this.maxDataSize) { + return; + } + + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.'; + this._emitError(new Error(message)); +}; + +CombinedStream.prototype._updateDataSize = function() { + this.dataSize = 0; + + var self = this; + this._streams.forEach(function(stream) { + if (!stream.dataSize) { + return; + } + + self.dataSize += stream.dataSize; + }); + + if (this._currentStream && this._currentStream.dataSize) { + this.dataSize += this._currentStream.dataSize; + } +}; + +CombinedStream.prototype._emitError = function(err) { + this._reset(); + this.emit('error', err); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/.npmignore @@ -0,0 +1 @@ +test diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License new file mode 100644 index 0000000..4804b7a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/License @@ -0,0 +1,19 @@ +Copyright (c) 2011 Debuggable Limited <felix@debuggable.com> + +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/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile new file mode 100644 index 0000000..b4ff85a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Makefile @@ -0,0 +1,7 @@ +SHELL := /bin/bash + +test: + @./test/run.js + +.PHONY: test + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md new file mode 100644 index 0000000..aca36f9 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/Readme.md @@ -0,0 +1,141 @@ +# delayed-stream + +Buffers events from a stream until you are ready to handle them. + +## Installation + +``` bash +npm install delayed-stream +``` + +## Usage + +The following example shows how to write a http echo server that delays its +response by 1000 ms. + +``` javascript +var DelayedStream = require('delayed-stream'); +var http = require('http'); + +http.createServer(function(req, res) { + var delayed = DelayedStream.create(req); + + setTimeout(function() { + res.writeHead(200); + delayed.pipe(res); + }, 1000); +}); +``` + +If you are not using `Stream#pipe`, you can also manually release the buffered +events by calling `delayedStream.resume()`: + +``` javascript +var delayed = DelayedStream.create(req); + +setTimeout(function() { + // Emit all buffered events and resume underlaying source + delayed.resume(); +}, 1000); +``` + +## Implementation + +In order to use this meta stream properly, here are a few things you should +know about the implementation. + +### Event Buffering / Proxying + +All events of the `source` stream are hijacked by overwriting the `source.emit` +method. Until node implements a catch-all event listener, this is the only way. + +However, delayed-stream still continues to emit all events it captures on the +`source`, regardless of whether you have released the delayed stream yet or +not. + +Upon creation, delayed-stream captures all `source` events and stores them in +an internal event buffer. Once `delayedStream.release()` is called, all +buffered events are emitted on the `delayedStream`, and the event buffer is +cleared. After that, delayed-stream merely acts as a proxy for the underlaying +source. + +### Error handling + +Error events on `source` are buffered / proxied just like any other events. +However, `delayedStream.create` attaches a no-op `'error'` listener to the +`source`. This way you only have to handle errors on the `delayedStream` +object, rather than in two places. + +### Buffer limits + +delayed-stream provides a `maxDataSize` property that can be used to limit +the amount of data being buffered. In order to protect you from bad `source` +streams that don't react to `source.pause()`, this feature is enabled by +default. + +## API + +### DelayedStream.create(source, [options]) + +Returns a new `delayedStream`. Available options are: + +* `pauseStream` +* `maxDataSize` + +The description for those properties can be found below. + +### delayedStream.source + +The `source` stream managed by this object. This is useful if you are +passing your `delayedStream` around, and you still want to access properties +on the `source` object. + +### delayedStream.pauseStream = true + +Whether to pause the underlaying `source` when calling +`DelayedStream.create()`. Modifying this property afterwards has no effect. + +### delayedStream.maxDataSize = 1024 * 1024 + +The amount of data to buffer before emitting an `error`. + +If the underlaying source is emitting `Buffer` objects, the `maxDataSize` +refers to bytes. + +If the underlaying source is emitting JavaScript strings, the size refers to +characters. + +If you know what you are doing, you can set this property to `Infinity` to +disable this feature. You can also modify this property during runtime. + +### delayedStream.dataSize = 0 + +The amount of data buffered so far. + +### delayedStream.readable + +An ECMA5 getter that returns the value of `source.readable`. + +### delayedStream.resume() + +If the `delayedStream` has not been released so far, `delayedStream.release()` +is called. + +In either case, `source.resume()` is called. + +### delayedStream.pause() + +Calls `source.pause()`. + +### delayedStream.pipe(dest) + +Calls `delayedStream.resume()` and then proxies the arguments to `source.pipe`. + +### delayedStream.release() + +Emits and clears all events that have been buffered up so far. This does not +resume the underlaying source, use `delayedStream.resume()` instead. + +## License + +delayed-stream is licensed under the MIT license. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js new file mode 100644 index 0000000..b38fc85 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/lib/delayed_stream.js @@ -0,0 +1,107 @@ +var Stream = require('stream').Stream; +var util = require('util'); + +module.exports = DelayedStream; +function DelayedStream() { + this.source = null; + this.dataSize = 0; + this.maxDataSize = 1024 * 1024; + this.pauseStream = true; + + this._maxDataSizeExceeded = false; + this._released = false; + this._bufferedEvents = []; +} +util.inherits(DelayedStream, Stream); + +DelayedStream.create = function(source, options) { + var delayedStream = new this(); + + options = options || {}; + for (var option in options) { + delayedStream[option] = options[option]; + } + + delayedStream.source = source; + + var realEmit = source.emit; + source.emit = function() { + delayedStream._handleEmit(arguments); + return realEmit.apply(source, arguments); + }; + + source.on('error', function() {}); + if (delayedStream.pauseStream) { + source.pause(); + } + + return delayedStream; +}; + +Object.defineProperty(DelayedStream.prototype, 'readable', { + configurable: true, + enumerable: true, + get: function() { + return this.source.readable; + } +}); + +DelayedStream.prototype.setEncoding = function() { + return this.source.setEncoding.apply(this.source, arguments); +}; + +DelayedStream.prototype.resume = function() { + if (!this._released) { + this.release(); + } + + this.source.resume(); +}; + +DelayedStream.prototype.pause = function() { + this.source.pause(); +}; + +DelayedStream.prototype.release = function() { + this._released = true; + + this._bufferedEvents.forEach(function(args) { + this.emit.apply(this, args); + }.bind(this)); + this._bufferedEvents = []; +}; + +DelayedStream.prototype.pipe = function() { + var r = Stream.prototype.pipe.apply(this, arguments); + this.resume(); + return r; +}; + +DelayedStream.prototype._handleEmit = function(args) { + if (this._released) { + this.emit.apply(this, args); + return; + } + + if (args[0] === 'data') { + this.dataSize += args[1].length; + this._checkIfMaxDataSizeExceeded(); + } + + this._bufferedEvents.push(args); +}; + +DelayedStream.prototype._checkIfMaxDataSizeExceeded = function() { + if (this._maxDataSizeExceeded) { + return; + } + + if (this.dataSize <= this.maxDataSize) { + return; + } + + this._maxDataSizeExceeded = true; + var message = + 'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.' + this.emit('error', new Error(message)); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json new file mode 100644 index 0000000..a471728 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream/package.json @@ -0,0 +1,64 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "contributors": [ + { + "name": "Mike Atkins", + "email": "apeherder@gmail.com" + } + ], + "name": "delayed-stream", + "description": "Buffers events from a stream until you are ready to handle them.", + "license": "MIT", + "version": "1.0.0", + "homepage": "https://github.com/felixge/node-delayed-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-delayed-stream.git" + }, + "main": "./lib/delayed_stream", + "engines": { + "node": ">=0.4.0" + }, + "scripts": { + "test": "make test" + }, + "dependencies": {}, + "devDependencies": { + "fake": "0.2.0", + "far": "0.0.1" + }, + "gitHead": "07a9dc99fb8f1a488160026b9ad77493f766fb84", + "bugs": { + "url": "https://github.com/felixge/node-delayed-stream/issues" + }, + "_id": "delayed-stream@1.0.0", + "_shasum": "df3ae199acadfb7d440aaae0b29e2272b24ec619", + "_from": "delayed-stream@>=1.0.0 <1.1.0", + "_npmVersion": "2.8.3", + "_nodeVersion": "1.6.4", + "_npmUser": { + "name": "apechimp", + "email": "apeherder@gmail.com" + }, + "dist": { + "shasum": "df3ae199acadfb7d440aaae0b29e2272b24ec619", + "tarball": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + }, + "maintainers": [ + { + "name": "felixge", + "email": "felix@debuggable.com" + }, + { + "name": "apechimp", + "email": "apeherder@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/package.json b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/package.json new file mode 100644 index 0000000..d3f8032 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/node_modules/combined-stream/package.json @@ -0,0 +1,67 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "combined-stream", + "description": "A stream that emits multiple other streams one after another.", + "version": "1.0.5", + "homepage": "https://github.com/felixge/node-combined-stream", + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-combined-stream.git" + }, + "main": "./lib/combined_stream", + "scripts": { + "test": "node test/run.js" + }, + "engines": { + "node": ">= 0.8" + }, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "devDependencies": { + "far": "~0.0.7" + }, + "license": "MIT", + "gitHead": "cfc7b815d090a109bcedb5bb0f6713148d55a6b7", + "bugs": { + "url": "https://github.com/felixge/node-combined-stream/issues" + }, + "_id": "combined-stream@1.0.5", + "_shasum": "938370a57b4a51dea2c77c15d5c5fdf895164009", + "_from": "combined-stream@>=1.0.5 <2.0.0", + "_npmVersion": "2.10.1", + "_nodeVersion": "0.12.4", + "_npmUser": { + "name": "alexindigo", + "email": "iam@alexindigo.com" + }, + "dist": { + "shasum": "938370a57b4a51dea2c77c15d5c5fdf895164009", + "tarball": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + }, + "maintainers": [ + { + "name": "felixge", + "email": "felix@debuggable.com" + }, + { + "name": "celer", + "email": "dtyree77@gmail.com" + }, + { + "name": "alexindigo", + "email": "iam@alexindigo.com" + }, + { + "name": "apechimp", + "email": "apeherder@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/form-data/package.json b/node_modules/supertest/node_modules/superagent/node_modules/form-data/package.json new file mode 100644 index 0000000..6bfb06f --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/form-data/package.json @@ -0,0 +1,84 @@ +{ + "author": { + "name": "Felix Geisendörfer", + "email": "felix@debuggable.com", + "url": "http://debuggable.com/" + }, + "name": "form-data", + "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", + "version": "1.0.0-rc3", + "repository": { + "type": "git", + "url": "git://github.com/form-data/form-data.git" + }, + "main": "./lib/form_data", + "browser": "./lib/browser", + "scripts": { + "test": "./test/run.js" + }, + "pre-commit": [ + "test" + ], + "engines": { + "node": ">= 0.10" + }, + "dependencies": { + "async": "^1.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.3" + }, + "license": "MIT", + "devDependencies": { + "fake": "^0.2.2", + "far": "^0.0.7", + "formidable": "^1.0.17", + "pre-commit": "^1.0.10", + "request": "^2.60.0" + }, + "gitHead": "c174f1b7f3a78a00ec5af0360469280445e37804", + "bugs": { + "url": "https://github.com/form-data/form-data/issues" + }, + "homepage": "https://github.com/form-data/form-data#readme", + "_id": "form-data@1.0.0-rc3", + "_shasum": "d35bc62e7fbc2937ae78f948aaa0d38d90607577", + "_from": "form-data@1.0.0-rc3", + "_npmVersion": "2.11.0", + "_nodeVersion": "2.2.1", + "_npmUser": { + "name": "dylanpiercey", + "email": "pierceydylan@gmail.com" + }, + "dist": { + "shasum": "d35bc62e7fbc2937ae78f948aaa0d38d90607577", + "tarball": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz" + }, + "maintainers": [ + { + "name": "felixge", + "email": "felix@debuggable.com" + }, + { + "name": "idralyuk", + "email": "igor@buran.us" + }, + { + "name": "alexindigo", + "email": "iam@alexindigo.com" + }, + { + "name": "mikeal", + "email": "mikeal.rogers@gmail.com" + }, + { + "name": "celer", + "email": "dtyree77@gmail.com" + }, + { + "name": "dylanpiercey", + "email": "pierceydylan@gmail.com" + } + ], + "directories": {}, + "_resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/formidable/.npmignore new file mode 100644 index 0000000..ed16858 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/.npmignore @@ -0,0 +1,7 @@ +/test +/tool +/example +/benchmark +*.upload +*.un~ +*.http diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/.travis.yml b/node_modules/supertest/node_modules/superagent/node_modules/formidable/.travis.yml new file mode 100644 index 0000000..e20bedc --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 0.8 + - "0.10" + - 0.11 diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/formidable/LICENSE new file mode 100644 index 0000000..38d3c9c --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/LICENSE @@ -0,0 +1,7 @@ +Copyright (C) 2011 Felix Geisendörfer + +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/supertest/node_modules/superagent/node_modules/formidable/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/formidable/Readme.md new file mode 100644 index 0000000..e103c3d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/Readme.md @@ -0,0 +1,425 @@ +# Formidable + +[](http://travis-ci.org/felixge/node-formidable) + +## Purpose + +A node.js module for parsing form data, especially file uploads. + +## Current status + +This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading +and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from +a large variety of clients and is considered production-ready. + +## Features + +* Fast (~500mb/sec), non-buffering multipart parser +* Automatically writing file uploads to disk +* Low memory footprint +* Graceful error handling +* Very high test coverage + +## Installation + +This is a low level package, and if you're using a high level framework such as Express, chances are it's already included in it. You can [read this discussion](http://stackoverflow.com/questions/11295554/how-to-disable-express-bodyparser-for-file-uploads-node-js) about how Formidable is integrated with Express. + +Via [npm](http://github.com/isaacs/npm): +``` +npm install formidable@latest +``` +Manually: +``` +git clone git://github.com/felixge/node-formidable.git formidable +vim my.js +# var formidable = require('./formidable'); +``` + +Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library. + +## Example + +Parse an incoming file upload. +```javascript +var formidable = require('formidable'), + http = require('http'), + util = require('util'); + +http.createServer(function(req, res) { + if (req.url == '/upload' && req.method.toLowerCase() == 'post') { + // parse a file upload + var form = new formidable.IncomingForm(); + + form.parse(req, function(err, fields, files) { + res.writeHead(200, {'content-type': 'text/plain'}); + res.write('received upload:\n\n'); + res.end(util.inspect({fields: fields, files: files})); + }); + + return; + } + + // show a file upload form + res.writeHead(200, {'content-type': 'text/html'}); + res.end( + '<form action="/upload" enctype="multipart/form-data" method="post">'+ + '<input type="text" name="title"><br>'+ + '<input type="file" name="upload" multiple="multiple"><br>'+ + '<input type="submit" value="Upload">'+ + '</form>' + ); +}).listen(8080); +``` +## API + +### Formidable.IncomingForm +```javascript +var form = new formidable.IncomingForm() +``` +Creates a new incoming form. + +```javascript +form.encoding = 'utf-8'; +``` +Sets encoding for incoming form fields. + +```javascript +form.uploadDir = "/my/dir"; +``` +Sets the directory for placing file uploads in. You can move them later on using +`fs.rename()`. The default is `os.tmpDir()`. + +```javascript +form.keepExtensions = false; +``` +If you want the files written to `form.uploadDir` to include the extensions of the original files, set this property to `true`. + +```javascript +form.type +``` +Either 'multipart' or 'urlencoded' depending on the incoming request. + +```javascript +form.maxFieldsSize = 2 * 1024 * 1024; +``` +Limits the amount of memory all fields together (except files) can allocate in bytes. +If this value is exceeded, an `'error'` event is emitted. The default +size is 2MB. + +```javascript +form.maxFields = 1000; +``` +Limits the number of fields that the querystring parser will decode. Defaults +to 1000 (0 for unlimited). + +```javascript +form.hash = false; +``` +If you want checksums calculated for incoming files, set this to either `'sha1'` or `'md5'`. + +```javascript +form.multiples = false; +``` +If this option is enabled, when you call `form.parse`, the `files` argument will contain arrays of files for inputs which submit multiple files using the HTML5 `multiple` attribute. + +```javascript +form.bytesReceived +``` +The amount of bytes received for this form so far. + +```javascript +form.bytesExpected +``` +The expected number of bytes in this form. + +```javascript +form.parse(request, [cb]); +``` +Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields and files are collected and passed to the callback: + + +```javascript +form.parse(req, function(err, fields, files) { + // ... +}); + +form.onPart(part); +``` +You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing. + +```javascript +form.onPart = function(part) { + part.addListener('data', function() { + // ... + }); +} +``` +If you want to use formidable to only handle certain parts for you, you can do so: +```javascript +form.onPart = function(part) { + if (!part.filename) { + // let formidable handle all non-file parts + form.handlePart(part); + } +} +``` +Check the code in this method for further inspiration. + + +### Formidable.File +```javascript +file.size = 0 +``` +The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet. +```javascript +file.path = null +``` +The path this file is being written to. You can modify this in the `'fileBegin'` event in +case you are unhappy with the way formidable generates a temporary path for your files. +```javascript +file.name = null +``` +The name this file had according to the uploading client. +```javascript +file.type = null +``` +The mime type of this file, according to the uploading client. +```javascript +file.lastModifiedDate = null +``` +A date object (or `null`) containing the time this file was last written to. Mostly +here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). +```javascript +file.hash = null +``` +If hash calculation was set, you can read the hex digest out of this var. + +#### Formidable.File#toJSON() + + This method returns a JSON-representation of the file, allowing you to + `JSON.stringify()` the file which is useful for logging and responding + to requests. + +### Events + + +#### 'progress' +```javascript +form.on('progress', function(bytesReceived, bytesExpected) { +}); +``` +Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar. + + + +#### 'field' +```javascript +form.on('field', function(name, value) { +}); +``` + +#### 'fileBegin' + +Emitted whenever a field / value pair has been received. +```javascript +form.on('fileBegin', function(name, file) { +}); +``` + +#### 'file' + +Emitted whenever a new file is detected in the upload stream. Use this even if +you want to stream the file to somewhere else while buffering the upload on +the file system. + +Emitted whenever a field / file pair has been received. `file` is an instance of `File`. +```javascript +form.on('file', function(name, file) { +}); +``` + +#### 'error' + +Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events. +```javascript +form.on('error', function(err) { +}); +``` + +#### 'aborted' + + +Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. After this event is emitted, an `error` event will follow. In the future there will be a separate 'timeout' event (needs a change in the node core). +```javascript +form.on('aborted', function() { +}); +``` + +##### 'end' +```javascript +form.on('end', function() { +}); +``` +Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response. + + + +## Changelog + +### v1.0.14 + +* Add failing hash tests. (Ben Trask) +* Enable hash calculation again (Eugene Girshov) +* Test for immediate data events (Tim Smart) +* Re-arrange IncomingForm#parse (Tim Smart) + +### v1.0.13 + +* Only update hash if update method exists (Sven Lito) +* According to travis v0.10 needs to go quoted (Sven Lito) +* Bumping build node versions (Sven Lito) +* Additional fix for empty requests (Eugene Girshov) +* Change the default to 1000, to match the new Node behaviour. (OrangeDog) +* Add ability to control maxKeys in the querystring parser. (OrangeDog) +* Adjust test case to work with node 0.9.x (Eugene Girshov) +* Update package.json (Sven Lito) +* Path adjustment according to eb4468b (Markus Ast) + +### v1.0.12 + +* Emit error on aborted connections (Eugene Girshov) +* Add support for empty requests (Eugene Girshov) +* Fix name/filename handling in Content-Disposition (jesperp) +* Tolerate malformed closing boundary in multipart (Eugene Girshov) +* Ignore preamble in multipart messages (Eugene Girshov) +* Add support for application/json (Mike Frey, Carlos Rodriguez) +* Add support for Base64 encoding (Elmer Bulthuis) +* Add File#toJSON (TJ Holowaychuk) +* Remove support for Node.js 0.4 & 0.6 (Andrew Kelley) +* Documentation improvements (Sven Lito, Andre Azevedo) +* Add support for application/octet-stream (Ion Lupascu, Chris Scribner) +* Use os.tmpDir() to get tmp directory (Andrew Kelley) +* Improve package.json (Andrew Kelley, Sven Lito) +* Fix benchmark script (Andrew Kelley) +* Fix scope issue in incoming_forms (Sven Lito) +* Fix file handle leak on error (OrangeDog) + +### v1.0.11 + +* Calculate checksums for incoming files (sreuter) +* Add definition parameters to "IncomingForm" as an argument (Math-) + +### v1.0.10 + +* Make parts to be proper Streams (Matt Robenolt) + +### v1.0.9 + +* Emit progress when content length header parsed (Tim Koschützki) +* Fix Readme syntax due to GitHub changes (goob) +* Replace references to old 'sys' module in Readme with 'util' (Peter Sugihara) + +### v1.0.8 + +* Strip potentially unsafe characters when using `keepExtensions: true`. +* Switch to utest / urun for testing +* Add travis build + +### v1.0.7 + +* Remove file from package that was causing problems when installing on windows. (#102) +* Fix typos in Readme (Jason Davies). + +### v1.0.6 + +* Do not default to the default to the field name for file uploads where + filename="". + +### v1.0.5 + +* Support filename="" in multipart parts +* Explain unexpected end() errors in parser better + +**Note:** Starting with this version, formidable emits 'file' events for empty +file input fields. Previously those were incorrectly emitted as regular file +input fields with value = "". + +### v1.0.4 + +* Detect a good default tmp directory regardless of platform. (#88) + +### v1.0.3 + +* Fix problems with utf8 characters (#84) / semicolons in filenames (#58) +* Small performance improvements +* New test suite and fixture system + +### v1.0.2 + +* Exclude node\_modules folder from git +* Implement new `'aborted'` event +* Fix files in example folder to work with recent node versions +* Make gently a devDependency + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2) + +### v1.0.1 + +* Fix package.json to refer to proper main directory. (#68, Dean Landolt) + +[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1) + +### v1.0.0 + +* Add support for multipart boundaries that are quoted strings. (Jeff Craig) + +This marks the beginning of development on version 2.0 which will include +several architectural improvements. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0) + +### v0.9.11 + +* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki) +* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class + +**Important:** The old property names of the File class will be removed in a +future release. + +[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11) + +### Older releases + +These releases were done before starting to maintain the above Changelog: + +* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10) +* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9) +* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8) +* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7) +* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6) +* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5) +* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4) +* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3) +* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2) +* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0) +* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0) + +## License + +Formidable is licensed under the MIT license. + +## Ports + +* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable + +## Credits + +* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/index.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/index.js new file mode 100644 index 0000000..4cc88b3 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/index.js @@ -0,0 +1 @@ +module.exports = require('./lib');
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/file.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/file.js new file mode 100644 index 0000000..e34c10e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/file.js @@ -0,0 +1,72 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var util = require('util'), + WriteStream = require('fs').WriteStream, + EventEmitter = require('events').EventEmitter, + crypto = require('crypto'); + +function File(properties) { + EventEmitter.call(this); + + this.size = 0; + this.path = null; + this.name = null; + this.type = null; + this.hash = null; + this.lastModifiedDate = null; + + this._writeStream = null; + + for (var key in properties) { + this[key] = properties[key]; + } + + if(typeof this.hash === 'string') { + this.hash = crypto.createHash(properties.hash); + } else { + this.hash = null; + } +} +module.exports = File; +util.inherits(File, EventEmitter); + +File.prototype.open = function() { + this._writeStream = new WriteStream(this.path); +}; + +File.prototype.toJSON = function() { + return { + size: this.size, + path: this.path, + name: this.name, + type: this.type, + mtime: this.lastModifiedDate, + length: this.length, + filename: this.filename, + mime: this.mime + }; +}; + +File.prototype.write = function(buffer, cb) { + var self = this; + if (self.hash) { + self.hash.update(buffer); + } + this._writeStream.write(buffer, function() { + self.lastModifiedDate = new Date(); + self.size += buffer.length; + self.emit('progress', self.size); + cb(); + }); +}; + +File.prototype.end = function(cb) { + var self = this; + if (self.hash) { + self.hash = self.hash.digest('hex'); + } + this._writeStream.end(function() { + self.emit('end'); + cb(); + }); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/incoming_form.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/incoming_form.js new file mode 100644 index 0000000..b423445 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/incoming_form.js @@ -0,0 +1,555 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var crypto = require('crypto'); +var fs = require('fs'); +var util = require('util'), + path = require('path'), + File = require('./file'), + MultipartParser = require('./multipart_parser').MultipartParser, + QuerystringParser = require('./querystring_parser').QuerystringParser, + OctetParser = require('./octet_parser').OctetParser, + JSONParser = require('./json_parser').JSONParser, + StringDecoder = require('string_decoder').StringDecoder, + EventEmitter = require('events').EventEmitter, + Stream = require('stream').Stream, + os = require('os'); + +function IncomingForm(opts) { + if (!(this instanceof IncomingForm)) return new IncomingForm(opts); + EventEmitter.call(this); + + opts=opts||{}; + + this.error = null; + this.ended = false; + + this.maxFields = opts.maxFields || 1000; + this.maxFieldsSize = opts.maxFieldsSize || 2 * 1024 * 1024; + this.keepExtensions = opts.keepExtensions || false; + this.uploadDir = opts.uploadDir || os.tmpDir(); + this.encoding = opts.encoding || 'utf-8'; + this.headers = null; + this.type = null; + this.hash = opts.hash || false; + this.multiples = opts.multiples || false; + + this.bytesReceived = null; + this.bytesExpected = null; + + this._parser = null; + this._flushing = 0; + this._fieldsSize = 0; + this.openedFiles = []; + + return this; +} +util.inherits(IncomingForm, EventEmitter); +exports.IncomingForm = IncomingForm; + +IncomingForm.prototype.parse = function(req, cb) { + this.pause = function() { + try { + req.pause(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + return true; + }; + + this.resume = function() { + try { + req.resume(); + } catch (err) { + // the stream was destroyed + if (!this.ended) { + // before it was completed, crash & burn + this._error(err); + } + return false; + } + + return true; + }; + + // Setup callback first, so we don't miss anything from data events emitted + // immediately. + if (cb) { + var fields = {}, files = {}; + this + .on('field', function(name, value) { + fields[name] = value; + }) + .on('file', function(name, file) { + if (this.multiples) { + if (files[name]) { + if (!Array.isArray(files[name])) { + files[name] = [files[name]]; + } + files[name].push(file); + } else { + files[name] = file; + } + } else { + files[name] = file; + } + }) + .on('error', function(err) { + cb(err, fields, files); + }) + .on('end', function() { + cb(null, fields, files); + }); + } + + // Parse headers and setup the parser, ready to start listening for data. + this.writeHeaders(req.headers); + + // Start listening for data. + var self = this; + req + .on('error', function(err) { + self._error(err); + }) + .on('aborted', function() { + self.emit('aborted'); + self._error(new Error('Request aborted')); + }) + .on('data', function(buffer) { + self.write(buffer); + }) + .on('end', function() { + if (self.error) { + return; + } + + var err = self._parser.end(); + if (err) { + self._error(err); + } + }); + + return this; +}; + +IncomingForm.prototype.writeHeaders = function(headers) { + this.headers = headers; + this._parseContentLength(); + this._parseContentType(); +}; + +IncomingForm.prototype.write = function(buffer) { + if (this.error) { + return; + } + if (!this._parser) { + this._error(new Error('uninitialized parser')); + return; + } + + this.bytesReceived += buffer.length; + this.emit('progress', this.bytesReceived, this.bytesExpected); + + var bytesParsed = this._parser.write(buffer); + if (bytesParsed !== buffer.length) { + this._error(new Error('parser error, '+bytesParsed+' of '+buffer.length+' bytes parsed')); + } + + return bytesParsed; +}; + +IncomingForm.prototype.pause = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.resume = function() { + // this does nothing, unless overwritten in IncomingForm.parse + return false; +}; + +IncomingForm.prototype.onPart = function(part) { + // this method can be overwritten by the user + this.handlePart(part); +}; + +IncomingForm.prototype.handlePart = function(part) { + var self = this; + + if (part.filename === undefined) { + var value = '' + , decoder = new StringDecoder(this.encoding); + + part.on('data', function(buffer) { + self._fieldsSize += buffer.length; + if (self._fieldsSize > self.maxFieldsSize) { + self._error(new Error('maxFieldsSize exceeded, received '+self._fieldsSize+' bytes of field data')); + return; + } + value += decoder.write(buffer); + }); + + part.on('end', function() { + self.emit('field', part.name, value); + }); + return; + } + + this._flushing++; + + var file = new File({ + path: this._uploadPath(part.filename), + name: part.filename, + type: part.mime, + hash: self.hash + }); + + this.emit('fileBegin', part.name, file); + + file.open(); + this.openedFiles.push(file); + + part.on('data', function(buffer) { + if (buffer.length == 0) { + return; + } + self.pause(); + file.write(buffer, function() { + self.resume(); + }); + }); + + part.on('end', function() { + file.end(function() { + self._flushing--; + self.emit('file', part.name, file); + self._maybeEnd(); + }); + }); +}; + +function dummyParser(self) { + return { + end: function () { + self.ended = true; + self._maybeEnd(); + return null; + } + }; +} + +IncomingForm.prototype._parseContentType = function() { + if (this.bytesExpected === 0) { + this._parser = dummyParser(this); + return; + } + + if (!this.headers['content-type']) { + this._error(new Error('bad content-type header, no content-type')); + return; + } + + if (this.headers['content-type'].match(/octet-stream/i)) { + this._initOctetStream(); + return; + } + + if (this.headers['content-type'].match(/urlencoded/i)) { + this._initUrlencoded(); + return; + } + + if (this.headers['content-type'].match(/multipart/i)) { + var m = this.headers['content-type'].match(/boundary=(?:"([^"]+)"|([^;]+))/i); + if (m) { + this._initMultipart(m[1] || m[2]); + } else { + this._error(new Error('bad content-type header, no multipart boundary')); + } + return; + } + + if (this.headers['content-type'].match(/json/i)) { + this._initJSONencoded(); + return; + } + + this._error(new Error('bad content-type header, unknown content-type: '+this.headers['content-type'])); +}; + +IncomingForm.prototype._error = function(err) { + if (this.error || this.ended) { + return; + } + + this.error = err; + this.emit('error', err); + + if (Array.isArray(this.openedFiles)) { + this.openedFiles.forEach(function(file) { + file._writeStream.destroy(); + setTimeout(fs.unlink, 0, file.path, function(error) { }); + }); + } +}; + +IncomingForm.prototype._parseContentLength = function() { + this.bytesReceived = 0; + if (this.headers['content-length']) { + this.bytesExpected = parseInt(this.headers['content-length'], 10); + } else if (this.headers['transfer-encoding'] === undefined) { + this.bytesExpected = 0; + } + + if (this.bytesExpected !== null) { + this.emit('progress', this.bytesReceived, this.bytesExpected); + } +}; + +IncomingForm.prototype._newParser = function() { + return new MultipartParser(); +}; + +IncomingForm.prototype._initMultipart = function(boundary) { + this.type = 'multipart'; + + var parser = new MultipartParser(), + self = this, + headerField, + headerValue, + part; + + parser.initWithBoundary(boundary); + + parser.onPartBegin = function() { + part = new Stream(); + part.readable = true; + part.headers = {}; + part.name = null; + part.filename = null; + part.mime = null; + + part.transferEncoding = 'binary'; + part.transferBuffer = ''; + + headerField = ''; + headerValue = ''; + }; + + parser.onHeaderField = function(b, start, end) { + headerField += b.toString(self.encoding, start, end); + }; + + parser.onHeaderValue = function(b, start, end) { + headerValue += b.toString(self.encoding, start, end); + }; + + parser.onHeaderEnd = function() { + headerField = headerField.toLowerCase(); + part.headers[headerField] = headerValue; + + var m = headerValue.match(/\bname="([^"]+)"/i); + if (headerField == 'content-disposition') { + if (m) { + part.name = m[1]; + } + + part.filename = self._fileName(headerValue); + } else if (headerField == 'content-type') { + part.mime = headerValue; + } else if (headerField == 'content-transfer-encoding') { + part.transferEncoding = headerValue.toLowerCase(); + } + + headerField = ''; + headerValue = ''; + }; + + parser.onHeadersEnd = function() { + switch(part.transferEncoding){ + case 'binary': + case '7bit': + case '8bit': + parser.onPartData = function(b, start, end) { + part.emit('data', b.slice(start, end)); + }; + + parser.onPartEnd = function() { + part.emit('end'); + }; + break; + + case 'base64': + parser.onPartData = function(b, start, end) { + part.transferBuffer += b.slice(start, end).toString('ascii'); + + /* + four bytes (chars) in base64 converts to three bytes in binary + encoding. So we should always work with a number of bytes that + can be divided by 4, it will result in a number of buytes that + can be divided vy 3. + */ + var offset = parseInt(part.transferBuffer.length / 4, 10) * 4; + part.emit('data', new Buffer(part.transferBuffer.substring(0, offset), 'base64')); + part.transferBuffer = part.transferBuffer.substring(offset); + }; + + parser.onPartEnd = function() { + part.emit('data', new Buffer(part.transferBuffer, 'base64')); + part.emit('end'); + }; + break; + + default: + return self._error(new Error('unknown transfer-encoding')); + } + + self.onPart(part); + }; + + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._fileName = function(headerValue) { + var m = headerValue.match(/\bfilename="(.*?)"($|; )/i); + if (!m) return; + + var filename = m[1].substr(m[1].lastIndexOf('\\') + 1); + filename = filename.replace(/%22/g, '"'); + filename = filename.replace(/&#([\d]{4});/g, function(m, code) { + return String.fromCharCode(code); + }); + return filename; +}; + +IncomingForm.prototype._initUrlencoded = function() { + this.type = 'urlencoded'; + + var parser = new QuerystringParser(this.maxFields) + , self = this; + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._initOctetStream = function() { + this.type = 'octet-stream'; + var filename = this.headers['x-file-name']; + var mime = this.headers['content-type']; + + var file = new File({ + path: this._uploadPath(filename), + name: filename, + type: mime + }); + + this.emit('fileBegin', filename, file); + file.open(); + + this._flushing++; + + var self = this; + + self._parser = new OctetParser(); + + //Keep track of writes that haven't finished so we don't emit the file before it's done being written + var outstandingWrites = 0; + + self._parser.on('data', function(buffer){ + self.pause(); + outstandingWrites++; + + file.write(buffer, function() { + outstandingWrites--; + self.resume(); + + if(self.ended){ + self._parser.emit('doneWritingFile'); + } + }); + }); + + self._parser.on('end', function(){ + self._flushing--; + self.ended = true; + + var done = function(){ + file.end(function() { + self.emit('file', 'file', file); + self._maybeEnd(); + }); + }; + + if(outstandingWrites === 0){ + done(); + } else { + self._parser.once('doneWritingFile', done); + } + }); +}; + +IncomingForm.prototype._initJSONencoded = function() { + this.type = 'json'; + + var parser = new JSONParser() + , self = this; + + if (this.bytesExpected) { + parser.initWithLength(this.bytesExpected); + } + + parser.onField = function(key, val) { + self.emit('field', key, val); + }; + + parser.onEnd = function() { + self.ended = true; + self._maybeEnd(); + }; + + this._parser = parser; +}; + +IncomingForm.prototype._uploadPath = function(filename) { + var name = 'upload_'; + var buf = crypto.randomBytes(16); + for (var i = 0; i < buf.length; ++i) { + name += ('0' + buf[i].toString(16)).slice(-2); + } + + if (this.keepExtensions) { + var ext = path.extname(filename); + ext = ext.replace(/(\.[a-z0-9]+).*/i, '$1'); + + name += ext; + } + + return path.join(this.uploadDir, name); +}; + +IncomingForm.prototype._maybeEnd = function() { + if (!this.ended || this._flushing || this.error) { + return; + } + + this.emit('end'); +}; + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/index.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/index.js new file mode 100644 index 0000000..7a6e3e1 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/index.js @@ -0,0 +1,3 @@ +var IncomingForm = require('./incoming_form').IncomingForm; +IncomingForm.IncomingForm = IncomingForm; +module.exports = IncomingForm; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/json_parser.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/json_parser.js new file mode 100644 index 0000000..db39c31 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/json_parser.js @@ -0,0 +1,35 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +var Buffer = require('buffer').Buffer; + +function JSONParser() { + this.data = new Buffer(''); + this.bytesWritten = 0; +} +exports.JSONParser = JSONParser; + +JSONParser.prototype.initWithLength = function(length) { + this.data = new Buffer(length); +}; + +JSONParser.prototype.write = function(buffer) { + if (this.data.length >= this.bytesWritten + buffer.length) { + buffer.copy(this.data, this.bytesWritten); + } else { + this.data = Buffer.concat([this.data, buffer]); + } + this.bytesWritten += buffer.length; + return buffer.length; +}; + +JSONParser.prototype.end = function() { + try { + var fields = JSON.parse(this.data.toString('utf8')); + for (var field in fields) { + this.onField(field, fields[field]); + } + } catch (e) {} + this.data = null; + + this.onEnd(); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/multipart_parser.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/multipart_parser.js new file mode 100644 index 0000000..36de2b0 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/multipart_parser.js @@ -0,0 +1,332 @@ +var Buffer = require('buffer').Buffer, + s = 0, + S = + { PARSER_UNINITIALIZED: s++, + START: s++, + START_BOUNDARY: s++, + HEADER_FIELD_START: s++, + HEADER_FIELD: s++, + HEADER_VALUE_START: s++, + HEADER_VALUE: s++, + HEADER_VALUE_ALMOST_DONE: s++, + HEADERS_ALMOST_DONE: s++, + PART_DATA_START: s++, + PART_DATA: s++, + PART_END: s++, + END: s++ + }, + + f = 1, + F = + { PART_BOUNDARY: f, + LAST_BOUNDARY: f *= 2 + }, + + LF = 10, + CR = 13, + SPACE = 32, + HYPHEN = 45, + COLON = 58, + A = 97, + Z = 122, + + lower = function(c) { + return c | 0x20; + }; + +for (s in S) { + exports[s] = S[s]; +} + +function MultipartParser() { + this.boundary = null; + this.boundaryChars = null; + this.lookbehind = null; + this.state = S.PARSER_UNINITIALIZED; + + this.index = null; + this.flags = 0; +} +exports.MultipartParser = MultipartParser; + +MultipartParser.stateToString = function(stateNumber) { + for (var state in S) { + var number = S[state]; + if (number === stateNumber) return state; + } +}; + +MultipartParser.prototype.initWithBoundary = function(str) { + this.boundary = new Buffer(str.length+4); + this.boundary.write('\r\n--', 0); + this.boundary.write(str, 4); + this.lookbehind = new Buffer(this.boundary.length+8); + this.state = S.START; + + this.boundaryChars = {}; + for (var i = 0; i < this.boundary.length; i++) { + this.boundaryChars[this.boundary[i]] = true; + } +}; + +MultipartParser.prototype.write = function(buffer) { + var self = this, + i = 0, + len = buffer.length, + prevIndex = this.index, + index = this.index, + state = this.state, + flags = this.flags, + lookbehind = this.lookbehind, + boundary = this.boundary, + boundaryChars = this.boundaryChars, + boundaryLength = this.boundary.length, + boundaryEnd = boundaryLength - 1, + bufferLength = buffer.length, + c, + cl, + + mark = function(name) { + self[name+'Mark'] = i; + }, + clear = function(name) { + delete self[name+'Mark']; + }, + callback = function(name, buffer, start, end) { + if (start !== undefined && start === end) { + return; + } + + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](buffer, start, end); + } + }, + dataCallback = function(name, clear) { + var markSymbol = name+'Mark'; + if (!(markSymbol in self)) { + return; + } + + if (!clear) { + callback(name, buffer, self[markSymbol], buffer.length); + self[markSymbol] = 0; + } else { + callback(name, buffer, self[markSymbol], i); + delete self[markSymbol]; + } + }; + + for (i = 0; i < len; i++) { + c = buffer[i]; + switch (state) { + case S.PARSER_UNINITIALIZED: + return i; + case S.START: + index = 0; + state = S.START_BOUNDARY; + case S.START_BOUNDARY: + if (index == boundary.length - 2) { + if (c == HYPHEN) { + flags |= F.LAST_BOUNDARY; + } else if (c != CR) { + return i; + } + index++; + break; + } else if (index - 1 == boundary.length - 2) { + if (flags & F.LAST_BOUNDARY && c == HYPHEN){ + callback('end'); + state = S.END; + flags = 0; + } else if (!(flags & F.LAST_BOUNDARY) && c == LF) { + index = 0; + callback('partBegin'); + state = S.HEADER_FIELD_START; + } else { + return i; + } + break; + } + + if (c != boundary[index+2]) { + index = -2; + } + if (c == boundary[index+2]) { + index++; + } + break; + case S.HEADER_FIELD_START: + state = S.HEADER_FIELD; + mark('headerField'); + index = 0; + case S.HEADER_FIELD: + if (c == CR) { + clear('headerField'); + state = S.HEADERS_ALMOST_DONE; + break; + } + + index++; + if (c == HYPHEN) { + break; + } + + if (c == COLON) { + if (index == 1) { + // empty header field + return i; + } + dataCallback('headerField', true); + state = S.HEADER_VALUE_START; + break; + } + + cl = lower(c); + if (cl < A || cl > Z) { + return i; + } + break; + case S.HEADER_VALUE_START: + if (c == SPACE) { + break; + } + + mark('headerValue'); + state = S.HEADER_VALUE; + case S.HEADER_VALUE: + if (c == CR) { + dataCallback('headerValue', true); + callback('headerEnd'); + state = S.HEADER_VALUE_ALMOST_DONE; + } + break; + case S.HEADER_VALUE_ALMOST_DONE: + if (c != LF) { + return i; + } + state = S.HEADER_FIELD_START; + break; + case S.HEADERS_ALMOST_DONE: + if (c != LF) { + return i; + } + + callback('headersEnd'); + state = S.PART_DATA_START; + break; + case S.PART_DATA_START: + state = S.PART_DATA; + mark('partData'); + case S.PART_DATA: + prevIndex = index; + + if (index === 0) { + // boyer-moore derrived algorithm to safely skip non-boundary data + i += boundaryEnd; + while (i < bufferLength && !(buffer[i] in boundaryChars)) { + i += boundaryLength; + } + i -= boundaryEnd; + c = buffer[i]; + } + + if (index < boundary.length) { + if (boundary[index] == c) { + if (index === 0) { + dataCallback('partData', true); + } + index++; + } else { + index = 0; + } + } else if (index == boundary.length) { + index++; + if (c == CR) { + // CR = part boundary + flags |= F.PART_BOUNDARY; + } else if (c == HYPHEN) { + // HYPHEN = end boundary + flags |= F.LAST_BOUNDARY; + } else { + index = 0; + } + } else if (index - 1 == boundary.length) { + if (flags & F.PART_BOUNDARY) { + index = 0; + if (c == LF) { + // unset the PART_BOUNDARY flag + flags &= ~F.PART_BOUNDARY; + callback('partEnd'); + callback('partBegin'); + state = S.HEADER_FIELD_START; + break; + } + } else if (flags & F.LAST_BOUNDARY) { + if (c == HYPHEN) { + callback('partEnd'); + callback('end'); + state = S.END; + flags = 0; + } else { + index = 0; + } + } else { + index = 0; + } + } + + if (index > 0) { + // when matching a possible boundary, keep a lookbehind reference + // in case it turns out to be a false lead + lookbehind[index-1] = c; + } else if (prevIndex > 0) { + // if our boundary turned out to be rubbish, the captured lookbehind + // belongs to partData + callback('partData', lookbehind, 0, prevIndex); + prevIndex = 0; + mark('partData'); + + // reconsider the current character even so it interrupted the sequence + // it could be the beginning of a new sequence + i--; + } + + break; + case S.END: + break; + default: + return i; + } + } + + dataCallback('headerField'); + dataCallback('headerValue'); + dataCallback('partData'); + + this.index = index; + this.state = state; + this.flags = flags; + + return len; +}; + +MultipartParser.prototype.end = function() { + var callback = function(self, name) { + var callbackSymbol = 'on'+name.substr(0, 1).toUpperCase()+name.substr(1); + if (callbackSymbol in self) { + self[callbackSymbol](); + } + }; + if ((this.state == S.HEADER_FIELD_START && this.index === 0) || + (this.state == S.PART_DATA && this.index == this.boundary.length)) { + callback(this, 'partEnd'); + callback(this, 'end'); + } else if (this.state != S.END) { + return new Error('MultipartParser.end(): stream ended unexpectedly: ' + this.explain()); + } +}; + +MultipartParser.prototype.explain = function() { + return 'state = ' + MultipartParser.stateToString(this.state); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/octet_parser.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/octet_parser.js new file mode 100644 index 0000000..6e8b551 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/octet_parser.js @@ -0,0 +1,20 @@ +var EventEmitter = require('events').EventEmitter + , util = require('util'); + +function OctetParser(options){ + if(!(this instanceof OctetParser)) return new OctetParser(options); + EventEmitter.call(this); +} + +util.inherits(OctetParser, EventEmitter); + +exports.OctetParser = OctetParser; + +OctetParser.prototype.write = function(buffer) { + this.emit('data', buffer); + return buffer.length; +}; + +OctetParser.prototype.end = function() { + this.emit('end'); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/querystring_parser.js b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/querystring_parser.js new file mode 100644 index 0000000..fcaffe0 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/lib/querystring_parser.js @@ -0,0 +1,27 @@ +if (global.GENTLY) require = GENTLY.hijack(require); + +// This is a buffering parser, not quite as nice as the multipart one. +// If I find time I'll rewrite this to be fully streaming as well +var querystring = require('querystring'); + +function QuerystringParser(maxKeys) { + this.maxKeys = maxKeys; + this.buffer = ''; +} +exports.QuerystringParser = QuerystringParser; + +QuerystringParser.prototype.write = function(buffer) { + this.buffer += buffer.toString('ascii'); + return buffer.length; +}; + +QuerystringParser.prototype.end = function() { + var fields = querystring.parse(this.buffer, '&', '=', { maxKeys: this.maxKeys }); + for (var field in fields) { + this.onField(field, fields[field]); + } + this.buffer = ''; + + this.onEnd(); +}; + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/formidable/package.json b/node_modules/supertest/node_modules/superagent/node_modules/formidable/package.json new file mode 100644 index 0000000..98510aa --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/formidable/package.json @@ -0,0 +1,65 @@ +{ + "name": "formidable", + "description": "A node.js module for parsing form data, especially file uploads.", + "homepage": "https://github.com/felixge/node-formidable", + "version": "1.0.17", + "devDependencies": { + "gently": "0.8.0", + "findit": "0.1.1", + "hashish": "0.0.4", + "urun": "~0.0.6", + "utest": "0.0.3", + "request": "~2.11.4" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/index", + "scripts": { + "test": "node test/run.js", + "clean": "rm test/tmp/*" + }, + "engines": { + "node": ">=0.8.0" + }, + "repository": { + "type": "git", + "url": "git://github.com/felixge/node-formidable.git" + }, + "bugs": { + "url": "http://github.com/felixge/node-formidable/issues" + }, + "optionalDependencies": {}, + "dependencies": {}, + "_id": "formidable@1.0.17", + "dist": { + "shasum": "ef5491490f9433b705faa77249c99029ae348559", + "tarball": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" + }, + "_from": "formidable@>=1.0.14 <1.1.0", + "_npmVersion": "1.4.3", + "_npmUser": { + "name": "felixge", + "email": "felix@debuggable.com" + }, + "maintainers": [ + { + "name": "felixge", + "email": "felix@debuggable.com" + }, + { + "name": "svnlto", + "email": "me@svenlito.com" + }, + { + "name": "superjoe", + "email": "superjoe30@gmail.com" + }, + { + "name": "tim-smart", + "email": "tim@fostle.com" + } + ], + "_shasum": "ef5491490f9433b705faa77249c99029ae348559", + "_resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintignore b/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintrc b/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintrc new file mode 100644 index 0000000..997b3f7 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/.jshintrc @@ -0,0 +1,10 @@ +{ + "node": true, + + "curly": true, + "latedef": true, + "quotmark": true, + "undef": true, + "unused": true, + "trailing": true +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/qs/.npmignore new file mode 100644 index 0000000..7e1574d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/.npmignore @@ -0,0 +1,18 @@ +.idea +*.iml +npm-debug.log +dump.rdb +node_modules +results.tap +results.xml +npm-shrinkwrap.json +config.json +.DS_Store +*/.DS_Store +*/*/.DS_Store +._* +*/._* +*/*/._* +coverage.* +lib-cov +complexity.md diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/.travis.yml b/node_modules/supertest/node_modules/superagent/node_modules/qs/.travis.yml new file mode 100644 index 0000000..c891dd0 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/.travis.yml @@ -0,0 +1,4 @@ +language: node_js + +node_js: + - 0.10
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/CHANGELOG.md b/node_modules/supertest/node_modules/superagent/node_modules/qs/CHANGELOG.md new file mode 100644 index 0000000..f5ee8b4 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/CHANGELOG.md @@ -0,0 +1,68 @@ + +## [**2.3.3**](https://github.com/hapijs/qs/issues?milestone=18&state=open) +- [**#59**](https://github.com/hapijs/qs/issues/59) make sure array indexes are >= 0, closes #57 +- [**#58**](https://github.com/hapijs/qs/issues/58) make qs usable for browser loader + +## [**2.3.2**](https://github.com/hapijs/qs/issues?milestone=17&state=closed) +- [**#55**](https://github.com/hapijs/qs/issues/55) allow merging a string into an object + +## [**2.3.1**](https://github.com/hapijs/qs/issues?milestone=16&state=closed) +- [**#52**](https://github.com/hapijs/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError". + +## [**2.3.0**](https://github.com/hapijs/qs/issues?milestone=15&state=closed) +- [**#50**](https://github.com/hapijs/qs/issues/50) add option to omit array indices, closes #46 + +## [**2.2.5**](https://github.com/hapijs/qs/issues?milestone=14&state=closed) +- [**#39**](https://github.com/hapijs/qs/issues/39) Is there an alternative to Buffer.isBuffer? +- [**#49**](https://github.com/hapijs/qs/issues/49) refactor utils.merge, fixes #45 +- [**#41**](https://github.com/hapijs/qs/issues/41) avoid browserifying Buffer, for #39 + +## [**2.2.4**](https://github.com/hapijs/qs/issues?milestone=13&state=closed) +- [**#38**](https://github.com/hapijs/qs/issues/38) how to handle object keys beginning with a number + +## [**2.2.3**](https://github.com/hapijs/qs/issues?milestone=12&state=closed) +- [**#37**](https://github.com/hapijs/qs/issues/37) parser discards first empty value in array +- [**#36**](https://github.com/hapijs/qs/issues/36) Update to lab 4.x + +## [**2.2.2**](https://github.com/hapijs/qs/issues?milestone=11&state=closed) +- [**#33**](https://github.com/hapijs/qs/issues/33) Error when plain object in a value +- [**#34**](https://github.com/hapijs/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty +- [**#24**](https://github.com/hapijs/qs/issues/24) Changelog? Semver? + +## [**2.2.1**](https://github.com/hapijs/qs/issues?milestone=10&state=closed) +- [**#32**](https://github.com/hapijs/qs/issues/32) account for circular references properly, closes #31 +- [**#31**](https://github.com/hapijs/qs/issues/31) qs.parse stackoverflow on circular objects + +## [**2.2.0**](https://github.com/hapijs/qs/issues?milestone=9&state=closed) +- [**#26**](https://github.com/hapijs/qs/issues/26) Don't use Buffer global if it's not present +- [**#30**](https://github.com/hapijs/qs/issues/30) Bug when merging non-object values into arrays +- [**#29**](https://github.com/hapijs/qs/issues/29) Don't call Utils.clone at the top of Utils.merge +- [**#23**](https://github.com/hapijs/qs/issues/23) Ability to not limit parameters? + +## [**2.1.0**](https://github.com/hapijs/qs/issues?milestone=8&state=closed) +- [**#22**](https://github.com/hapijs/qs/issues/22) Enable using a RegExp as delimiter + +## [**2.0.0**](https://github.com/hapijs/qs/issues?milestone=7&state=closed) +- [**#18**](https://github.com/hapijs/qs/issues/18) Why is there arrayLimit? +- [**#20**](https://github.com/hapijs/qs/issues/20) Configurable parametersLimit +- [**#21**](https://github.com/hapijs/qs/issues/21) make all limits optional, for #18, for #20 + +## [**1.2.2**](https://github.com/hapijs/qs/issues?milestone=6&state=closed) +- [**#19**](https://github.com/hapijs/qs/issues/19) Don't overwrite null values + +## [**1.2.1**](https://github.com/hapijs/qs/issues?milestone=5&state=closed) +- [**#16**](https://github.com/hapijs/qs/issues/16) ignore non-string delimiters +- [**#15**](https://github.com/hapijs/qs/issues/15) Close code block + +## [**1.2.0**](https://github.com/hapijs/qs/issues?milestone=4&state=closed) +- [**#12**](https://github.com/hapijs/qs/issues/12) Add optional delim argument +- [**#13**](https://github.com/hapijs/qs/issues/13) fix #11: flattened keys in array are now correctly parsed + +## [**1.1.0**](https://github.com/hapijs/qs/issues?milestone=3&state=closed) +- [**#7**](https://github.com/hapijs/qs/issues/7) Empty values of a POST array disappear after being submitted +- [**#9**](https://github.com/hapijs/qs/issues/9) Should not omit equals signs (=) when value is null +- [**#6**](https://github.com/hapijs/qs/issues/6) Minor grammar fix in README + +## [**1.0.2**](https://github.com/hapijs/qs/issues?milestone=2&state=closed) +- [**#5**](https://github.com/hapijs/qs/issues/5) array holes incorrectly copied into object on large index + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/CONTRIBUTING.md b/node_modules/supertest/node_modules/superagent/node_modules/qs/CONTRIBUTING.md new file mode 100644 index 0000000..8928361 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/CONTRIBUTING.md @@ -0,0 +1 @@ +Please view our [hapijs contributing guide](https://github.com/hapijs/hapi/blob/master/CONTRIBUTING.md). diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/qs/LICENSE new file mode 100755 index 0000000..d456948 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2014 Nathan LaFreniere and other contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of any contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * * * + +The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/Makefile b/node_modules/supertest/node_modules/superagent/node_modules/qs/Makefile new file mode 100644 index 0000000..31cc899 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/Makefile @@ -0,0 +1,8 @@ +test: + @node node_modules/lab/bin/lab -a code -L +test-cov: + @node node_modules/lab/bin/lab -a code -t 100 -L +test-cov-html: + @node node_modules/lab/bin/lab -a code -L -r html -o coverage.html + +.PHONY: test test-cov test-cov-html diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/README.md b/node_modules/supertest/node_modules/superagent/node_modules/qs/README.md new file mode 100755 index 0000000..21bf3fa --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/README.md @@ -0,0 +1,222 @@ +# qs + +A querystring parsing and stringifying library with some added security. + +[](http://travis-ci.org/hapijs/qs) + +Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf) + +The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring). + +## Usage + +```javascript +var Qs = require('qs'); + +var obj = Qs.parse('a=c'); // { a: 'c' } +var str = Qs.stringify(obj); // 'a=c' +``` + +### Parsing Objects + +```javascript +Qs.parse(string, [options]); +``` + +**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`. +For example, the string `'foo[bar]=baz'` converts to: + +```javascript +{ + foo: { + bar: 'baz' + } +} +``` + +URI encoded strings work too: + +```javascript +Qs.parse('a%5Bb%5D=c'); +// { a: { b: 'c' } } +``` + +You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`: + +```javascript +{ + foo: { + bar: { + baz: 'foobarbaz' + } + } +} +``` + +By default, when nesting objects **qs** will only parse up to 5 children deep. This means if you attempt to parse a string like +`'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be: + +```javascript +{ + a: { + b: { + c: { + d: { + e: { + f: { + '[g][h][i]': 'j' + } + } + } + } + } + } +} +``` + +This depth can be overridden by passing a `depth` option to `Qs.parse(string, [options])`: + +```javascript +Qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 }); +// { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } } +``` + +The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. + +For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option: + +```javascript +Qs.parse('a=b&c=d', { parameterLimit: 1 }); +// { a: 'b' } +``` + +An optional delimiter can also be passed: + +```javascript +Qs.parse('a=b;c=d', { delimiter: ';' }); +// { a: 'b', c: 'd' } +``` + +Delimiters can be a regular expression too: + +```javascript +Qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ }); +// { a: 'b', c: 'd', e: 'f' } +``` + +### Parsing Arrays + +**qs** can also parse arrays using a similar `[]` notation: + +```javascript +Qs.parse('a[]=b&a[]=c'); +// { a: ['b', 'c'] } +``` + +You may specify an index as well: + +```javascript +Qs.parse('a[1]=c&a[0]=b'); +// { a: ['b', 'c'] } +``` + +Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number +to create an array. When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving +their order: + +```javascript +Qs.parse('a[1]=b&a[15]=c'); +// { a: ['b', 'c'] } +``` + +Note that an empty string is also a value, and will be preserved: + +```javascript +Qs.parse('a[]=&a[]=b'); +// { a: ['', 'b'] } +Qs.parse('a[0]=b&a[1]=&a[2]=c'); +// { a: ['b', '', 'c'] } +``` + +**qs** will also limit specifying indices in an array to a maximum index of `20`. Any array members with an index of greater than `20` will +instead be converted to an object with the index as the key: + +```javascript +Qs.parse('a[100]=b'); +// { a: { '100': 'b' } } +``` + +This limit can be overridden by passing an `arrayLimit` option: + +```javascript +Qs.parse('a[1]=b', { arrayLimit: 0 }); +// { a: { '1': 'b' } } +``` + +To disable array parsing entirely, set `arrayLimit` to `-1`. + +If you mix notations, **qs** will merge the two items into an object: + +```javascript +Qs.parse('a[0]=b&a[b]=c'); +// { a: { '0': 'b', b: 'c' } } +``` + +You can also create arrays of objects: + +```javascript +Qs.parse('a[][b]=c'); +// { a: [{ b: 'c' }] } +``` + +### Stringifying + +```javascript +Qs.stringify(object, [options]); +``` + +When stringifying, **qs** always URI encodes output. Objects are stringified as you would expect: + +```javascript +Qs.stringify({ a: 'b' }); +// 'a=b' +Qs.stringify({ a: { b: 'c' } }); +// 'a%5Bb%5D=c' +``` + +Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage. + +When arrays are stringified, by default they are given explicit indices: + +```javascript +Qs.stringify({ a: ['b', 'c', 'd'] }); +// 'a[0]=b&a[1]=c&a[2]=d' +``` + +You may override this by setting the `indices` option to `false`: + +```javascript +Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); +// 'a=b&a=c&a=d' +``` + +Empty strings and null values will omit the value, but the equals sign (=) remains in place: + +```javascript +Qs.stringify({ a: '' }); +// 'a=' +``` + +Properties that are set to `undefined` will be omitted entirely: + +```javascript +Qs.stringify({ a: null, b: undefined }); +// 'a=' +``` + +The delimiter may be overridden with stringify as well: + +```javascript +Qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }); +// 'a=b;c=d' +``` diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/index.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/index.js new file mode 100644 index 0000000..2291cd8 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/index.js @@ -0,0 +1 @@ +module.exports = require('./lib/'); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/index.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/index.js new file mode 100755 index 0000000..0e09493 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/index.js @@ -0,0 +1,15 @@ +// Load modules + +var Stringify = require('./stringify'); +var Parse = require('./parse'); + + +// Declare internals + +var internals = {}; + + +module.exports = { + stringify: Stringify, + parse: Parse +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/parse.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/parse.js new file mode 100755 index 0000000..4e7d02a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/parse.js @@ -0,0 +1,157 @@ +// Load modules + +var Utils = require('./utils'); + + +// Declare internals + +var internals = { + delimiter: '&', + depth: 5, + arrayLimit: 20, + parameterLimit: 1000 +}; + + +internals.parseValues = function (str, options) { + + var obj = {}; + var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); + + for (var i = 0, il = parts.length; i < il; ++i) { + var part = parts[i]; + var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1; + + if (pos === -1) { + obj[Utils.decode(part)] = ''; + } + else { + var key = Utils.decode(part.slice(0, pos)); + var val = Utils.decode(part.slice(pos + 1)); + + if (!obj.hasOwnProperty(key)) { + obj[key] = val; + } + else { + obj[key] = [].concat(obj[key]).concat(val); + } + } + } + + return obj; +}; + + +internals.parseObject = function (chain, val, options) { + + if (!chain.length) { + return val; + } + + var root = chain.shift(); + + var obj = {}; + if (root === '[]') { + obj = []; + obj = obj.concat(internals.parseObject(chain, val, options)); + } + else { + var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root; + var index = parseInt(cleanRoot, 10); + var indexString = '' + index; + if (!isNaN(index) && + root !== cleanRoot && + indexString === cleanRoot && + index >= 0 && + index <= options.arrayLimit) { + + obj = []; + obj[index] = internals.parseObject(chain, val, options); + } + else { + obj[cleanRoot] = internals.parseObject(chain, val, options); + } + } + + return obj; +}; + + +internals.parseKeys = function (key, val, options) { + + if (!key) { + return; + } + + // The regex chunks + + var parent = /^([^\[\]]*)/; + var child = /(\[[^\[\]]*\])/g; + + // Get the parent + + var segment = parent.exec(key); + + // Don't allow them to overwrite object prototype properties + + if (Object.prototype.hasOwnProperty(segment[1])) { + return; + } + + // Stash the parent if it exists + + var keys = []; + if (segment[1]) { + keys.push(segment[1]); + } + + // Loop through children appending to the array until we hit depth + + var i = 0; + while ((segment = child.exec(key)) !== null && i < options.depth) { + + ++i; + if (!Object.prototype.hasOwnProperty(segment[1].replace(/\[|\]/g, ''))) { + keys.push(segment[1]); + } + } + + // If there's a remainder, just add whatever is left + + if (segment) { + keys.push('[' + key.slice(segment.index) + ']'); + } + + return internals.parseObject(keys, val, options); +}; + + +module.exports = function (str, options) { + + if (str === '' || + str === null || + typeof str === 'undefined') { + + return {}; + } + + options = options || {}; + options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter; + options.depth = typeof options.depth === 'number' ? options.depth : internals.depth; + options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit; + options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit; + + var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str; + var obj = {}; + + // Iterate over the keys and setup the new object + + var keys = Object.keys(tempObj); + for (var i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + var newObj = internals.parseKeys(key, tempObj[key], options); + obj = Utils.merge(obj, newObj); + } + + return Utils.compact(obj); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/stringify.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/stringify.js new file mode 100755 index 0000000..b441104 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/stringify.js @@ -0,0 +1,77 @@ +// Load modules + +var Utils = require('./utils'); + + +// Declare internals + +var internals = { + delimiter: '&', + indices: true +}; + + +internals.stringify = function (obj, prefix, options) { + + if (Utils.isBuffer(obj)) { + obj = obj.toString(); + } + else if (obj instanceof Date) { + obj = obj.toISOString(); + } + else if (obj === null) { + obj = ''; + } + + if (typeof obj === 'string' || + typeof obj === 'number' || + typeof obj === 'boolean') { + + return [encodeURIComponent(prefix) + '=' + encodeURIComponent(obj)]; + } + + var values = []; + + if (typeof obj === 'undefined') { + return values; + } + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + if (!options.indices && + Array.isArray(obj)) { + + values = values.concat(internals.stringify(obj[key], prefix, options)); + } + else { + values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', options)); + } + } + + return values; +}; + + +module.exports = function (obj, options) { + + options = options || {}; + var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; + options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices; + + var keys = []; + + if (typeof obj !== 'object' || + obj === null) { + + return ''; + } + + var objKeys = Object.keys(obj); + for (var i = 0, il = objKeys.length; i < il; ++i) { + var key = objKeys[i]; + keys = keys.concat(internals.stringify(obj[key], key, options)); + } + + return keys.join(delimiter); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/utils.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/utils.js new file mode 100755 index 0000000..5240bd5 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/lib/utils.js @@ -0,0 +1,132 @@ +// Load modules + + +// Declare internals + +var internals = {}; + + +exports.arrayToObject = function (source) { + + var obj = {}; + for (var i = 0, il = source.length; i < il; ++i) { + if (typeof source[i] !== 'undefined') { + + obj[i] = source[i]; + } + } + + return obj; +}; + + +exports.merge = function (target, source) { + + if (!source) { + return target; + } + + if (typeof source !== 'object') { + if (Array.isArray(target)) { + target.push(source); + } + else { + target[source] = true; + } + + return target; + } + + if (typeof target !== 'object') { + target = [target].concat(source); + return target; + } + + if (Array.isArray(target) && + !Array.isArray(source)) { + + target = exports.arrayToObject(target); + } + + var keys = Object.keys(source); + for (var k = 0, kl = keys.length; k < kl; ++k) { + var key = keys[k]; + var value = source[key]; + + if (!target[key]) { + target[key] = value; + } + else { + target[key] = exports.merge(target[key], value); + } + } + + return target; +}; + + +exports.decode = function (str) { + + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (e) { + return str; + } +}; + + +exports.compact = function (obj, refs) { + + if (typeof obj !== 'object' || + obj === null) { + + return obj; + } + + refs = refs || []; + var lookup = refs.indexOf(obj); + if (lookup !== -1) { + return refs[lookup]; + } + + refs.push(obj); + + if (Array.isArray(obj)) { + var compacted = []; + + for (var i = 0, il = obj.length; i < il; ++i) { + if (typeof obj[i] !== 'undefined') { + compacted.push(obj[i]); + } + } + + return compacted; + } + + var keys = Object.keys(obj); + for (i = 0, il = keys.length; i < il; ++i) { + var key = keys[i]; + obj[key] = exports.compact(obj[key], refs); + } + + return obj; +}; + + +exports.isRegExp = function (obj) { + return Object.prototype.toString.call(obj) === '[object RegExp]'; +}; + + +exports.isBuffer = function (obj) { + + if (obj === null || + typeof obj === 'undefined') { + + return false; + } + + return !!(obj.constructor && + obj.constructor.isBuffer && + obj.constructor.isBuffer(obj)); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/package.json b/node_modules/supertest/node_modules/superagent/node_modules/qs/package.json new file mode 100644 index 0000000..c040d31 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/package.json @@ -0,0 +1,58 @@ +{ + "name": "qs", + "version": "2.3.3", + "description": "A querystring parser that supports nesting and arrays, with a depth limit", + "homepage": "https://github.com/hapijs/qs", + "main": "index.js", + "dependencies": {}, + "devDependencies": { + "code": "1.x.x", + "lab": "5.x.x" + }, + "scripts": { + "test": "make test-cov" + }, + "repository": { + "type": "git", + "url": "https://github.com/hapijs/qs.git" + }, + "keywords": [ + "querystring", + "qs" + ], + "licenses": [ + { + "type": "BSD", + "url": "http://github.com/hapijs/qs/raw/master/LICENSE" + } + ], + "gitHead": "9250c4cda5102fcf72441445816e6d311fc6813d", + "bugs": { + "url": "https://github.com/hapijs/qs/issues" + }, + "_id": "qs@2.3.3", + "_shasum": "e9e85adbe75da0bbe4c8e0476a086290f863b404", + "_from": "qs@2.3.3", + "_npmVersion": "2.1.6", + "_nodeVersion": "0.10.32", + "_npmUser": { + "name": "nlf", + "email": "quitlahok@gmail.com" + }, + "maintainers": [ + { + "name": "nlf", + "email": "quitlahok@gmail.com" + }, + { + "name": "hueniverse", + "email": "eran@hueniverse.com" + } + ], + "dist": { + "shasum": "e9e85adbe75da0bbe4c8e0476a086290f863b404", + "tarball": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/test/parse.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/test/parse.js new file mode 100755 index 0000000..6c20cc1 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/test/parse.js @@ -0,0 +1,413 @@ +/* eslint no-extend-native:0 */ +// Load modules + +var Code = require('code'); +var Lab = require('lab'); +var Qs = require('../'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var expect = Code.expect; +var describe = lab.experiment; +var it = lab.test; + + +describe('parse()', function () { + + it('parses a simple string', function (done) { + + expect(Qs.parse('0=foo')).to.deep.equal({ '0': 'foo' }); + expect(Qs.parse('foo=c++')).to.deep.equal({ foo: 'c ' }); + expect(Qs.parse('a[>=]=23')).to.deep.equal({ a: { '>=': '23' } }); + expect(Qs.parse('a[<=>]==23')).to.deep.equal({ a: { '<=>': '=23' } }); + expect(Qs.parse('a[==]=23')).to.deep.equal({ a: { '==': '23' } }); + expect(Qs.parse('foo')).to.deep.equal({ foo: '' }); + expect(Qs.parse('foo=bar')).to.deep.equal({ foo: 'bar' }); + expect(Qs.parse(' foo = bar = baz ')).to.deep.equal({ ' foo ': ' bar = baz ' }); + expect(Qs.parse('foo=bar=baz')).to.deep.equal({ foo: 'bar=baz' }); + expect(Qs.parse('foo=bar&bar=baz')).to.deep.equal({ foo: 'bar', bar: 'baz' }); + expect(Qs.parse('foo=bar&baz')).to.deep.equal({ foo: 'bar', baz: '' }); + expect(Qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World')).to.deep.equal({ + cht: 'p3', + chd: 't:60,40', + chs: '250x100', + chl: 'Hello|World' + }); + done(); + }); + + it('parses a single nested string', function (done) { + + expect(Qs.parse('a[b]=c')).to.deep.equal({ a: { b: 'c' } }); + done(); + }); + + it('parses a double nested string', function (done) { + + expect(Qs.parse('a[b][c]=d')).to.deep.equal({ a: { b: { c: 'd' } } }); + done(); + }); + + it('defaults to a depth of 5', function (done) { + + expect(Qs.parse('a[b][c][d][e][f][g][h]=i')).to.deep.equal({ a: { b: { c: { d: { e: { f: { '[g][h]': 'i' } } } } } } }); + done(); + }); + + it('only parses one level when depth = 1', function (done) { + + expect(Qs.parse('a[b][c]=d', { depth: 1 })).to.deep.equal({ a: { b: { '[c]': 'd' } } }); + expect(Qs.parse('a[b][c][d]=e', { depth: 1 })).to.deep.equal({ a: { b: { '[c][d]': 'e' } } }); + done(); + }); + + it('parses a simple array', function (done) { + + expect(Qs.parse('a=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); + done(); + }); + + it('parses an explicit array', function (done) { + + expect(Qs.parse('a[]=b')).to.deep.equal({ a: ['b'] }); + expect(Qs.parse('a[]=b&a[]=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a[]=b&a[]=c&a[]=d')).to.deep.equal({ a: ['b', 'c', 'd'] }); + done(); + }); + + it('parses a mix of simple and explicit arrays', function (done) { + + expect(Qs.parse('a=b&a[]=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a[]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a[0]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a=b&a[0]=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a[1]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a=b&a[1]=c')).to.deep.equal({ a: ['b', 'c'] }); + done(); + }); + + it('parses a nested array', function (done) { + + expect(Qs.parse('a[b][]=c&a[b][]=d')).to.deep.equal({ a: { b: ['c', 'd'] } }); + expect(Qs.parse('a[>=]=25')).to.deep.equal({ a: { '>=': '25' } }); + done(); + }); + + it('allows to specify array indices', function (done) { + + expect(Qs.parse('a[1]=c&a[0]=b&a[2]=d')).to.deep.equal({ a: ['b', 'c', 'd'] }); + expect(Qs.parse('a[1]=c&a[0]=b')).to.deep.equal({ a: ['b', 'c'] }); + expect(Qs.parse('a[1]=c')).to.deep.equal({ a: ['c'] }); + done(); + }); + + it('limits specific array indices to 20', function (done) { + + expect(Qs.parse('a[20]=a')).to.deep.equal({ a: ['a'] }); + expect(Qs.parse('a[21]=a')).to.deep.equal({ a: { '21': 'a' } }); + done(); + }); + + it('supports keys that begin with a number', function (done) { + + expect(Qs.parse('a[12b]=c')).to.deep.equal({ a: { '12b': 'c' } }); + done(); + }); + + it('supports encoded = signs', function (done) { + + expect(Qs.parse('he%3Dllo=th%3Dere')).to.deep.equal({ 'he=llo': 'th=ere' }); + done(); + }); + + it('is ok with url encoded strings', function (done) { + + expect(Qs.parse('a[b%20c]=d')).to.deep.equal({ a: { 'b c': 'd' } }); + expect(Qs.parse('a[b]=c%20d')).to.deep.equal({ a: { b: 'c d' } }); + done(); + }); + + it('allows brackets in the value', function (done) { + + expect(Qs.parse('pets=["tobi"]')).to.deep.equal({ pets: '["tobi"]' }); + expect(Qs.parse('operators=[">=", "<="]')).to.deep.equal({ operators: '[">=", "<="]' }); + done(); + }); + + it('allows empty values', function (done) { + + expect(Qs.parse('')).to.deep.equal({}); + expect(Qs.parse(null)).to.deep.equal({}); + expect(Qs.parse(undefined)).to.deep.equal({}); + done(); + }); + + it('transforms arrays to objects', function (done) { + + expect(Qs.parse('foo[0]=bar&foo[bad]=baz')).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } }); + expect(Qs.parse('foo[bad]=baz&foo[0]=bar')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } }); + expect(Qs.parse('foo[bad]=baz&foo[]=bar')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar' } }); + expect(Qs.parse('foo[]=bar&foo[bad]=baz')).to.deep.equal({ foo: { '0': 'bar', bad: 'baz' } }); + expect(Qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo')).to.deep.equal({ foo: { bad: 'baz', '0': 'bar', '1': 'foo' } }); + expect(Qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb')).to.deep.equal({foo: [ {a: 'a', b: 'b'}, {a: 'aa', b: 'bb'} ]}); + done(); + }); + + it('can add keys to objects', function (done) { + + expect(Qs.parse('a[b]=c&a=d')).to.deep.equal({ a: { b: 'c', d: true } }); + done(); + }); + + it('correctly prunes undefined values when converting an array to an object', function (done) { + + expect(Qs.parse('a[2]=b&a[99999999]=c')).to.deep.equal({ a: { '2': 'b', '99999999': 'c' } }); + done(); + }); + + it('supports malformed uri characters', function (done) { + + expect(Qs.parse('{%:%}')).to.deep.equal({ '{%:%}': '' }); + expect(Qs.parse('foo=%:%}')).to.deep.equal({ foo: '%:%}' }); + done(); + }); + + it('doesn\'t produce empty keys', function (done) { + + expect(Qs.parse('_r=1&')).to.deep.equal({ '_r': '1' }); + done(); + }); + + it('cannot override prototypes', function (done) { + + var obj = Qs.parse('toString=bad&bad[toString]=bad&constructor=bad'); + expect(typeof obj.toString).to.equal('function'); + expect(typeof obj.bad.toString).to.equal('function'); + expect(typeof obj.constructor).to.equal('function'); + done(); + }); + + it('cannot access Object prototype', function (done) { + + Qs.parse('constructor[prototype][bad]=bad'); + Qs.parse('bad[constructor][prototype][bad]=bad'); + expect(typeof Object.prototype.bad).to.equal('undefined'); + done(); + }); + + it('parses arrays of objects', function (done) { + + expect(Qs.parse('a[][b]=c')).to.deep.equal({ a: [{ b: 'c' }] }); + expect(Qs.parse('a[0][b]=c')).to.deep.equal({ a: [{ b: 'c' }] }); + done(); + }); + + it('allows for empty strings in arrays', function (done) { + + expect(Qs.parse('a[]=b&a[]=&a[]=c')).to.deep.equal({ a: ['b', '', 'c'] }); + expect(Qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]=')).to.deep.equal({ a: ['b', '', 'c', ''] }); + expect(Qs.parse('a[]=&a[]=b&a[]=c')).to.deep.equal({ a: ['', 'b', 'c'] }); + done(); + }); + + it('compacts sparse arrays', function (done) { + + expect(Qs.parse('a[10]=1&a[2]=2')).to.deep.equal({ a: ['2', '1'] }); + done(); + }); + + it('parses semi-parsed strings', function (done) { + + expect(Qs.parse({ 'a[b]': 'c' })).to.deep.equal({ a: { b: 'c' } }); + expect(Qs.parse({ 'a[b]': 'c', 'a[d]': 'e' })).to.deep.equal({ a: { b: 'c', d: 'e' } }); + done(); + }); + + it('parses buffers correctly', function (done) { + + var b = new Buffer('test'); + expect(Qs.parse({ a: b })).to.deep.equal({ a: b }); + done(); + }); + + it('continues parsing when no parent is found', function (done) { + + expect(Qs.parse('[]&a=b')).to.deep.equal({ '0': '', a: 'b' }); + expect(Qs.parse('[foo]=bar')).to.deep.equal({ foo: 'bar' }); + done(); + }); + + it('does not error when parsing a very long array', function (done) { + + var str = 'a[]=a'; + while (Buffer.byteLength(str) < 128 * 1024) { + str += '&' + str; + } + + expect(function () { + + Qs.parse(str); + }).to.not.throw(); + + done(); + }); + + it('should not throw when a native prototype has an enumerable property', { parallel: false }, function (done) { + + Object.prototype.crash = ''; + Array.prototype.crash = ''; + expect(Qs.parse.bind(null, 'a=b')).to.not.throw(); + expect(Qs.parse('a=b')).to.deep.equal({ a: 'b' }); + expect(Qs.parse.bind(null, 'a[][b]=c')).to.not.throw(); + expect(Qs.parse('a[][b]=c')).to.deep.equal({ a: [{ b: 'c' }] }); + delete Object.prototype.crash; + delete Array.prototype.crash; + done(); + }); + + it('parses a string with an alternative string delimiter', function (done) { + + expect(Qs.parse('a=b;c=d', { delimiter: ';' })).to.deep.equal({ a: 'b', c: 'd' }); + done(); + }); + + it('parses a string with an alternative RegExp delimiter', function (done) { + + expect(Qs.parse('a=b; c=d', { delimiter: /[;,] */ })).to.deep.equal({ a: 'b', c: 'd' }); + done(); + }); + + it('does not use non-splittable objects as delimiters', function (done) { + + expect(Qs.parse('a=b&c=d', { delimiter: true })).to.deep.equal({ a: 'b', c: 'd' }); + done(); + }); + + it('allows overriding parameter limit', function (done) { + + expect(Qs.parse('a=b&c=d', { parameterLimit: 1 })).to.deep.equal({ a: 'b' }); + done(); + }); + + it('allows setting the parameter limit to Infinity', function (done) { + + expect(Qs.parse('a=b&c=d', { parameterLimit: Infinity })).to.deep.equal({ a: 'b', c: 'd' }); + done(); + }); + + it('allows overriding array limit', function (done) { + + expect(Qs.parse('a[0]=b', { arrayLimit: -1 })).to.deep.equal({ a: { '0': 'b' } }); + expect(Qs.parse('a[-1]=b', { arrayLimit: -1 })).to.deep.equal({ a: { '-1': 'b' } }); + expect(Qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 })).to.deep.equal({ a: { '0': 'b', '1': 'c' } }); + done(); + }); + + it('parses an object', function (done) { + + var input = { + 'user[name]': {'pop[bob]': 3}, + 'user[email]': null + }; + + var expected = { + 'user': { + 'name': {'pop[bob]': 3}, + 'email': null + } + }; + + var result = Qs.parse(input); + + expect(result).to.deep.equal(expected); + done(); + }); + + it('parses an object and not child values', function (done) { + + var input = { + 'user[name]': {'pop[bob]': { 'test': 3 }}, + 'user[email]': null + }; + + var expected = { + 'user': { + 'name': {'pop[bob]': { 'test': 3 }}, + 'email': null + } + }; + + var result = Qs.parse(input); + + expect(result).to.deep.equal(expected); + done(); + }); + + it('does not blow up when Buffer global is missing', function (done) { + + var tempBuffer = global.Buffer; + delete global.Buffer; + var result = Qs.parse('a=b&c=d'); + global.Buffer = tempBuffer; + expect(result).to.deep.equal({ a: 'b', c: 'd' }); + done(); + }); + + it('does not crash when using invalid dot notation', function (done) { + + expect(Qs.parse('roomInfoList[0].childrenAges[0]=15&roomInfoList[0].numberOfAdults=2')).to.deep.equal({ roomInfoList: [['15', '2']] }); + done(); + }); + + it('does not crash when parsing circular references', function (done) { + + var a = {}; + a.b = a; + + var parsed; + + expect(function () { + + parsed = Qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a }); + }).to.not.throw(); + + expect(parsed).to.contain('foo'); + expect(parsed.foo).to.contain('bar', 'baz'); + expect(parsed.foo.bar).to.equal('baz'); + expect(parsed.foo.baz).to.deep.equal(a); + done(); + }); + + it('parses plain objects correctly', function (done) { + + var a = Object.create(null); + a.b = 'c'; + + expect(Qs.parse(a)).to.deep.equal({ b: 'c' }); + var result = Qs.parse({ a: a }); + expect(result).to.contain('a'); + expect(result.a).to.deep.equal(a); + done(); + }); + + it('parses dates correctly', function (done) { + + var now = new Date(); + expect(Qs.parse({ a: now })).to.deep.equal({ a: now }); + done(); + }); + + it('parses regular expressions correctly', function (done) { + + var re = /^test$/; + expect(Qs.parse({ a: re })).to.deep.equal({ a: re }); + done(); + }); +}); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/qs/test/stringify.js b/node_modules/supertest/node_modules/superagent/node_modules/qs/test/stringify.js new file mode 100755 index 0000000..75e397a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/qs/test/stringify.js @@ -0,0 +1,179 @@ +/* eslint no-extend-native:0 */ +// Load modules + +var Code = require('code'); +var Lab = require('lab'); +var Qs = require('../'); + + +// Declare internals + +var internals = {}; + + +// Test shortcuts + +var lab = exports.lab = Lab.script(); +var expect = Code.expect; +var describe = lab.experiment; +var it = lab.test; + + +describe('stringify()', function () { + + it('stringifies a querystring object', function (done) { + + expect(Qs.stringify({ a: 'b' })).to.equal('a=b'); + expect(Qs.stringify({ a: 1 })).to.equal('a=1'); + expect(Qs.stringify({ a: 1, b: 2 })).to.equal('a=1&b=2'); + done(); + }); + + it('stringifies a nested object', function (done) { + + expect(Qs.stringify({ a: { b: 'c' } })).to.equal('a%5Bb%5D=c'); + expect(Qs.stringify({ a: { b: { c: { d: 'e' } } } })).to.equal('a%5Bb%5D%5Bc%5D%5Bd%5D=e'); + done(); + }); + + it('stringifies an array value', function (done) { + + expect(Qs.stringify({ a: ['b', 'c', 'd'] })).to.equal('a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d'); + done(); + }); + + it('omits array indices when asked', function (done) { + + expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false })).to.equal('a=b&a=c&a=d'); + done(); + }); + + it('stringifies a nested array value', function (done) { + + expect(Qs.stringify({ a: { b: ['c', 'd'] } })).to.equal('a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d'); + done(); + }); + + it('stringifies an object inside an array', function (done) { + + expect(Qs.stringify({ a: [{ b: 'c' }] })).to.equal('a%5B0%5D%5Bb%5D=c'); + expect(Qs.stringify({ a: [{ b: { c: [1] } }] })).to.equal('a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1'); + done(); + }); + + it('does not omit object keys when indices = false', function (done) { + + expect(Qs.stringify({ a: [{ b: 'c' }] }, { indices: false })).to.equal('a%5Bb%5D=c'); + done(); + }); + + it('stringifies a complicated object', function (done) { + + expect(Qs.stringify({ a: { b: 'c', d: 'e' } })).to.equal('a%5Bb%5D=c&a%5Bd%5D=e'); + done(); + }); + + it('stringifies an empty value', function (done) { + + expect(Qs.stringify({ a: '' })).to.equal('a='); + expect(Qs.stringify({ a: '', b: '' })).to.equal('a=&b='); + expect(Qs.stringify({ a: null })).to.equal('a='); + expect(Qs.stringify({ a: { b: null } })).to.equal('a%5Bb%5D='); + done(); + }); + + it('stringifies an empty object', function (done) { + + var obj = Object.create(null); + obj.a = 'b'; + expect(Qs.stringify(obj)).to.equal('a=b'); + done(); + }); + + it('returns an empty string for invalid input', function (done) { + + expect(Qs.stringify(undefined)).to.equal(''); + expect(Qs.stringify(false)).to.equal(''); + expect(Qs.stringify(null)).to.equal(''); + expect(Qs.stringify('')).to.equal(''); + done(); + }); + + it('stringifies an object with an empty object as a child', function (done) { + + var obj = { + a: Object.create(null) + }; + + obj.a.b = 'c'; + expect(Qs.stringify(obj)).to.equal('a%5Bb%5D=c'); + done(); + }); + + it('drops keys with a value of undefined', function (done) { + + expect(Qs.stringify({ a: undefined })).to.equal(''); + expect(Qs.stringify({ a: { b: undefined, c: null } })).to.equal('a%5Bc%5D='); + done(); + }); + + it('url encodes values', function (done) { + + expect(Qs.stringify({ a: 'b c' })).to.equal('a=b%20c'); + done(); + }); + + it('stringifies a date', function (done) { + + var now = new Date(); + var str = 'a=' + encodeURIComponent(now.toISOString()); + expect(Qs.stringify({ a: now })).to.equal(str); + done(); + }); + + it('stringifies the weird object from qs', function (done) { + + expect(Qs.stringify({ 'my weird field': 'q1!2"\'w$5&7/z8)?' })).to.equal('my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F'); + done(); + }); + + it('skips properties that are part of the object prototype', function (done) { + + Object.prototype.crash = 'test'; + expect(Qs.stringify({ a: 'b'})).to.equal('a=b'); + expect(Qs.stringify({ a: { b: 'c' } })).to.equal('a%5Bb%5D=c'); + delete Object.prototype.crash; + done(); + }); + + it('stringifies boolean values', function (done) { + + expect(Qs.stringify({ a: true })).to.equal('a=true'); + expect(Qs.stringify({ a: { b: true } })).to.equal('a%5Bb%5D=true'); + expect(Qs.stringify({ b: false })).to.equal('b=false'); + expect(Qs.stringify({ b: { c: false } })).to.equal('b%5Bc%5D=false'); + done(); + }); + + it('stringifies buffer values', function (done) { + + expect(Qs.stringify({ a: new Buffer('test') })).to.equal('a=test'); + expect(Qs.stringify({ a: { b: new Buffer('test') } })).to.equal('a%5Bb%5D=test'); + done(); + }); + + it('stringifies an object using an alternative delimiter', function (done) { + + expect(Qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' })).to.equal('a=b;c=d'); + done(); + }); + + it('doesn\'t blow up when Buffer global is missing', function (done) { + + var tempBuffer = global.Buffer; + delete global.Buffer; + expect(Qs.stringify({ a: 'b', c: 'd' })).to.equal('a=b&c=d'); + global.Buffer = tempBuffer; + done(); + }); +}); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/.npmignore new file mode 100644 index 0000000..38344f8 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/.npmignore @@ -0,0 +1,5 @@ +build/ +test/ +examples/ +fs.js +zlib.js
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/LICENSE new file mode 100644 index 0000000..0c44ae7 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/README.md b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/README.md new file mode 100644 index 0000000..34c1189 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/README.md @@ -0,0 +1,15 @@ +# readable-stream + +***Node-core streams for userland*** + +[](https://nodei.co/npm/readable-stream/) +[](https://nodei.co/npm/readable-stream/) + +This package is a mirror of the Streams2 and Streams3 implementations in Node-core. + +If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core. + +**readable-stream** comes in two major versions, v1.0.x and v1.1.x. The former tracks the Streams2 implementation in Node 0.10, including bug-fixes and minor improvements as they are added. The latter tracks Streams3 as it develops in Node 0.11; we will likely see a v1.2.x branch for Node 0.12. + +**readable-stream** uses proper patch-level versioning so if you pin to `"~1.0.0"` you’ll get the latest Node 0.10 Streams2 implementation, including any fixes and minor non-breaking improvements. The patch-level versions of 1.0.x and 1.1.x should mirror the patch-level versions of Node-core releases. You should prefer the **1.0.x** releases for now and when you’re ready to start using Streams3, pin to `"~1.1.0"` + diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/duplex.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/duplex.js new file mode 100644 index 0000000..ca807af --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/duplex.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_duplex.js") diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_duplex.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_duplex.js new file mode 100644 index 0000000..b513d61 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_duplex.js @@ -0,0 +1,89 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +module.exports = Duplex; + +/*<replacement>*/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} +/*</replacement>*/ + + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +forEach(objectKeys(Writable.prototype), function(method) { + if (!Duplex.prototype[method]) + Duplex.prototype[method] = Writable.prototype[method]; +}); + +function Duplex(options) { + if (!(this instanceof Duplex)) + return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) + this.allowHalfOpen = false; + + this.once('end', onend); +} + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) + return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(this.end.bind(this)); +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_passthrough.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_passthrough.js new file mode 100644 index 0000000..895ca50 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_passthrough.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) + return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function(chunk, encoding, cb) { + cb(null, chunk); +}; diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_readable.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_readable.js new file mode 100644 index 0000000..0ca7705 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_readable.js @@ -0,0 +1,959 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +module.exports = Readable; + +/*<replacement>*/ +var isArray = require('isarray'); +/*</replacement>*/ + + +/*<replacement>*/ +var Buffer = require('buffer').Buffer; +/*</replacement>*/ + +Readable.ReadableState = ReadableState; + +var EE = require('events').EventEmitter; + +/*<replacement>*/ +if (!EE.listenerCount) EE.listenerCount = function(emitter, type) { + return emitter.listeners(type).length; +}; +/*</replacement>*/ + +var Stream = require('stream'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +var StringDecoder; + +util.inherits(Readable, Stream); + +function ReadableState(options, stream) { + options = options || {}; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.buffer = []; + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = false; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // In streams that never have any data, and do push(null) right away, + // the consumer can miss the 'end' event if they do some I/O before + // consuming the stream. So, we don't emit('end') until some reading + // happens. + this.calledRead = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // when piping, we only care about 'readable' events that happen + // after read()ing all the bytes and not getting any pushback. + this.ranOut = false; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + if (!(this instanceof Readable)) + return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + Stream.call(this); +} + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function(chunk, encoding) { + var state = this._readableState; + + if (typeof chunk === 'string' && !state.objectMode) { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = new Buffer(chunk, encoding); + encoding = ''; + } + } + + return readableAddChunk(this, state, chunk, encoding, false); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function(chunk) { + var state = this._readableState; + return readableAddChunk(this, state, chunk, '', true); +}; + +function readableAddChunk(stream, state, chunk, encoding, addToFront) { + var er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (chunk === null || chunk === undefined) { + state.reading = false; + if (!state.ended) + onEofChunk(stream, state); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (state.ended && !addToFront) { + var e = new Error('stream.push() after EOF'); + stream.emit('error', e); + } else if (state.endEmitted && addToFront) { + var e = new Error('stream.unshift() after end event'); + stream.emit('error', e); + } else { + if (state.decoder && !addToFront && !encoding) + chunk = state.decoder.write(chunk); + + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) { + state.buffer.unshift(chunk); + } else { + state.reading = false; + state.buffer.push(chunk); + } + + if (state.needReadable) + emitReadable(stream); + + maybeReadMore(stream, state); + } + } else if (!addToFront) { + state.reading = false; + } + + return needMoreData(state); +} + + + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && + (state.needReadable || + state.length < state.highWaterMark || + state.length === 0); +} + +// backwards compatibility. +Readable.prototype.setEncoding = function(enc) { + if (!StringDecoder) + StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; +}; + +// Don't raise the hwm > 128MB +var MAX_HWM = 0x800000; +function roundUpToNextPowerOf2(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 + n--; + for (var p = 1; p < 32; p <<= 1) n |= n >> p; + n++; + } + return n; +} + +function howMuchToRead(n, state) { + if (state.length === 0 && state.ended) + return 0; + + if (state.objectMode) + return n === 0 ? 0 : 1; + + if (isNaN(n) || n === null) { + // only flow one buffer at a time + if (state.flowing && state.buffer.length) + return state.buffer[0].length; + else + return state.length; + } + + if (n <= 0) + return 0; + + // If we're asking for more than the target buffer level, + // then raise the water mark. Bump up to the next highest + // power of 2, to prevent increasing it excessively in tiny + // amounts. + if (n > state.highWaterMark) + state.highWaterMark = roundUpToNextPowerOf2(n); + + // don't have that much. return null, unless we've ended. + if (n > state.length) { + if (!state.ended) { + state.needReadable = true; + return 0; + } else + return state.length; + } + + return n; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function(n) { + var state = this._readableState; + state.calledRead = true; + var nOrig = n; + + if (typeof n !== 'number' || n > 0) + state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && + state.needReadable && + (state.length >= state.highWaterMark || state.ended)) { + emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) + endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + + // if we currently have less than the highWaterMark, then also read some + if (state.length - n <= state.highWaterMark) + doRead = true; + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) + doRead = false; + + if (doRead) { + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) + state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + } + + // If _read called its callback synchronously, then `reading` + // will be false, and we need to re-evaluate how much data we + // can return to the user. + if (doRead && !state.reading) + n = howMuchToRead(nOrig, state); + + var ret; + if (n > 0) + ret = fromList(n, state); + else + ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } + + state.length -= n; + + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (state.length === 0 && !state.ended) + state.needReadable = true; + + // If we happened to read() exactly the remaining amount in the + // buffer, and the EOF has been seen at this point, then make sure + // that we emit 'end' on the very next tick. + if (state.ended && !state.endEmitted && state.length === 0) + endReadable(this); + + return ret; +}; + +function chunkInvalid(state, chunk) { + var er = null; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode && + !er) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + + +function onEofChunk(stream, state) { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // if we've ended and we have some data left, then emit + // 'readable' now to make sure it gets picked up. + if (state.length > 0) + emitReadable(stream); + else + endReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (state.emittedReadable) + return; + + state.emittedReadable = true; + if (state.sync) + process.nextTick(function() { + emitReadable_(stream); + }); + else + emitReadable_(stream); +} + +function emitReadable_(stream) { + stream.emit('readable'); +} + + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(function() { + maybeReadMore_(stream, state); + }); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && + state.length < state.highWaterMark) { + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + else + len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function(n) { + this.emit('error', new Error('not implemented')); +}; + +Readable.prototype.pipe = function(dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && + dest !== process.stdout && + dest !== process.stderr; + + var endFn = doEnd ? onend : cleanup; + if (state.endEmitted) + process.nextTick(endFn); + else + src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable) { + if (readable !== src) return; + cleanup(); + } + + function onend() { + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + function cleanup() { + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', cleanup); + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (!dest._writableState || dest._writableState.needDrain) + ondrain(); + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + unpipe(); + dest.removeListener('error', onerror); + if (EE.listenerCount(dest, 'error') === 0) + dest.emit('error', er); + } + // This is a brutally ugly hack to make sure that our error handler + // is attached before any userland ones. NEVER DO THIS. + if (!dest._events || !dest._events.error) + dest.on('error', onerror); + else if (isArray(dest._events.error)) + dest._events.error.unshift(onerror); + else + dest._events.error = [onerror, dest._events.error]; + + + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + // the handler that waits for readable events after all + // the data gets sucked out in flow. + // This would be easier to follow with a .once() handler + // in flow(), but that is too slow. + this.on('readable', pipeOnReadable); + + state.flowing = true; + process.nextTick(function() { + flow(src); + }); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function() { + var dest = this; + var state = src._readableState; + state.awaitDrain--; + if (state.awaitDrain === 0) + flow(src); + }; +} + +function flow(src) { + var state = src._readableState; + var chunk; + state.awaitDrain = 0; + + function write(dest, i, list) { + var written = dest.write(chunk); + if (false === written) { + state.awaitDrain++; + } + } + + while (state.pipesCount && null !== (chunk = src.read())) { + + if (state.pipesCount === 1) + write(state.pipes, 0, null); + else + forEach(state.pipes, write); + + src.emit('data', chunk); + + // if anyone needs a drain, then we have to wait for that. + if (state.awaitDrain > 0) + return; + } + + // if every destination was unpiped, either before entering this + // function, or in the while loop, then stop flowing. + // + // NB: This is a pretty rare edge case. + if (state.pipesCount === 0) { + state.flowing = false; + + // if there were data event listeners added, then switch to old mode. + if (EE.listenerCount(src, 'data') > 0) + emitDataEvents(src); + return; + } + + // at this point, no one needed a drain, so we just ran out of data + // on the next readable event, start it over again. + state.ranOut = true; +} + +function pipeOnReadable() { + if (this._readableState.ranOut) { + this._readableState.ranOut = false; + flow(this); + } +} + + +Readable.prototype.unpipe = function(dest) { + var state = this._readableState; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) + return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) + return this; + + if (!dest) + dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + if (dest) + dest.emit('unpipe', this); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + this.removeListener('readable', pipeOnReadable); + state.flowing = false; + + for (var i = 0; i < len; i++) + dests[i].emit('unpipe', this); + return this; + } + + // try to find the right one. + var i = indexOf(state.pipes, dest); + if (i === -1) + return this; + + state.pipes.splice(i, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) + state.pipes = state.pipes[0]; + + dest.emit('unpipe', this); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function(ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data' && !this._readableState.flowing) + emitDataEvents(this); + + if (ev === 'readable' && this.readable) { + var state = this._readableState; + if (!state.readableListening) { + state.readableListening = true; + state.emittedReadable = false; + state.needReadable = true; + if (!state.reading) { + this.read(0); + } else if (state.length) { + emitReadable(this, state); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function() { + emitDataEvents(this); + this.read(0); + this.emit('resume'); +}; + +Readable.prototype.pause = function() { + emitDataEvents(this, true); + this.emit('pause'); +}; + +function emitDataEvents(stream, startPaused) { + var state = stream._readableState; + + if (state.flowing) { + // https://github.com/isaacs/readable-stream/issues/16 + throw new Error('Cannot switch to old mode now.'); + } + + var paused = startPaused || false; + var readable = false; + + // convert to an old-style stream. + stream.readable = true; + stream.pipe = Stream.prototype.pipe; + stream.on = stream.addListener = Stream.prototype.on; + + stream.on('readable', function() { + readable = true; + + var c; + while (!paused && (null !== (c = stream.read()))) + stream.emit('data', c); + + if (c === null) { + readable = false; + stream._readableState.needReadable = true; + } + }); + + stream.pause = function() { + paused = true; + this.emit('pause'); + }; + + stream.resume = function() { + paused = false; + if (readable) + process.nextTick(function() { + stream.emit('readable'); + }); + else + this.read(0); + this.emit('resume'); + }; + + // now make it start, just in case it hadn't already. + stream.emit('readable'); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function(stream) { + var state = this._readableState; + var paused = false; + + var self = this; + stream.on('end', function() { + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) + self.push(chunk); + } + + self.push(null); + }); + + stream.on('data', function(chunk) { + if (state.decoder) + chunk = state.decoder.write(chunk); + if (!chunk || !state.objectMode && !chunk.length) + return; + + var ret = self.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (typeof stream[i] === 'function' && + typeof this[i] === 'undefined') { + this[i] = function(method) { return function() { + return stream[method].apply(stream, arguments); + }}(i); + } + } + + // proxy certain important events. + var events = ['error', 'close', 'destroy', 'pause', 'resume']; + forEach(events, function(ev) { + stream.on(ev, self.emit.bind(self, ev)); + }); + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + self._read = function(n) { + if (paused) { + paused = false; + stream.resume(); + } + }; + + return self; +}; + + + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +function fromList(n, state) { + var list = state.buffer; + var length = state.length; + var stringMode = !!state.decoder; + var objectMode = !!state.objectMode; + var ret; + + // nothing in the list, definitely empty. + if (list.length === 0) + return null; + + if (length === 0) + ret = null; + else if (objectMode) + ret = list.shift(); + else if (!n || n >= length) { + // read it all, truncate the array. + if (stringMode) + ret = list.join(''); + else + ret = Buffer.concat(list, length); + list.length = 0; + } else { + // read just some of it. + if (n < list[0].length) { + // just take a part of the first list item. + // slice is the same for buffers and strings. + var buf = list[0]; + ret = buf.slice(0, n); + list[0] = buf.slice(n); + } else if (n === list[0].length) { + // first list is a perfect match + ret = list.shift(); + } else { + // complex case. + // we have enough to cover it, but it spans past the first buffer. + if (stringMode) + ret = ''; + else + ret = new Buffer(n); + + var c = 0; + for (var i = 0, l = list.length; i < l && c < n; i++) { + var buf = list[0]; + var cpy = Math.min(n - c, buf.length); + + if (stringMode) + ret += buf.slice(0, cpy); + else + buf.copy(ret, c, 0, cpy); + + if (cpy < buf.length) + list[0] = buf.slice(cpy); + else + list.shift(); + + c += cpy; + } + } + } + + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) + throw new Error('endReadable called on non-empty stream'); + + if (!state.endEmitted && state.calledRead) { + state.ended = true; + process.nextTick(function() { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } + }); + } +} + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} + +function indexOf (xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_transform.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_transform.js new file mode 100644 index 0000000..eb188df --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_transform.js @@ -0,0 +1,210 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + +util.inherits(Transform, Duplex); + + +function TransformState(options, stream) { + this.afterTransform = function(er, data) { + return afterTransform(stream, er, data); + }; + + this.needTransform = false; + this.transforming = false; + this.writecb = null; + this.writechunk = null; +} + +function afterTransform(stream, er, data) { + var ts = stream._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) + return stream.emit('error', new Error('no writecb in Transform class')); + + ts.writechunk = null; + ts.writecb = null; + + if (data !== null && data !== undefined) + stream.push(data); + + if (cb) + cb(er); + + var rs = stream._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + stream._read(rs.highWaterMark); + } +} + + +function Transform(options) { + if (!(this instanceof Transform)) + return new Transform(options); + + Duplex.call(this, options); + + var ts = this._transformState = new TransformState(options, this); + + // when the writable side finishes, then flush out anything remaining. + var stream = this; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + this.once('finish', function() { + if ('function' === typeof this._flush) + this._flush(function(er) { + done(stream, er); + }); + else + done(stream); + }); +} + +Transform.prototype.push = function(chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function(chunk, encoding, cb) { + throw new Error('not implemented'); +}; + +Transform.prototype._write = function(chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || + rs.needReadable || + rs.length < rs.highWaterMark) + this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function(n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + + +function done(stream, er) { + if (er) + return stream.emit('error', er); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + var ws = stream._writableState; + var rs = stream._readableState; + var ts = stream._transformState; + + if (ws.length) + throw new Error('calling transform done when ws.length != 0'); + + if (ts.transforming) + throw new Error('calling transform done when still transforming'); + + return stream.push(null); +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_writable.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_writable.js new file mode 100644 index 0000000..d0254d5 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/lib/_stream_writable.js @@ -0,0 +1,387 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, cb), and it'll handle all +// the drain event emission and buffering. + +module.exports = Writable; + +/*<replacement>*/ +var Buffer = require('buffer').Buffer; +/*</replacement>*/ + +Writable.WritableState = WritableState; + + +/*<replacement>*/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/*</replacement>*/ + + +var Stream = require('stream'); + +util.inherits(Writable, Stream); + +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; +} + +function WritableState(options, stream) { + options = options || {}; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + // cast to ints. + this.highWaterMark = ~~this.highWaterMark; + + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, becuase any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function(er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.buffer = []; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; +} + +function Writable(options) { + var Duplex = require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, though they're not + // instanceof Writable, they're instanceof Readable. + if (!(this instanceof Writable) && !(this instanceof Duplex)) + return new Writable(options); + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function() { + this.emit('error', new Error('Cannot pipe. Not readable.')); +}; + + +function writeAfterEnd(stream, state, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); +} + +// If we get something that is not a buffer, string, null, or undefined, +// and we're not in objectMode, then that's an error. +// Otherwise stream chunks are all considered to be of length=1, and the +// watermarks determine how many objects to keep in the buffer, rather than +// how many bytes or characters. +function validChunk(stream, state, chunk, cb) { + var valid = true; + if (!Buffer.isBuffer(chunk) && + 'string' !== typeof chunk && + chunk !== null && + chunk !== undefined && + !state.objectMode) { + var er = new TypeError('Invalid non-string/buffer chunk'); + stream.emit('error', er); + process.nextTick(function() { + cb(er); + }); + valid = false; + } + return valid; +} + +Writable.prototype.write = function(chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + else if (!encoding) + encoding = state.defaultEncoding; + + if (typeof cb !== 'function') + cb = function() {}; + + if (state.ended) + writeAfterEnd(this, state, cb); + else if (validChunk(this, state, chunk, cb)) + ret = writeOrBuffer(this, state, chunk, encoding, cb); + + return ret; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && + state.decodeStrings !== false && + typeof chunk === 'string') { + chunk = new Buffer(chunk, encoding); + } + return chunk; +} + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, chunk, encoding, cb) { + chunk = decodeChunk(state, chunk, encoding); + if (Buffer.isBuffer(chunk)) + encoding = 'buffer'; + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) + state.needDrain = true; + + if (state.writing) + state.buffer.push(new WriteReq(chunk, encoding, cb)); + else + doWrite(stream, state, len, chunk, encoding, cb); + + return ret; +} + +function doWrite(stream, state, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + if (sync) + process.nextTick(function() { + cb(er); + }); + else + cb(er); + + stream._writableState.errorEmitted = true; + stream.emit('error', er); +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) + onwriteError(stream, state, sync, er, cb); + else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(stream, state); + + if (!finished && !state.bufferProcessing && state.buffer.length) + clearBuffer(stream, state); + + if (sync) { + process.nextTick(function() { + afterWrite(stream, state, finished, cb); + }); + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) + onwriteDrain(stream, state); + cb(); + if (finished) + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + + for (var c = 0; c < state.buffer.length; c++) { + var entry = state.buffer[c]; + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, len, chunk, encoding, cb); + + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + c++; + break; + } + } + + state.bufferProcessing = false; + if (c < state.buffer.length) + state.buffer = state.buffer.slice(c); + else + state.buffer.length = 0; +} + +Writable.prototype._write = function(chunk, encoding, cb) { + cb(new Error('not implemented')); +}; + +Writable.prototype.end = function(chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (typeof chunk !== 'undefined' && chunk !== null) + this.write(chunk, encoding); + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) + endWritable(this, state, cb); +}; + + +function needFinish(stream, state) { + return (state.ending && + state.length === 0 && + !state.finished && + !state.writing); +} + +function finishMaybe(stream, state) { + var need = needFinish(stream, state); + if (need) { + state.finished = true; + stream.emit('finish'); + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) + process.nextTick(cb); + else + stream.once('finish', cb); + } + state.ended = true; +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/package.json b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/package.json new file mode 100644 index 0000000..62d4c9f --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/package.json @@ -0,0 +1,68 @@ +{ + "name": "readable-stream", + "version": "1.0.27-1", + "description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x", + "main": "readable.js", + "dependencies": { + "core-util-is": "~1.0.0", + "isarray": "0.0.1", + "string_decoder": "~0.10.x", + "inherits": "~2.0.1" + }, + "devDependencies": { + "tap": "~0.2.6" + }, + "scripts": { + "test": "tap test/simple/*.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/readable-stream" + }, + "keywords": [ + "readable", + "stream", + "pipe" + ], + "browser": { + "util": false + }, + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/isaacs/readable-stream/issues" + }, + "homepage": "https://github.com/isaacs/readable-stream", + "_id": "readable-stream@1.0.27-1", + "dist": { + "shasum": "6b67983c20357cefd07f0165001a16d710d91078", + "tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz" + }, + "_from": "readable-stream@1.0.27-1", + "_npmVersion": "1.4.3", + "_npmUser": { + "name": "rvagg", + "email": "rod@vagg.org" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + }, + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "directories": {}, + "_shasum": "6b67983c20357cefd07f0165001a16d710d91078", + "_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/passthrough.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/passthrough.js new file mode 100644 index 0000000..27e8d8a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/passthrough.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_passthrough.js") diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/readable.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/readable.js new file mode 100644 index 0000000..4d1ddfc --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/readable.js @@ -0,0 +1,6 @@ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/transform.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/transform.js new file mode 100644 index 0000000..5d482f0 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/transform.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_transform.js") diff --git a/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/writable.js b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/writable.js new file mode 100644 index 0000000..e1e9efd --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/readable-stream/writable.js @@ -0,0 +1 @@ +module.exports = require("./lib/_stream_writable.js") diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/.npmignore b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/.npmignore new file mode 100644 index 0000000..aa6fd7c --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/.npmignore @@ -0,0 +1,3 @@ +components +build +node_modules
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/History.md b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/History.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/History.md diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/LICENSE b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/LICENSE new file mode 100644 index 0000000..2bb9ad2 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/LICENSE @@ -0,0 +1,176 @@ + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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/supertest/node_modules/superagent/node_modules/reduce-component/Makefile b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/Makefile new file mode 100644 index 0000000..71e373c --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/Makefile @@ -0,0 +1,16 @@ + +build: components index.js + @component build --dev + +components: component.json + @component install --dev + +clean: + rm -fr build components + +test: + @./node_modules/.bin/mocha \ + --require should \ + --reporter spec + +.PHONY: clean test diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/Readme.md b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/Readme.md new file mode 100644 index 0000000..479ed6f --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/Readme.md @@ -0,0 +1,32 @@ + +# reduce + + array reduce + +## Installation + +```sh + $ component install redventures/reduce +``` + +## API + +```js +var reduce = require('reduce'); + +var numbers = [0, 1, 2, 3, 4, 5]; + +var result = reduce(numbers, function(prev, curr){ + return prev + curr; +}); +``` + +## License + +Copyright 2012 Red Ventures + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at: + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/component.json b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/component.json new file mode 100644 index 0000000..5fe6e17 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/component.json @@ -0,0 +1,13 @@ +{ + "name": "reduce", + "repo": "redventures/reduce", + "description": "Array reduce component", + "version": "1.0.0", + "keywords": ["array", "reduce"], + "dependencies": {}, + "development": {}, + "license": "Apache, Version 2.0", + "scripts": [ + "index.js" + ] +}
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/index.js b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/index.js new file mode 100644 index 0000000..26deede --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/index.js @@ -0,0 +1,24 @@ + +/** + * Reduce `arr` with `fn`. + * + * @param {Array} arr + * @param {Function} fn + * @param {Mixed} initial + * + * TODO: combatible error handling? + */ + +module.exports = function(arr, fn, initial){ + var idx = 0; + var len = arr.length; + var curr = arguments.length == 3 + ? initial + : arr[idx++]; + + while (idx < len) { + curr = fn.call(null, curr, arr[idx], ++idx, arr); + } + + return curr; +};
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/package.json b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/package.json new file mode 100644 index 0000000..a74c28d --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/package.json @@ -0,0 +1,46 @@ +{ + "name": "reduce-component", + "description": "Array reduce component", + "version": "1.0.1", + "repository": { + "type": "git", + "url": "git://github.com/redventures/reduce.git" + }, + "dependencies": {}, + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "component": { + "scripts": { + "reduce": "index.js" + } + }, + "main": "./index.js", + "license": "Apache, Version 2.0", + "readme": "\n# reduce\n\n array reduce\n\n## Installation\n\n```sh\n $ component install redventures/reduce\n```\n\n## API\n\n```js\nvar reduce = require('reduce');\n\nvar numbers = [0, 1, 2, 3, 4, 5];\n\nvar result = reduce(numbers, function(prev, curr){\n return prev + curr;\n});\n```\n \n## License\n\nCopyright 2012 Red Ventures\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless 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.\n", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/redventures/reduce/issues" + }, + "_id": "reduce-component@1.0.1", + "dist": { + "shasum": "e0c93542c574521bea13df0f9488ed82ab77c5da", + "tarball": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz" + }, + "_from": "reduce-component@1.0.1", + "_npmVersion": "1.3.11", + "_npmUser": { + "name": "gjohnson", + "email": "gjj391@gmail.com" + }, + "maintainers": [ + { + "name": "gjohnson", + "email": "gjj391@gmail.com" + } + ], + "directories": {}, + "_shasum": "e0c93542c574521bea13df0f9488ed82ab77c5da", + "_resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/index.html b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/index.html new file mode 100644 index 0000000..6325231 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/index.html @@ -0,0 +1,30 @@ +<html> +<head> + <title>reduce component</title> +</head> +<body> + <script src="../build/build.js"></script> + <script> + var reduce = require('reduce'); + + var items = [0, 1, 2, 3, 4, 5]; + var none = []; + + var a = reduce(items, concat); + var b = reduce(items, sum); + var c = reduce(items, sum, 10); + + console.log('concat: %s', a); + console.log('sum: %s', b); + console.log('sum + 10: %s', c); + + function concat(prev, curr, idx, arr) { + return String(prev) + String(curr); + } + + function sum(prev, curr){ + return prev + curr; + } + </script> +</body> +</html>
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/reduce.js b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/reduce.js new file mode 100644 index 0000000..d44af28 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/node_modules/reduce-component/test/reduce.js @@ -0,0 +1,49 @@ + +var reduce = require('..'); + +describe('reduce', function(){ + + describe('when adding prev and current', function(){ + it('should be sum all the values', function(){ + var numbers = [2,2,2]; + var fn = function(prev, curr){ + return prev + curr; + }; + + var a = numbers.reduce(fn); + var b = reduce(numbers, fn); + + a.should.equal(6); + b.should.equal(a); + }); + }); + + describe('when passing in an initial value', function(){ + it('should default to it', function(){ + var items = []; + var fn = function(prev){ + return prev; + }; + + var a = items.reduce(fn, 'foo'); + var b = reduce(items, fn, 'foo'); + + a.should.equal('foo'); + b.should.equal(a); + }); + + it('should start with it', function(){ + var items = [10, 10]; + var fn = function(prev, curr){ + return prev + curr; + }; + + var a = items.reduce(fn, 10); + var b = reduce(items, fn, 10); + + a.should.equal(30); + b.should.equal(a); + }); + }); + +});
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/package.json b/node_modules/supertest/node_modules/superagent/package.json new file mode 100644 index 0000000..aad028a --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/package.json @@ -0,0 +1,146 @@ +{ + "name": "superagent", + "version": "1.8.3", + "description": "elegant & feature rich browser / node HTTP with a fluent API", + "scripts": { + "prepublish": "make all", + "test": "make test" + }, + "keywords": [ + "http", + "ajax", + "request", + "agent" + ], + "license": "MIT", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "contributors": [ + { + "name": "Kornel Lesiński", + "email": "kornel@geekhood.net" + }, + { + "name": "Peter Lyons", + "email": "pete@peterlyons.com" + }, + { + "name": "Hunter Loftis", + "email": "hunter@hunterloftis.com" + } + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/superagent.git" + }, + "dependencies": { + "qs": "2.3.3", + "formidable": "~1.0.14", + "mime": "1.3.4", + "component-emitter": "~1.2.0", + "methods": "~1.1.1", + "cookiejar": "2.0.6", + "debug": "2", + "reduce-component": "1.0.1", + "extend": "3.0.0", + "form-data": "1.0.0-rc3", + "readable-stream": "1.0.27-1" + }, + "devDependencies": { + "Base64": "~0.3.0", + "basic-auth-connect": "~1.0.0", + "better-assert": "~1.0.1", + "body-parser": "~1.9.2", + "browserify": "~6.3.2", + "cookie-parser": "~1.3.3", + "express": "~4.9.8", + "express-session": "~1.9.1", + "marked": "0.3.5", + "mocha": "~2.0.1", + "should": "~3.1.3", + "zuul": "~1.19.0" + }, + "browser": { + "./lib/node/index.js": "./lib/client.js", + "emitter": "component-emitter", + "reduce": "reduce-component", + "./test/support/server.js": "./test/support/blank.js" + }, + "component": { + "scripts": { + "superagent": "lib/client.js" + } + }, + "main": "./lib/node/index.js", + "engines": { + "node": ">= 0.8" + }, + "gitHead": "4d986d7f0c1efd8d0690c95a9276a6c818b758f7", + "bugs": { + "url": "https://github.com/visionmedia/superagent/issues" + }, + "homepage": "https://github.com/visionmedia/superagent#readme", + "_id": "superagent@1.8.3", + "_shasum": "2b7d70fcc870eda4f2a61e619dd54009b86547c3", + "_from": "superagent@>=1.7.2 <2.0.0", + "_npmVersion": "3.7.5", + "_nodeVersion": "5.6.0", + "_npmUser": { + "name": "kornel", + "email": "pornel@pornel.net" + }, + "dist": { + "shasum": "2b7d70fcc870eda4f2a61e619dd54009b86547c3", + "tarball": "https://registry.npmjs.org/superagent/-/superagent-1.8.3.tgz" + }, + "maintainers": [ + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "kof", + "email": "oleg008@gmail.com" + }, + { + "name": "kornel", + "email": "pornel@pornel.net" + }, + { + "name": "naman34", + "email": "naman34@gmail.com" + }, + { + "name": "nw", + "email": "nw@nwhite.net" + }, + { + "name": "rauchg", + "email": "rauchg@gmail.com" + }, + { + "name": "superjoe", + "email": "superjoe30@gmail.com" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "travisjeffery", + "email": "tj@travisjeffery.com" + }, + { + "name": "yields", + "email": "yields@icloud.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/superagent-1.8.3.tgz_1458840247188_0.5249448795802891" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/superagent/-/superagent-1.8.3.tgz" +} diff --git a/node_modules/supertest/node_modules/superagent/superagent.js b/node_modules/supertest/node_modules/superagent/superagent.js new file mode 100644 index 0000000..b64d1d5 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/superagent.js @@ -0,0 +1,1486 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.superagent = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +/** + * Check if `obj` is an object. + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + +function isObject(obj) { + return null != obj && 'object' == typeof obj; +} + +module.exports = isObject; + +},{}],2:[function(require,module,exports){ +/** + * Module of mixed-in functions shared between node and client code + */ +var isObject = require('./is-object'); + +/** + * Clear previous timeout. + * + * @return {Request} for chaining + * @api public + */ + +exports.clearTimeout = function _clearTimeout(){ + this._timeout = 0; + clearTimeout(this._timer); + return this; +}; + +/** + * Force given parser + * + * Sets the body parser no matter type. + * + * @param {Function} + * @api public + */ + +exports.parse = function parse(fn){ + this._parser = fn; + return this; +}; + +/** + * Set timeout to `ms`. + * + * @param {Number} ms + * @return {Request} for chaining + * @api public + */ + +exports.timeout = function timeout(ms){ + this._timeout = ms; + return this; +}; + +/** + * Faux promise support + * + * @param {Function} fulfill + * @param {Function} reject + * @return {Request} + */ + +exports.then = function then(fulfill, reject) { + return this.end(function(err, res) { + err ? reject(err) : fulfill(res); + }); +} + +/** + * Allow for extension + */ + +exports.use = function use(fn) { + fn(this); + return this; +} + + +/** + * Get request header `field`. + * Case-insensitive. + * + * @param {String} field + * @return {String} + * @api public + */ + +exports.get = function(field){ + return this._header[field.toLowerCase()]; +}; + +/** + * Get case-insensitive header `field` value. + * This is a deprecated internal API. Use `.get(field)` instead. + * + * (getHeader is no longer used internally by the superagent code base) + * + * @param {String} field + * @return {String} + * @api private + * @deprecated + */ + +exports.getHeader = exports.get; + +/** + * Set header `field` to `val`, or multiple fields with one object. + * Case-insensitive. + * + * Examples: + * + * req.get('/') + * .set('Accept', 'application/json') + * .set('X-API-Key', 'foobar') + * .end(callback); + * + * req.get('/') + * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' }) + * .end(callback); + * + * @param {String|Object} field + * @param {String} val + * @return {Request} for chaining + * @api public + */ + +exports.set = function(field, val){ + if (isObject(field)) { + for (var key in field) { + this.set(key, field[key]); + } + return this; + } + this._header[field.toLowerCase()] = val; + this.header[field] = val; + return this; +}; + +/** + * Remove header `field`. + * Case-insensitive. + * + * Example: + * + * req.get('/') + * .unset('User-Agent') + * .end(callback); + * + * @param {String} field + */ +exports.unset = function(field){ + delete this._header[field.toLowerCase()]; + delete this.header[field]; + return this; +}; + +/** + * Write the field `name` and `val` for "multipart/form-data" + * request bodies. + * + * ``` js + * request.post('/upload') + * .field('foo', 'bar') + * .end(callback); + * ``` + * + * @param {String} name + * @param {String|Blob|File|Buffer|fs.ReadStream} val + * @return {Request} for chaining + * @api public + */ +exports.field = function(name, val) { + this._getFormData().append(name, val); + return this; +}; + +},{"./is-object":1}],3:[function(require,module,exports){ +// The node and browser modules expose versions of this with the +// appropriate constructor function bound as first argument +/** + * Issue a request: + * + * Examples: + * + * request('GET', '/users').end(callback) + * request('/users').end(callback) + * request('/users', callback) + * + * @param {String} method + * @param {String|Function} url or callback + * @return {Request} + * @api public + */ + +function request(RequestConstructor, method, url) { + // callback + if ('function' == typeof url) { + return new RequestConstructor('GET', method).end(url); + } + + // url first + if (2 == arguments.length) { + return new RequestConstructor('GET', method); + } + + return new RequestConstructor(method, url); +} + +module.exports = request; + +},{}],4:[function(require,module,exports){ + +/** + * Expose `Emitter`. + */ + +module.exports = Emitter; + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = +Emitter.prototype.addEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks['$' + event] = this._callbacks['$' + event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + function on() { + this.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = +Emitter.prototype.removeEventListener = function(event, fn){ + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks['$' + event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks['$' + event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks['$' + event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks['$' + event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; + +},{}],5:[function(require,module,exports){ + +/** + * Reduce `arr` with `fn`. + * + * @param {Array} arr + * @param {Function} fn + * @param {Mixed} initial + * + * TODO: combatible error handling? + */ + +module.exports = function(arr, fn, initial){ + var idx = 0; + var len = arr.length; + var curr = arguments.length == 3 + ? initial + : arr[idx++]; + + while (idx < len) { + curr = fn.call(null, curr, arr[idx], ++idx, arr); + } + + return curr; +}; +},{}],6:[function(require,module,exports){ +/** + * Module dependencies. + */ + +var Emitter = require('emitter'); +var reduce = require('reduce'); +var requestBase = require('./request-base'); +var isObject = require('./is-object'); + +/** + * Root reference for iframes. + */ + +var root; +if (typeof window !== 'undefined') { // Browser window + root = window; +} else if (typeof self !== 'undefined') { // Web Worker + root = self; +} else { // Other environments + root = this; +} + +/** + * Noop. + */ + +function noop(){}; + +/** + * Check if `obj` is a host object, + * we don't want to serialize these :) + * + * TODO: future proof, move to compoent land + * + * @param {Object} obj + * @return {Boolean} + * @api private + */ + +function isHost(obj) { + var str = {}.toString.call(obj); + + switch (str) { + case '[object File]': + case '[object Blob]': + case '[object FormData]': + return true; + default: + return false; + } +} + +/** + * Expose `request`. + */ + +var request = module.exports = require('./request').bind(null, Request); + +/** + * Determine XHR. + */ + +request.getXHR = function () { + if (root.XMLHttpRequest + && (!root.location || 'file:' != root.location.protocol + || !root.ActiveXObject)) { + return new XMLHttpRequest; + } else { + try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {} + try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} + } + return false; +}; + +/** + * Removes leading and trailing whitespace, added to support IE. + * + * @param {String} s + * @return {String} + * @api private + */ + +var trim = ''.trim + ? function(s) { return s.trim(); } + : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); }; + +/** + * Serialize the given `obj`. + * + * @param {Object} obj + * @return {String} + * @api private + */ + +function serialize(obj) { + if (!isObject(obj)) return obj; + var pairs = []; + for (var key in obj) { + if (null != obj[key]) { + pushEncodedKeyValuePair(pairs, key, obj[key]); + } + } + return pairs.join('&'); +} + +/** + * Helps 'serialize' with serializing arrays. + * Mutates the pairs array. + * + * @param {Array} pairs + * @param {String} key + * @param {Mixed} val + */ + +function pushEncodedKeyValuePair(pairs, key, val) { + if (Array.isArray(val)) { + return val.forEach(function(v) { + pushEncodedKeyValuePair(pairs, key, v); + }); + } + pairs.push(encodeURIComponent(key) + + '=' + encodeURIComponent(val)); +} + +/** + * Expose serialization method. + */ + + request.serializeObject = serialize; + + /** + * Parse the given x-www-form-urlencoded `str`. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function parseString(str) { + var obj = {}; + var pairs = str.split('&'); + var parts; + var pair; + + for (var i = 0, len = pairs.length; i < len; ++i) { + pair = pairs[i]; + parts = pair.split('='); + obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]); + } + + return obj; +} + +/** + * Expose parser. + */ + +request.parseString = parseString; + +/** + * Default MIME type map. + * + * superagent.types.xml = 'application/xml'; + * + */ + +request.types = { + html: 'text/html', + json: 'application/json', + xml: 'application/xml', + urlencoded: 'application/x-www-form-urlencoded', + 'form': 'application/x-www-form-urlencoded', + 'form-data': 'application/x-www-form-urlencoded' +}; + +/** + * Default serialization map. + * + * superagent.serialize['application/xml'] = function(obj){ + * return 'generated xml here'; + * }; + * + */ + + request.serialize = { + 'application/x-www-form-urlencoded': serialize, + 'application/json': JSON.stringify + }; + + /** + * Default parsers. + * + * superagent.parse['application/xml'] = function(str){ + * return { object parsed from str }; + * }; + * + */ + +request.parse = { + 'application/x-www-form-urlencoded': parseString, + 'application/json': JSON.parse +}; + +/** + * Parse the given header `str` into + * an object containing the mapped fields. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function parseHeader(str) { + var lines = str.split(/\r?\n/); + var fields = {}; + var index; + var line; + var field; + var val; + + lines.pop(); // trailing CRLF + + for (var i = 0, len = lines.length; i < len; ++i) { + line = lines[i]; + index = line.indexOf(':'); + field = line.slice(0, index).toLowerCase(); + val = trim(line.slice(index + 1)); + fields[field] = val; + } + + return fields; +} + +/** + * Check if `mime` is json or has +json structured syntax suffix. + * + * @param {String} mime + * @return {Boolean} + * @api private + */ + +function isJSON(mime) { + return /[\/+]json\b/.test(mime); +} + +/** + * Return the mime type for the given `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function type(str){ + return str.split(/ *; */).shift(); +}; + +/** + * Return header field parameters. + * + * @param {String} str + * @return {Object} + * @api private + */ + +function params(str){ + return reduce(str.split(/ *; */), function(obj, str){ + var parts = str.split(/ *= */) + , key = parts.shift() + , val = parts.shift(); + + if (key && val) obj[key] = val; + return obj; + }, {}); +}; + +/** + * Initialize a new `Response` with the given `xhr`. + * + * - set flags (.ok, .error, etc) + * - parse header + * + * Examples: + * + * Aliasing `superagent` as `request` is nice: + * + * request = superagent; + * + * We can use the promise-like API, or pass callbacks: + * + * request.get('/').end(function(res){}); + * request.get('/', function(res){}); + * + * Sending data can be chained: + * + * request + * .post('/user') + * .send({ name: 'tj' }) + * .end(function(res){}); + * + * Or passed to `.send()`: + * + * request + * .post('/user') + * .send({ name: 'tj' }, function(res){}); + * + * Or passed to `.post()`: + * + * request + * .post('/user', { name: 'tj' }) + * .end(function(res){}); + * + * Or further reduced to a single call for simple cases: + * + * request + * .post('/user', { name: 'tj' }, function(res){}); + * + * @param {XMLHTTPRequest} xhr + * @param {Object} options + * @api private + */ + +function Response(req, options) { + options = options || {}; + this.req = req; + this.xhr = this.req.xhr; + // responseText is accessible only if responseType is '' or 'text' and on older browsers + this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined') + ? this.xhr.responseText + : null; + this.statusText = this.req.xhr.statusText; + this.setStatusProperties(this.xhr.status); + this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders()); + // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but + // getResponseHeader still works. so we get content-type even if getting + // other headers fails. + this.header['content-type'] = this.xhr.getResponseHeader('content-type'); + this.setHeaderProperties(this.header); + this.body = this.req.method != 'HEAD' + ? this.parseBody(this.text ? this.text : this.xhr.response) + : null; +} + +/** + * Get case-insensitive `field` value. + * + * @param {String} field + * @return {String} + * @api public + */ + +Response.prototype.get = function(field){ + return this.header[field.toLowerCase()]; +}; + +/** + * Set header related properties: + * + * - `.type` the content type without params + * + * A response of "Content-Type: text/plain; charset=utf-8" + * will provide you with a `.type` of "text/plain". + * + * @param {Object} header + * @api private + */ + +Response.prototype.setHeaderProperties = function(header){ + // content-type + var ct = this.header['content-type'] || ''; + this.type = type(ct); + + // params + var obj = params(ct); + for (var key in obj) this[key] = obj[key]; +}; + +/** + * Parse the given body `str`. + * + * Used for auto-parsing of bodies. Parsers + * are defined on the `superagent.parse` object. + * + * @param {String} str + * @return {Mixed} + * @api private + */ + +Response.prototype.parseBody = function(str){ + var parse = request.parse[this.type]; + if (!parse && isJSON(this.type)) { + parse = request.parse['application/json']; + } + return parse && str && (str.length || str instanceof Object) + ? parse(str) + : null; +}; + +/** + * Set flags such as `.ok` based on `status`. + * + * For example a 2xx response will give you a `.ok` of __true__ + * whereas 5xx will be __false__ and `.error` will be __true__. The + * `.clientError` and `.serverError` are also available to be more + * specific, and `.statusType` is the class of error ranging from 1..5 + * sometimes useful for mapping respond colors etc. + * + * "sugar" properties are also defined for common cases. Currently providing: + * + * - .noContent + * - .badRequest + * - .unauthorized + * - .notAcceptable + * - .notFound + * + * @param {Number} status + * @api private + */ + +Response.prototype.setStatusProperties = function(status){ + // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request + if (status === 1223) { + status = 204; + } + + var type = status / 100 | 0; + + // status / class + this.status = this.statusCode = status; + this.statusType = type; + + // basics + this.info = 1 == type; + this.ok = 2 == type; + this.clientError = 4 == type; + this.serverError = 5 == type; + this.error = (4 == type || 5 == type) + ? this.toError() + : false; + + // sugar + this.accepted = 202 == status; + this.noContent = 204 == status; + this.badRequest = 400 == status; + this.unauthorized = 401 == status; + this.notAcceptable = 406 == status; + this.notFound = 404 == status; + this.forbidden = 403 == status; +}; + +/** + * Return an `Error` representative of this response. + * + * @return {Error} + * @api public + */ + +Response.prototype.toError = function(){ + var req = this.req; + var method = req.method; + var url = req.url; + + var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')'; + var err = new Error(msg); + err.status = this.status; + err.method = method; + err.url = url; + + return err; +}; + +/** + * Expose `Response`. + */ + +request.Response = Response; + +/** + * Initialize a new `Request` with the given `method` and `url`. + * + * @param {String} method + * @param {String} url + * @api public + */ + +function Request(method, url) { + var self = this; + this._query = this._query || []; + this.method = method; + this.url = url; + this.header = {}; // preserves header name case + this._header = {}; // coerces header names to lowercase + this.on('end', function(){ + var err = null; + var res = null; + + try { + res = new Response(self); + } catch(e) { + err = new Error('Parser is unable to parse the response'); + err.parse = true; + err.original = e; + // issue #675: return the raw response if the response parsing fails + err.rawResponse = self.xhr && self.xhr.responseText ? self.xhr.responseText : null; + // issue #876: return the http status code if the response parsing fails + err.statusCode = self.xhr && self.xhr.status ? self.xhr.status : null; + return self.callback(err); + } + + self.emit('response', res); + + if (err) { + return self.callback(err, res); + } + + if (res.status >= 200 && res.status < 300) { + return self.callback(err, res); + } + + var new_err = new Error(res.statusText || 'Unsuccessful HTTP response'); + new_err.original = err; + new_err.response = res; + new_err.status = res.status; + + self.callback(new_err, res); + }); +} + +/** + * Mixin `Emitter` and `requestBase`. + */ + +Emitter(Request.prototype); +for (var key in requestBase) { + Request.prototype[key] = requestBase[key]; +} + +/** + * Abort the request, and clear potential timeout. + * + * @return {Request} + * @api public + */ + +Request.prototype.abort = function(){ + if (this.aborted) return; + this.aborted = true; + this.xhr.abort(); + this.clearTimeout(); + this.emit('abort'); + return this; +}; + +/** + * Set Content-Type to `type`, mapping values from `request.types`. + * + * Examples: + * + * superagent.types.xml = 'application/xml'; + * + * request.post('/') + * .type('xml') + * .send(xmlstring) + * .end(callback); + * + * request.post('/') + * .type('application/xml') + * .send(xmlstring) + * .end(callback); + * + * @param {String} type + * @return {Request} for chaining + * @api public + */ + +Request.prototype.type = function(type){ + this.set('Content-Type', request.types[type] || type); + return this; +}; + +/** + * Set responseType to `val`. Presently valid responseTypes are 'blob' and + * 'arraybuffer'. + * + * Examples: + * + * req.get('/') + * .responseType('blob') + * .end(callback); + * + * @param {String} val + * @return {Request} for chaining + * @api public + */ + +Request.prototype.responseType = function(val){ + this._responseType = val; + return this; +}; + +/** + * Set Accept to `type`, mapping values from `request.types`. + * + * Examples: + * + * superagent.types.json = 'application/json'; + * + * request.get('/agent') + * .accept('json') + * .end(callback); + * + * request.get('/agent') + * .accept('application/json') + * .end(callback); + * + * @param {String} accept + * @return {Request} for chaining + * @api public + */ + +Request.prototype.accept = function(type){ + this.set('Accept', request.types[type] || type); + return this; +}; + +/** + * Set Authorization field value with `user` and `pass`. + * + * @param {String} user + * @param {String} pass + * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic') + * @return {Request} for chaining + * @api public + */ + +Request.prototype.auth = function(user, pass, options){ + if (!options) { + options = { + type: 'basic' + } + } + + switch (options.type) { + case 'basic': + var str = btoa(user + ':' + pass); + this.set('Authorization', 'Basic ' + str); + break; + + case 'auto': + this.username = user; + this.password = pass; + break; + } + return this; +}; + +/** +* Add query-string `val`. +* +* Examples: +* +* request.get('/shoes') +* .query('size=10') +* .query({ color: 'blue' }) +* +* @param {Object|String} val +* @return {Request} for chaining +* @api public +*/ + +Request.prototype.query = function(val){ + if ('string' != typeof val) val = serialize(val); + if (val) this._query.push(val); + return this; +}; + +/** + * Queue the given `file` as an attachment to the specified `field`, + * with optional `filename`. + * + * ``` js + * request.post('/upload') + * .attach(new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"})) + * .end(callback); + * ``` + * + * @param {String} field + * @param {Blob|File} file + * @param {String} filename + * @return {Request} for chaining + * @api public + */ + +Request.prototype.attach = function(field, file, filename){ + this._getFormData().append(field, file, filename || file.name); + return this; +}; + +Request.prototype._getFormData = function(){ + if (!this._formData) { + this._formData = new root.FormData(); + } + return this._formData; +}; + +/** + * Send `data` as the request body, defaulting the `.type()` to "json" when + * an object is given. + * + * Examples: + * + * // manual json + * request.post('/user') + * .type('json') + * .send('{"name":"tj"}') + * .end(callback) + * + * // auto json + * request.post('/user') + * .send({ name: 'tj' }) + * .end(callback) + * + * // manual x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send('name=tj') + * .end(callback) + * + * // auto x-www-form-urlencoded + * request.post('/user') + * .type('form') + * .send({ name: 'tj' }) + * .end(callback) + * + * // defaults to x-www-form-urlencoded + * request.post('/user') + * .send('name=tobi') + * .send('species=ferret') + * .end(callback) + * + * @param {String|Object} data + * @return {Request} for chaining + * @api public + */ + +Request.prototype.send = function(data){ + var obj = isObject(data); + var type = this._header['content-type']; + + // merge + if (obj && isObject(this._data)) { + for (var key in data) { + this._data[key] = data[key]; + } + } else if ('string' == typeof data) { + if (!type) this.type('form'); + type = this._header['content-type']; + if ('application/x-www-form-urlencoded' == type) { + this._data = this._data + ? this._data + '&' + data + : data; + } else { + this._data = (this._data || '') + data; + } + } else { + this._data = data; + } + + if (!obj || isHost(data)) return this; + if (!type) this.type('json'); + return this; +}; + +/** + * @deprecated + */ +Response.prototype.parse = function serialize(fn){ + if (root.console) { + console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0"); + } + this.serialize(fn); + return this; +}; + +Response.prototype.serialize = function serialize(fn){ + this._parser = fn; + return this; +}; + +/** + * Invoke the callback with `err` and `res` + * and handle arity check. + * + * @param {Error} err + * @param {Response} res + * @api private + */ + +Request.prototype.callback = function(err, res){ + var fn = this._callback; + this.clearTimeout(); + fn(err, res); +}; + +/** + * Invoke callback with x-domain error. + * + * @api private + */ + +Request.prototype.crossDomainError = function(){ + var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.'); + err.crossDomain = true; + + err.status = this.status; + err.method = this.method; + err.url = this.url; + + this.callback(err); +}; + +/** + * Invoke callback with timeout error. + * + * @api private + */ + +Request.prototype.timeoutError = function(){ + var timeout = this._timeout; + var err = new Error('timeout of ' + timeout + 'ms exceeded'); + err.timeout = timeout; + this.callback(err); +}; + +/** + * Enable transmission of cookies with x-domain requests. + * + * Note that for this to work the origin must not be + * using "Access-Control-Allow-Origin" with a wildcard, + * and also must set "Access-Control-Allow-Credentials" + * to "true". + * + * @api public + */ + +Request.prototype.withCredentials = function(){ + this._withCredentials = true; + return this; +}; + +/** + * Initiate request, invoking callback `fn(res)` + * with an instanceof `Response`. + * + * @param {Function} fn + * @return {Request} for chaining + * @api public + */ + +Request.prototype.end = function(fn){ + var self = this; + var xhr = this.xhr = request.getXHR(); + var query = this._query.join('&'); + var timeout = this._timeout; + var data = this._formData || this._data; + + // store callback + this._callback = fn || noop; + + // state change + xhr.onreadystatechange = function(){ + if (4 != xhr.readyState) return; + + // In IE9, reads to any property (e.g. status) off of an aborted XHR will + // result in the error "Could not complete the operation due to error c00c023f" + var status; + try { status = xhr.status } catch(e) { status = 0; } + + if (0 == status) { + if (self.timedout) return self.timeoutError(); + if (self.aborted) return; + return self.crossDomainError(); + } + self.emit('end'); + }; + + // progress + var handleProgress = function(e){ + if (e.total > 0) { + e.percent = e.loaded / e.total * 100; + } + e.direction = 'download'; + self.emit('progress', e); + }; + if (this.hasListeners('progress')) { + xhr.onprogress = handleProgress; + } + try { + if (xhr.upload && this.hasListeners('progress')) { + xhr.upload.onprogress = handleProgress; + } + } catch(e) { + // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist. + // Reported here: + // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context + } + + // timeout + if (timeout && !this._timer) { + this._timer = setTimeout(function(){ + self.timedout = true; + self.abort(); + }, timeout); + } + + // querystring + if (query) { + query = request.serializeObject(query); + this.url += ~this.url.indexOf('?') + ? '&' + query + : '?' + query; + } + + // initiate request + if (this.username && this.password) { + xhr.open(this.method, this.url, true, this.username, this.password); + } else { + xhr.open(this.method, this.url, true); + } + + // CORS + if (this._withCredentials) xhr.withCredentials = true; + + // body + if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !isHost(data)) { + // serialize stuff + var contentType = this._header['content-type']; + var serialize = this._parser || request.serialize[contentType ? contentType.split(';')[0] : '']; + if (!serialize && isJSON(contentType)) serialize = request.serialize['application/json']; + if (serialize) data = serialize(data); + } + + // set header fields + for (var field in this.header) { + if (null == this.header[field]) continue; + xhr.setRequestHeader(field, this.header[field]); + } + + if (this._responseType) { + xhr.responseType = this._responseType; + } + + // send stuff + this.emit('request', this); + + // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing) + // We need null here if data is undefined + xhr.send(typeof data !== 'undefined' ? data : null); + return this; +}; + + +/** + * Expose `Request`. + */ + +request.Request = Request; + +/** + * GET `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.get = function(url, data, fn){ + var req = request('GET', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.query(data); + if (fn) req.end(fn); + return req; +}; + +/** + * HEAD `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.head = function(url, data, fn){ + var req = request('HEAD', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * DELETE `url` with optional callback `fn(res)`. + * + * @param {String} url + * @param {Function} fn + * @return {Request} + * @api public + */ + +function del(url, fn){ + var req = request('DELETE', url); + if (fn) req.end(fn); + return req; +}; + +request['del'] = del; +request['delete'] = del; + +/** + * PATCH `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed} data + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.patch = function(url, data, fn){ + var req = request('PATCH', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * POST `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed} data + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.post = function(url, data, fn){ + var req = request('POST', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +/** + * PUT `url` with optional `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed|Function} data or fn + * @param {Function} fn + * @return {Request} + * @api public + */ + +request.put = function(url, data, fn){ + var req = request('PUT', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + if (fn) req.end(fn); + return req; +}; + +},{"./is-object":1,"./request":3,"./request-base":2,"emitter":4,"reduce":5}]},{},[6])(6) +});
\ No newline at end of file diff --git a/node_modules/supertest/node_modules/superagent/test.js b/node_modules/supertest/node_modules/superagent/test.js new file mode 100644 index 0000000..67637f0 --- /dev/null +++ b/node_modules/supertest/node_modules/superagent/test.js @@ -0,0 +1,6 @@ + +var bla = require('.'); + +bla.get('http://localhost:8080/') + .then(function(){return 1;}) + .then(console.log.bind(console)); diff --git a/node_modules/supertest/package.json b/node_modules/supertest/package.json new file mode 100644 index 0000000..4aee5d9 --- /dev/null +++ b/node_modules/supertest/package.json @@ -0,0 +1,87 @@ +{ + "name": "supertest", + "version": "1.2.0", + "description": "Super-agent driven library for testing HTTP servers", + "main": "index.js", + "scripts": { + "pretest": "npm install", + "test": "mocha --require should --reporter spec --check-leaks" + }, + "dependencies": { + "superagent": "^1.7.2", + "methods": "1.x" + }, + "devDependencies": { + "body-parser": "~1.13.2", + "cookie-parser": "~1.3.5", + "express": "~4.12.4", + "mocha": "~2.2.5", + "should": "~7.0.2" + }, + "engines": { + "node": ">=0.10.0" + }, + "keywords": [ + "superagent", + "request", + "tdd", + "bdd", + "http", + "test", + "testing" + ], + "author": { + "name": "TJ Holowaychuk" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/visionmedia/supertest.git" + }, + "gitHead": "f4efb75950d3081a06dc1e9e88b0372a0512f08e", + "bugs": { + "url": "https://github.com/visionmedia/supertest/issues" + }, + "homepage": "https://github.com/visionmedia/supertest#readme", + "_id": "supertest@1.2.0", + "_shasum": "850a795f9068d2faf19e01799ff09962e0ce43be", + "_from": "supertest@latest", + "_npmVersion": "2.14.12", + "_nodeVersion": "4.2.4", + "_npmUser": { + "name": "mikelax", + "email": "mholtzman@gmail.com" + }, + "dist": { + "shasum": "850a795f9068d2faf19e01799ff09962e0ce43be", + "tarball": "https://registry.npmjs.org/supertest/-/supertest-1.2.0.tgz" + }, + "maintainers": [ + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + }, + { + "name": "gjohnson", + "email": "gjj391@gmail.com" + }, + { + "name": "kof", + "email": "oleg008@gmail.com" + }, + { + "name": "defunctzombie", + "email": "shtylman@gmail.com" + }, + { + "name": "mikelax", + "email": "mholtzman@gmail.com" + } + ], + "_npmOperationalInternal": { + "host": "packages-6-west.internal.npmjs.com", + "tmp": "tmp/supertest-1.2.0.tgz_1455204548964_0.9615733381360769" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/supertest/-/supertest-1.2.0.tgz" +} diff --git a/node_modules/supertest/test/fixtures/test_cert.pem b/node_modules/supertest/test/fixtures/test_cert.pem new file mode 100644 index 0000000..6ff9b12 --- /dev/null +++ b/node_modules/supertest/test/fixtures/test_cert.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICjzCCAfgCCQCduAjYszOZ3DANBgkqhkiG9w0BAQUFADCBizELMAkGA1UEBhMC +Q04xEzARBgNVBAgTCkd1YW5nIERvbmcxFDASBgNVBAcTC0d1YW5nIFpob3VlMQ4w +DAYDVQQKEwVUQkVEUDENMAsGA1UECxMEVEVTVDEQMA4GA1UEAxMHZmVuZ21rMjEg +MB4GCSqGSIb3DQEJARYRZmVuZ21rMkBnbWFpbC5jb20wHhcNMTIwOTIzMTQxMDI5 +WhcNMTIxMDIzMTQxMDI5WjCBizELMAkGA1UEBhMCQ04xEzARBgNVBAgTCkd1YW5n +IERvbmcxFDASBgNVBAcTC0d1YW5nIFpob3VlMQ4wDAYDVQQKEwVUQkVEUDENMAsG +A1UECxMEVEVTVDEQMA4GA1UEAxMHZmVuZ21rMjEgMB4GCSqGSIb3DQEJARYRZmVu +Z21rMkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALOEtchk +KBK8WTqwXR2Aov2mc0+igyQTGbxBDSyyULHPiecMqOBHs5bV4DL1pc/01hLKIp4T +2j2KNTTmeivrtKd3wMQL7A+IgyqdmeqRi98pYUylFZrHxb9Kiwm7mpHanodmgnTT +zOluEpi/K9h9zM0DbIOynsOh9/w4E2Aq6JvrAgMBAAEwDQYJKoZIhvcNAQEFBQAD +gYEAnPd0JvCKQQBrm9jI6TkJKmfBa4NH0wUpMQv/bo2NWw1tA8fTQYb0S4aTep5Q +JdYctLQeE7abY1fpXFIwFY/FC0rE3alkEK+4PlCXvHGTYMiq90oH0JtlEqYTdTWJ +i99gtHarMEfzejyY3VDa2XFGmZrQCP6Co5NGDjAEr2A4ECg= +-----END CERTIFICATE----- diff --git a/node_modules/supertest/test/fixtures/test_key.pem b/node_modules/supertest/test/fixtures/test_key.pem new file mode 100644 index 0000000..dc4cb72 --- /dev/null +++ b/node_modules/supertest/test/fixtures/test_key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQCzhLXIZCgSvFk6sF0dgKL9pnNPooMkExm8QQ0sslCxz4nnDKjg +R7OW1eAy9aXP9NYSyiKeE9o9ijU05nor67Snd8DEC+wPiIMqnZnqkYvfKWFMpRWa +x8W/SosJu5qR2p6HZoJ008zpbhKYvyvYfczNA2yDsp7Doff8OBNgKuib6wIDAQAB +AoGAAp2tdHUZLGS4PCWzxalJNr8FMSTiGlV464hbI8qZaG3oyYgisdn5oPoO4U85 +ElW0BOQTKxCI/pqT+ehd4WP25u+RXBqOSfpIRQvY2RjXmeyrkDEZWATP/BUa/Oqa +0YitEsAXvt3pQli+LVc9GZSFZQECgwDVdAs4n7DdQlkLwIECQQDmFL9rIE/6wF3h +fJkvPFs67MJgMF/T4omLnv/FGSH7KBpjFHts9AbPIGjD1dadRpmHxk7ahbSTKMxu +uoZ1R1irAkEAx73MW4fJDQZDdJHwskYyGXuL99Fcr8xz6YZv75tm5O3eF2a/UvoO +UIgDGpTIWFrm+gli27p3J0rJhhOiI4JJwQJAYOjUR3bwuRlVcahdjTvK4WLf7Evz +0PdWH+z0pjwTyAn4M0tpQVb3lz57YiErqEsYV8v7Yqd2i5VfpjQCdlt6yQJBAIpm +7kph/SLEO0tzsGenEiHsJKFT9bhun8ape7h4YsSwOdrXPC0fzXlptVTe0S+/1Rpe +FJ0SSGv2e0snIYsfRUECQQCP8VOp3IIE8beytDoqn3QbWvobx94NVhHKUX5UB6C+ +bhY0LpTTFb8VMfSkICZXhbpcKf5zIdRjOh0ZLDeZJl5v +-----END RSA PRIVATE KEY----- diff --git a/node_modules/supertest/test/supertest.js b/node_modules/supertest/test/supertest.js new file mode 100644 index 0000000..517412d --- /dev/null +++ b/node_modules/supertest/test/supertest.js @@ -0,0 +1,1055 @@ + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +var request = require('..') + , https = require('https') + , fs = require('fs') + , path = require('path') + , should = require('should') + , express = require('express'); +var bodyParser = require('body-parser') + , cookieParser = require('cookie-parser'); + +describe('request(url)', function(){ + it('should be supported', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hello'); + }); + + var s = app.listen(function(){ + var url = 'http://localhost:' + s.address().port; + request(url) + .get('/') + .expect("hello", done); + }); + }); + + describe('.end(cb)', function() { + it('should set `this` to the test object when calling cb', function(done) { + var app = express(); + + app.get('/', function(req, res){ + res.send('hello'); + }); + + var s = app.listen(function(){ + var url = 'http://localhost:' + s.address().port; + var test = request(url).get('/'); + test.end(function(err, res) { + this.should.eql(test); + done(); + }); + }); + }); + }); +}); + +describe('request(app)', function(){ + it('should fire up the app on an ephemeral port', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .end(function(err, res){ + res.status.should.equal(200); + res.text.should.equal('hey'); + done(); + }); + }); + + it('should work with an active server', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + var server = app.listen(4000, function(){ + request(server) + .get('/') + .end(function(err, res){ + res.status.should.equal(200); + res.text.should.equal('hey'); + done(); + }); + }); + }); + + it('should work with remote server', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + var server = app.listen(4001, function(){ + request('http://localhost:4001') + .get('/') + .end(function(err, res){ + res.status.should.equal(200); + res.text.should.equal('hey'); + done(); + }); + }); + }); + + it('should work with a https server', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + var fixtures = path.join(__dirname, 'fixtures'); + var server = https.createServer({ + key: fs.readFileSync(path.join(fixtures, 'test_key.pem')), + cert: fs.readFileSync(path.join(fixtures, 'test_cert.pem')) + }, app); + + request(server) + .get('/') + .end(function(err, res){ + if (err) return done(err); + res.status.should.equal(200); + res.text.should.equal('hey'); + done(); + }); + }); + + it('should work with .send() etc', function(done){ + var app = express(); + + app.use(bodyParser.json()); + + app.post('/', function(req, res){ + res.send(req.body.name); + }); + + request(app) + .post('/') + .send({ name: 'tobi' }) + .expect('tobi', done); + }); + + it('should work when unbuffered', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.end('Hello'); + }); + + request(app) + .get('/') + .expect('Hello', done); + }); + + it('should default redirects to 0', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.redirect('/login'); + }); + + request(app) + .get('/') + .expect(302, done); + }); + + it('should handle redirects', function(done){ + var app = express(); + + app.get('/login', function (req, res){ + res.end('Login') + }); + + app.get('/', function(req, res){ + res.redirect('/login'); + }); + + request(app) + .get('/') + .redirects(1) + .end(function (err, res) { + should.exist(res) + res.status.should.be.equal(200) + res.text.should.be.equal('Login') + done() + }) + }); + + it('should handle socket errors', function(done) { + var app = express(); + + app.get('/', function(req, res){ + res.destroy(); + }); + + request(app) + .get('/') + .end(function(err) { + should.exist(err); + done(); + }); + }); + + describe('.end(fn)', function(){ + it('should close server', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('supertest FTW!'); + }); + + var test = request(app) + .get('/') + .end(function(){}); + + test._server.on('close', function(){ + done(); + }); + }); + + it('should wait for server to close before invoking fn', function(done){ + var app = express(); + var closed = false; + + app.get('/', function(req, res){ + res.send('supertest FTW!'); + }); + + var test = request(app) + .get('/') + .end(function(){ + closed.should.be.true; + done(); + }); + + test._server.on('close', function(){ + closed = true; + }); + }); + + it('should support nested requests', function(done){ + var app = express(); + var test = request(app); + + app.get('/', function(req, res){ + res.send('supertest FTW!'); + }); + + test + .get('/') + .end(function(){ + test + .get('/') + .end(function(err, res){ + (err === null).should.be.true; + res.status.should.equal(200); + res.text.should.equal('supertest FTW!'); + done(); + }); + }); + }); + + it('should include the response in the error callback', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('whatever'); + }); + + request(app) + .get('/') + .expect(function() { + throw new Error('Some error'); + }) + .end(function(err, res){ + should.exist(err); + should.exist(res); + // Duck-typing response, just in case. + res.status.should.equal(200); + done(); + }); + }); + + it('should set `this` to the test object when calling the error callback', function(done) { + var app = express(); + + app.get('/', function(req, res){ + res.send('whatever'); + }); + + var test = request(app).get('/'); + test.expect(function() { + throw new Error('Some error'); + }).end(function(err, res){ + should.exist(err); + this.should.eql(test); + done(); + }); + }); + + it('should handle an undefined Response', function (done) { + var app = express(); + + app.get('/', function(req, res){ + setTimeout( function () { + res.end(); + }, 20); + }); + + var s = app.listen(function(){ + var url = 'http://localhost:' + s.address().port; + request(url) + .get('/') + .timeout(1) + .expect(200, function (err) { + err.should.be.an.instanceof(Error); + return done(); + }); + }); + }); + + it('should handle error returned when server goes down', function (done) { + var app = express(); + + app.get('/', function(req, res){ + res.end(); + }); + + var s = app.listen(function(){ + var url = 'http://localhost:' + s.address().port; + s.close(); + request(url) + .get('/') + .expect(200, function (err) { + err.should.be.an.instanceof(Error); + return done(); + }); + }); + }); + }); + + describe('.expect(status[, fn])', function(){ + it('should assert the response status', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect(404) + .end(function(err, res){ + err.message.should.equal('expected 404 "Not Found", got 200 "OK"'); + done(); + }); + }); + }); + + describe('.expect(status)', function () { + it('should assert only status', function (done) { + var app = express(); + + app.get('/', function (req, res) { + res.send('hey'); + }); + + request(app) + .get('/') + .expect(200) + .end(done) + }); + }); + + describe('.expect(status, body[, fn])', function(){ + it('should assert the response body and status', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('foo'); + }); + + request(app) + .get('/') + .expect(200, 'foo', done) + }); + + describe("when the body argument is an empty string", function() { + it("should not quietly pass on failure", function(done) { + var app = express(); + + app.get('/', function(req, res){ + res.send('foo'); + }); + + request(app) + .get('/') + .expect(200, '') + .end(function(err, res){ + err.message.should.equal('expected \'\' response body, got \'foo\''); + done(); + }); + }); + }); + }); + + describe('.expect(body[, fn])', function(){ + it('should assert the response body', function(done){ + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res){ + res.send({ foo: 'bar' }); + }); + + request(app) + .get('/') + .expect('hey') + .end(function(err, res){ + err.message.should.equal('expected \'hey\' response body, got \'{"foo":"bar"}\''); + done(); + }); + }); + + it('should assert the status before the body', function (done) { + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res){ + res.status(500).send({ message: 'something went wrong' }); + }); + + request(app) + .get('/') + .expect(200) + .expect('hey') + .end(function(err, res){ + err.message.should.equal('expected 200 \"OK"\, got 500 \"Internal Server Error\"'); + done(); + }); + }); + + it('should assert the response text', function(done){ + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res){ + res.send({ foo: 'bar' }); + }); + + request(app) + .get('/') + .expect('{"foo":"bar"}', done); + }); + + it('should assert the parsed response body', function(done){ + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res){ + res.send({ foo: 'bar' }); + }); + + request(app) + .get('/') + .expect({ foo: 'baz' }) + .end(function(err, res){ + err.message.should.equal('expected { foo: \'baz\' } response body, got { foo: \'bar\' }'); + + request(app) + .get('/') + .expect({ foo: 'bar' }) + .end(done); + }); + }); + + it('should support regular expressions', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('foobar'); + }); + + request(app) + .get('/') + .expect(/^bar/) + .end(function(err, res){ + err.message.should.equal('expected body \'foobar\' to match /^bar/'); + done(); + }); + }); + + it('should assert response body multiple times', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey tj'); + }); + + request(app) + .get('/') + .expect(/tj/) + .expect('hey') + .expect('hey tj') + .end(function (err, res) { + err.message.should.equal("expected 'hey' response body, got 'hey tj'"); + done(); + }); + }); + + it('should assert response body multiple times with no exception', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey tj'); + }); + + request(app) + .get('/') + .expect(/tj/) + .expect(/^hey/) + .expect('hey tj', done); + }); + }); + + describe('.expect(field, value[, fn])', function(){ + it('should assert the header field presence', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send({ foo: 'bar' }); + }); + + request(app) + .get('/') + .expect('Content-Foo', 'bar') + .end(function(err, res){ + err.message.should.equal('expected "Content-Foo" header field'); + done(); + }); + }); + + it('should assert the header field value', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send({ foo: 'bar' }); + }); + + request(app) + .get('/') + .expect('Content-Type', 'text/html') + .end(function(err, res){ + err.message.should.equal('expected "Content-Type" of "text/html", got "application/json; charset=utf-8"'); + done(); + }); + }); + + it('should assert multiple fields', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', 'text/html; charset=utf-8') + .expect('Content-Length', '3') + .end(done); + }); + + it('should support regular expressions', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', /^application/) + .end(function(err){ + err.message.should.equal('expected "Content-Type" matching /^application/, got "text/html; charset=utf-8"'); + done(); + }); + }); + + it('should support numbers', function(done){ + var app = express(); + + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Length', 4) + .end(function(err){ + err.message.should.equal('expected "Content-Length" of "4", got "3"'); + done(); + }); + }); + + describe('handling arbitrary expect functions', function(){ + + + var app, get; + before(function(){ + app = express(); + app.get('/', function(req, res){ + res.send('hey'); + }); + }); + + beforeEach(function(){ + get = request(app).get('/'); + }); + + it('reports errors',function(done) { + get + .expect(function(res) { + throw new Error("failed") + }) + .end(function(err) { + err.message.should.equal('failed'); + done() + }); + }); + + it('ensures truthy non-errors returned from asserts are not promoted to errors',function(done){ + get + .expect(function(res) { + return "some descriptive error"; + }) + .end(function(err) { + should.not.exist(err); + done() + }); + }); + + it('ensures truthy errors returned from asserts are throw to end',function(done){ + get + .expect(function(res) { + return new Error("some descriptive error"); + }) + .end(function(err) { + err.message.should.equal("some descriptive error"); + (err instanceof Error).should.be.true; + done(); + }); + }); + + it("doesn't create false negatives", function(done){ + get + .expect(function(res) {}) + .end(done); + }); + + it("handles multiple asserts", function(done){ + var calls = []; + get + .expect(function(res) { calls[0] = 1 }) + .expect(function(res) { calls[1] = 1 }) + .expect(function(res) { calls[2] = 1 }) + .end(function() { + var callCount = [0,1,2].reduce(function(count,i) { + return count + calls[i] + },0); + callCount.should.equal(3,"didn't see all assertions run"); + done(); + }); + }); + + it("plays well with normal assertions - no false positives", function(done){ + get + .expect(function(res) {}) + .expect('Content-Type', /json/) + .end(function(err) { + err.message.should.match(/Content-Type/); + done(); + }); + }); + + it("plays well with normal assertions - no false negatives", function(done){ + get + .expect(function(res) {}) + .expect('Content-Type', /html/) + .expect(function(res) {}) + .expect('Content-Type', /text/) + .end(done) + }); + }); + + describe('handling multiple assertions per field', function(){ + + it('should work', function(done){ + var app = express(); + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', /text/) + .expect('Content-Type', /html/) + .end(done); + }); + + it('should return an error if the first one fails', function(done){ + var app = express(); + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', /bloop/) + .expect('Content-Type', /html/) + .end(function(err){ + err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); + done(); + }); + }); + + it('should return an error if a middle one fails', function(done){ + var app = express(); + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', /text/) + .expect('Content-Type', /bloop/) + .expect('Content-Type', /html/) + .end(function(err){ + err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); + done(); + }); + }); + + it('should return an error if the last one fails', function(done){ + var app = express(); + app.get('/', function(req, res){ + res.send('hey'); + }); + + request(app) + .get('/') + .expect('Content-Type', /text/) + .expect('Content-Type', /html/) + .expect('Content-Type', /bloop/) + .end(function(err){ + err.message.should.equal('expected "Content-Type" matching /bloop/, got "text/html; charset=utf-8"'); + done(); + }); + }); + }); + }); +}); + +describe('request.agent(app)', function(){ + var app = express(); + + app.use(cookieParser()); + + app.get('/', function(req, res){ + res.cookie('cookie', 'hey'); + res.send(); + }); + + app.get('/return', function(req, res){ + if (req.cookies.cookie) res.send(req.cookies.cookie); + else res.send(':(') + }); + + var agent = request.agent(app); + + it('should save cookies', function(done){ + agent + .get('/') + .expect('set-cookie', 'cookie=hey; Path=/', done); + }); + + it('should send cookies', function(done){ + agent + .get('/return') + .expect('hey', done); + }); +}); + +describe(".<http verb> works as expected", function(){ + it(".delete should work", function (done){ + var app = express(); + app.delete('/', function(req, res){ + res.sendStatus(200); + }); + + request(app) + .delete('/') + .expect(200, done); + }); + it(".del should work", function (done){ + var app = express(); + app.delete('/', function(req, res){ + res.sendStatus(200); + }); + + request(app) + .del('/') + .expect(200, done); + }); + it(".get should work", function (done){ + var app = express(); + app.get('/', function(req, res){ + res.sendStatus(200); + }); + + request(app) + .get('/') + .expect(200, done); + }); + it(".post should work", function (done){ + var app = express(); + app.post('/', function(req, res){ + res.sendStatus(200); + }); + + request(app) + .post('/') + .expect(200, done); + }); + it(".put should work", function (done){ + var app = express(); + app.put('/', function(req, res){ + res.sendStatus(200); + }); + + request(app) + .put('/') + .expect(200, done); + }); +}); + +describe('assert ordering by call order', function() { + it('should assert the body before status', function(done) { + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res) { + res.status(500).json({message: 'something went wrong'}); + }); + + request(app) + .get('/') + .expect('hey') + .expect(200) + .end(function(err, res) { + err.message.should.equal('expected \'hey\' response body, got \'{"message":"something went wrong"}\''); + done(); + }); + }); + + it('should assert the status before body', function(done) { + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res) { + res.status(500).json({message: 'something went wrong'}); + }); + + request(app) + .get('/') + .expect(200) + .expect('hey') + .end(function(err, res) { + err.message.should.equal('expected 200 "OK", got 500 "Internal Server Error"'); + done(); + }); + }); + + it('should assert the fields before body and status', function(done) { + var app = express(); + + app.set('json spaces', 0); + + app.get('/', function(req, res) { + res.status(200).json({hello: 'world'}); + }); + + request(app) + .get('/') + .expect('content-type', /html/) + .expect('hello') + .end(function(err, res) { + err.message.should.equal('expected "content-type" matching /html/, got "application/json; charset=utf-8"'); + done(); + }); + }); + + it('should call the expect function in order', function(done) { + var app = express(); + + app.get('/', function(req, res) { + res.status(200).json({}); + }); + + request(app) + .get('/') + .expect(function(res) { + res.body.first = 1; + }) + .expect(function(res) { + (res.body.first === 1).should.be.true; + res.body.second = 2; + }) + .end(function(err, res) { + if (err) return done(err); + (res.body.first === 1).should.be.true; + (res.body.second === 2).should.be.true; + done(); + }); + }); + + it('should call expect(fn) and expect(status, fn) in order', function(done) { + var app = express(); + + app.get('/', function(req, res) { + res.status(200).json({}); + }); + + request(app) + .get('/') + .expect(function(res) { + res.body.first = 1; + }) + .expect(200, function(err, res) { + (err === null).should.be.true; + (res.body.first === 1).should.be.true; + done(); + }); + }); + + it('should call expect(fn) and expect(header,value) in order', function(done) { + var app = express(); + + app.get('/', function(req, res) { + res + .set('X-Some-Header', 'Some value') + .send(); + }); + + request(app) + .get('/') + .expect('X-Some-Header', 'Some value') + .expect(function(res) { + res.headers['x-some-header'] = ''; + }) + .expect('X-Some-Header', '') + .end(done); + }); + + it('should call expect(fn) and expect(body) in order', function(done) { + var app = express(); + + app.get('/', function(req, res) { + res.json({somebody: 'some body value'}); + }); + + request(app) + .get('/') + .expect(/some body value/) + .expect(function(res) { + res.body.somebody = 'nobody'; + }) + .expect(/some body value/) // res.text should not be modified. + .expect({somebody: 'nobody'}) + .expect(function(res) { + res.text = 'gone'; + }) + .expect('gone') + .expect(/gone/) + .expect({somebody: 'nobody'}) // res.body should not be modified + .expect('gone', done); + }); +}); + +describe("request.get(url).query(vals) works as expected", function(){ + + it("normal single query string value works", function(done) { + var app = express(); + app.get('/', function(req, res){ + res.status(200).send(req.query.val); + }); + + request(app) + .get('/') + .query({val: "Test1"}) + .expect(200, function(err, res) { + res.text.should.be.equal('Test1'); + done(); + }); + }); + + it("array query string value works", function(done) { + var app = express(); + app.get('/', function(req, res){ + res.status(200).send(Array.isArray(req.query.val)); + }); + + request(app) + .get('/') + .query({'val[]': ["Test1", "Test2"]}) + .expect(200, function(err, res) { + res.req.path.should.be.equal('/?val%5B%5D=Test1&val%5B%5D=Test2'); + res.text.should.be.equal('true'); + done(); + }); + }); + + it("array query string value work even with single value", function(done) { + var app = express(); + app.get('/', function(req, res){ + res.status(200).send(Array.isArray(req.query.val)); + }); + + request(app) + .get('/') + .query({'val[]': ["Test1"]}) + .expect(200, function(err, res) { + res.req.path.should.be.equal('/?val%5B%5D=Test1'); + res.text.should.be.equal('true'); + done(); + }); + }); + + it("object query string value works", function(done) { + var app = express(); + app.get('/', function(req, res){ + res.status(200).send(req.query.val.test); + }); + + request(app) + .get('/') + .query({val: { test: 'Test1' } }) + .expect(200, function(err, res) { + res.text.should.be.equal('Test1'); + done(); + }); + }); +}); |
