| @@ -0,0 +1,65 @@ | |||
| var express = require('express'); | |||
| var formidable = require('formidable'); | |||
| var fs = require('fs'); | |||
| var spawn = require('child_process').spawn; | |||
| var app = express(); | |||
| var port = 9001; | |||
| app.listen(port, () => { | |||
| console.log("New app listening on " + port); | |||
| }); | |||
| app.use("/stitchify/stitchimg", express.static(__dirname + "/stitchimg")); | |||
| app.post("/stitchify/upload", (req, res) => { | |||
| console.log("Request to stitchify/upload"); | |||
| var form = new formidable.IncomingForm(); | |||
| form.parse(req, (err, fields, files) => { | |||
| console.log(files.infile.path); | |||
| var filepath = "/var/www/noelle.codes/node/stitchimg/" + files.infile.name; | |||
| fs.rename(files.infile.path, filepath, (err) => { | |||
| if (err) { | |||
| console.log("Oh no, err."); | |||
| res.write("<h2>Heck.</h2>"); | |||
| res.write("<p>There was a server-side error. Please hit the back button and try again.</p>"); | |||
| res.end(); | |||
| } else { | |||
| console.log("Uploaded " + files.infile.name); | |||
| var filepath = files.infile.path; | |||
| var process = spawn('python3', ["./stitchify.py",files.infile.name]); | |||
| process.stdout.on("data", (data) => { | |||
| console.log("Successfully converted " + data.toString()); | |||
| res.write("<img src='stitchimg/" + data.toString() + "'>"); | |||
| res.write("<br><br>"); | |||
| res.write("<p>(<a href='https://paypal.me/joyeusenoelle' target='_blank'>Did it work? Send me a couple bucks as a thank you!</a>)</p>"); | |||
| res.write("<p>(Or <a href='https://patreon.com/noelleanthony'>sign up for my Patreon so I can afford to stay alive and keep writing code like this!</a>)</p>"); | |||
| res.end(); | |||
| }); | |||
| } | |||
| }); | |||
| }); | |||
| }); | |||
| app.get("/stitchify", (req, res) => { | |||
| console.log("Request to stitchify"); | |||
| res.write("<h2>Stitchify!</h2>"); | |||
| res.write("<p>Turn your images into cross-stitch patterns!</p>"); | |||
| res.write("<p>At the moment, this tool supports images with up to 52 colors.More than that and it throws a tantrum.</p>"); | |||
| res.write("<form action='stitchify/upload' method='post' enctype='multipart/form-data'>"); | |||
| res.write("<input type='file' name='infile' accept='image/png, image/jpeg, image/gif'>"); | |||
| res.write("<input type='submit'>"); | |||
| res.write("</form>"); | |||
| res.write("<p>(<a href='https://paypal.me/joyeusenoelle' target='_blank'>Consider sending me a couple bucks as a thank you for writing this and keeping it running!</a>)</p>"); | |||
| res.write("<p>(Or <a href='https://patreon.com/noelleanthony'>sign up for my Patreon so I can afford to stay alive and keep writing code like this!</a>)</p>"); | |||
| res.end(); | |||
| }); | |||
| app.get("/", (req, res) => { | |||
| console.log("Generic request"); | |||
| res.write("Try going to /stitchify!"); | |||
| res.end(); | |||
| }); | |||
| @@ -0,0 +1 @@ | |||
| ../mime/cli.js | |||
| @@ -0,0 +1,236 @@ | |||
| 1.3.7 / 2019-04-29 | |||
| ================== | |||
| * deps: negotiator@0.6.2 | |||
| - Fix sorting charset, encoding, and language with extra parameters | |||
| 1.3.6 / 2019-04-28 | |||
| ================== | |||
| * deps: mime-types@~2.1.24 | |||
| - deps: mime-db@~1.40.0 | |||
| 1.3.5 / 2018-02-28 | |||
| ================== | |||
| * deps: mime-types@~2.1.18 | |||
| - deps: mime-db@~1.33.0 | |||
| 1.3.4 / 2017-08-22 | |||
| ================== | |||
| * deps: mime-types@~2.1.16 | |||
| - deps: mime-db@~1.29.0 | |||
| 1.3.3 / 2016-05-02 | |||
| ================== | |||
| * deps: mime-types@~2.1.11 | |||
| - deps: mime-db@~1.23.0 | |||
| * deps: negotiator@0.6.1 | |||
| - perf: improve `Accept` parsing speed | |||
| - perf: improve `Accept-Charset` parsing speed | |||
| - perf: improve `Accept-Encoding` parsing speed | |||
| - perf: improve `Accept-Language` parsing speed | |||
| 1.3.2 / 2016-03-08 | |||
| ================== | |||
| * deps: mime-types@~2.1.10 | |||
| - Fix extension of `application/dash+xml` | |||
| - Update primary extension for `audio/mp4` | |||
| - deps: mime-db@~1.22.0 | |||
| 1.3.1 / 2016-01-19 | |||
| ================== | |||
| * deps: mime-types@~2.1.9 | |||
| - deps: mime-db@~1.21.0 | |||
| 1.3.0 / 2015-09-29 | |||
| ================== | |||
| * deps: mime-types@~2.1.7 | |||
| - deps: mime-db@~1.19.0 | |||
| * deps: negotiator@0.6.0 | |||
| - Fix including type extensions in parameters in `Accept` parsing | |||
| - Fix parsing `Accept` parameters with quoted equals | |||
| - Fix parsing `Accept` parameters with quoted semicolons | |||
| - Lazy-load modules from main entry point | |||
| - perf: delay type concatenation until needed | |||
| - perf: enable strict mode | |||
| - perf: hoist regular expressions | |||
| - perf: remove closures getting spec properties | |||
| - perf: remove a closure from media type parsing | |||
| - perf: remove property delete from media type parsing | |||
| 1.2.13 / 2015-09-06 | |||
| =================== | |||
| * deps: mime-types@~2.1.6 | |||
| - deps: mime-db@~1.18.0 | |||
| 1.2.12 / 2015-07-30 | |||
| =================== | |||
| * deps: mime-types@~2.1.4 | |||
| - deps: mime-db@~1.16.0 | |||
| 1.2.11 / 2015-07-16 | |||
| =================== | |||
| * deps: mime-types@~2.1.3 | |||
| - deps: mime-db@~1.15.0 | |||
| 1.2.10 / 2015-07-01 | |||
| =================== | |||
| * deps: mime-types@~2.1.2 | |||
| - deps: mime-db@~1.14.0 | |||
| 1.2.9 / 2015-06-08 | |||
| ================== | |||
| * deps: mime-types@~2.1.1 | |||
| - perf: fix deopt during mapping | |||
| 1.2.8 / 2015-06-07 | |||
| ================== | |||
| * deps: mime-types@~2.1.0 | |||
| - deps: mime-db@~1.13.0 | |||
| * perf: avoid argument reassignment & argument slice | |||
| * perf: avoid negotiator recursive construction | |||
| * perf: enable strict mode | |||
| * perf: remove unnecessary bitwise operator | |||
| 1.2.7 / 2015-05-10 | |||
| ================== | |||
| * deps: negotiator@0.5.3 | |||
| - Fix media type parameter matching to be case-insensitive | |||
| 1.2.6 / 2015-05-07 | |||
| ================== | |||
| * deps: mime-types@~2.0.11 | |||
| - deps: mime-db@~1.9.1 | |||
| * deps: negotiator@0.5.2 | |||
| - Fix comparing media types with quoted values | |||
| - Fix splitting media types with quoted commas | |||
| 1.2.5 / 2015-03-13 | |||
| ================== | |||
| * deps: mime-types@~2.0.10 | |||
| - deps: mime-db@~1.8.0 | |||
| 1.2.4 / 2015-02-14 | |||
| ================== | |||
| * Support Node.js 0.6 | |||
| * deps: mime-types@~2.0.9 | |||
| - deps: mime-db@~1.7.0 | |||
| * deps: negotiator@0.5.1 | |||
| - Fix preference sorting to be stable for long acceptable lists | |||
| 1.2.3 / 2015-01-31 | |||
| ================== | |||
| * deps: mime-types@~2.0.8 | |||
| - deps: mime-db@~1.6.0 | |||
| 1.2.2 / 2014-12-30 | |||
| ================== | |||
| * deps: mime-types@~2.0.7 | |||
| - deps: mime-db@~1.5.0 | |||
| 1.2.1 / 2014-12-30 | |||
| ================== | |||
| * deps: mime-types@~2.0.5 | |||
| - deps: mime-db@~1.3.1 | |||
| 1.2.0 / 2014-12-19 | |||
| ================== | |||
| * deps: negotiator@0.5.0 | |||
| - Fix list return order when large accepted list | |||
| - Fix missing identity encoding when q=0 exists | |||
| - Remove dynamic building of Negotiator class | |||
| 1.1.4 / 2014-12-10 | |||
| ================== | |||
| * deps: mime-types@~2.0.4 | |||
| - deps: mime-db@~1.3.0 | |||
| 1.1.3 / 2014-11-09 | |||
| ================== | |||
| * deps: mime-types@~2.0.3 | |||
| - deps: mime-db@~1.2.0 | |||
| 1.1.2 / 2014-10-14 | |||
| ================== | |||
| * deps: negotiator@0.4.9 | |||
| - Fix error when media type has invalid parameter | |||
| 1.1.1 / 2014-09-28 | |||
| ================== | |||
| * deps: mime-types@~2.0.2 | |||
| - deps: mime-db@~1.1.0 | |||
| * deps: negotiator@0.4.8 | |||
| - Fix all negotiations to be case-insensitive | |||
| - Stable sort preferences of same quality according to client order | |||
| 1.1.0 / 2014-09-02 | |||
| ================== | |||
| * update `mime-types` | |||
| 1.0.7 / 2014-07-04 | |||
| ================== | |||
| * Fix wrong type returned from `type` when match after unknown extension | |||
| 1.0.6 / 2014-06-24 | |||
| ================== | |||
| * deps: negotiator@0.4.7 | |||
| 1.0.5 / 2014-06-20 | |||
| ================== | |||
| * fix crash when unknown extension given | |||
| 1.0.4 / 2014-06-19 | |||
| ================== | |||
| * use `mime-types` | |||
| 1.0.3 / 2014-06-11 | |||
| ================== | |||
| * deps: negotiator@0.4.6 | |||
| - Order by specificity when quality is the same | |||
| 1.0.2 / 2014-05-29 | |||
| ================== | |||
| * Fix interpretation when header not in request | |||
| * deps: pin negotiator@0.4.5 | |||
| 1.0.1 / 2014-01-18 | |||
| ================== | |||
| * Identity encoding isn't always acceptable | |||
| * deps: negotiator@~0.4.0 | |||
| 1.0.0 / 2013-12-27 | |||
| ================== | |||
| * Genesis | |||
| @@ -0,0 +1,23 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | |||
| Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.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. | |||
| @@ -0,0 +1,142 @@ | |||
| # accepts | |||
| [![NPM Version][npm-version-image]][npm-url] | |||
| [![NPM Downloads][npm-downloads-image]][npm-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). | |||
| Extracted from [koa](https://www.npmjs.com/package/koa) for general use. | |||
| In addition to negotiator, it allows: | |||
| - Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` | |||
| as well as `('text/html', 'application/json')`. | |||
| - Allows type shorthands such as `json`. | |||
| - Returns `false` when no types match | |||
| - Treats non-existent headers as `*` | |||
| ## Installation | |||
| This is a [Node.js](https://nodejs.org/en/) module available through the | |||
| [npm registry](https://www.npmjs.com/). Installation is done using the | |||
| [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | |||
| ```sh | |||
| $ npm install accepts | |||
| ``` | |||
| ## API | |||
| <!-- eslint-disable no-unused-vars --> | |||
| ```js | |||
| var accepts = require('accepts') | |||
| ``` | |||
| ### accepts(req) | |||
| Create a new `Accepts` object for the given `req`. | |||
| #### .charset(charsets) | |||
| Return the first accepted charset. If nothing in `charsets` is accepted, | |||
| then `false` is returned. | |||
| #### .charsets() | |||
| Return the charsets that the request accepts, in the order of the client's | |||
| preference (most preferred first). | |||
| #### .encoding(encodings) | |||
| Return the first accepted encoding. If nothing in `encodings` is accepted, | |||
| then `false` is returned. | |||
| #### .encodings() | |||
| Return the encodings that the request accepts, in the order of the client's | |||
| preference (most preferred first). | |||
| #### .language(languages) | |||
| Return the first accepted language. If nothing in `languages` is accepted, | |||
| then `false` is returned. | |||
| #### .languages() | |||
| Return the languages that the request accepts, in the order of the client's | |||
| preference (most preferred first). | |||
| #### .type(types) | |||
| Return the first accepted type (and it is returned as the same text as what | |||
| appears in the `types` array). If nothing in `types` is accepted, then `false` | |||
| is returned. | |||
| The `types` array can contain full MIME types or file extensions. Any value | |||
| that is not a full MIME types is passed to `require('mime-types').lookup`. | |||
| #### .types() | |||
| Return the types that the request accepts, in the order of the client's | |||
| preference (most preferred first). | |||
| ## Examples | |||
| ### Simple type negotiation | |||
| This simple example shows how to use `accepts` to return a different typed | |||
| respond body based on what the client wants to accept. The server lists it's | |||
| preferences in order and will get back the best match between the client and | |||
| server. | |||
| ```js | |||
| var accepts = require('accepts') | |||
| var http = require('http') | |||
| function app (req, res) { | |||
| var accept = accepts(req) | |||
| // the order of this list is significant; should be server preferred order | |||
| switch (accept.type(['json', 'html'])) { | |||
| case 'json': | |||
| res.setHeader('Content-Type', 'application/json') | |||
| res.write('{"hello":"world!"}') | |||
| break | |||
| case 'html': | |||
| res.setHeader('Content-Type', 'text/html') | |||
| res.write('<b>hello, world!</b>') | |||
| break | |||
| default: | |||
| // the fallback is text/plain, so no need to specify it above | |||
| res.setHeader('Content-Type', 'text/plain') | |||
| res.write('hello, world!') | |||
| break | |||
| } | |||
| res.end() | |||
| } | |||
| http.createServer(app).listen(3000) | |||
| ``` | |||
| You can test this out with the cURL program: | |||
| ```sh | |||
| curl -I -H'Accept: text/html' http://localhost:3000/ | |||
| ``` | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master | |||
| [coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master | |||
| [node-version-image]: https://badgen.net/npm/node/accepts | |||
| [node-version-url]: https://nodejs.org/en/download | |||
| [npm-downloads-image]: https://badgen.net/npm/dm/accepts | |||
| [npm-url]: https://npmjs.org/package/accepts | |||
| [npm-version-image]: https://badgen.net/npm/v/accepts | |||
| [travis-image]: https://badgen.net/travis/jshttp/accepts/master | |||
| [travis-url]: https://travis-ci.org/jshttp/accepts | |||
| @@ -0,0 +1,238 @@ | |||
| /*! | |||
| * accepts | |||
| * Copyright(c) 2014 Jonathan Ong | |||
| * Copyright(c) 2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var Negotiator = require('negotiator') | |||
| var mime = require('mime-types') | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = Accepts | |||
| /** | |||
| * Create a new Accepts object for the given req. | |||
| * | |||
| * @param {object} req | |||
| * @public | |||
| */ | |||
| function Accepts (req) { | |||
| if (!(this instanceof Accepts)) { | |||
| return new Accepts(req) | |||
| } | |||
| this.headers = req.headers | |||
| this.negotiator = new Negotiator(req) | |||
| } | |||
| /** | |||
| * Check if the given `type(s)` is acceptable, returning | |||
| * the best match when true, otherwise `undefined`, in which | |||
| * case you should respond with 406 "Not Acceptable". | |||
| * | |||
| * The `type` value may be a single mime type string | |||
| * such as "application/json", the extension name | |||
| * such as "json" or an array `["json", "html", "text/plain"]`. When a list | |||
| * or array is given the _best_ match, if any is returned. | |||
| * | |||
| * Examples: | |||
| * | |||
| * // Accept: text/html | |||
| * this.types('html'); | |||
| * // => "html" | |||
| * | |||
| * // Accept: text/*, application/json | |||
| * this.types('html'); | |||
| * // => "html" | |||
| * this.types('text/html'); | |||
| * // => "text/html" | |||
| * this.types('json', 'text'); | |||
| * // => "json" | |||
| * this.types('application/json'); | |||
| * // => "application/json" | |||
| * | |||
| * // Accept: text/*, application/json | |||
| * this.types('image/png'); | |||
| * this.types('png'); | |||
| * // => undefined | |||
| * | |||
| * // Accept: text/*;q=.5, application/json | |||
| * this.types(['html', 'json']); | |||
| * this.types('html', 'json'); | |||
| * // => "json" | |||
| * | |||
| * @param {String|Array} types... | |||
| * @return {String|Array|Boolean} | |||
| * @public | |||
| */ | |||
| Accepts.prototype.type = | |||
| Accepts.prototype.types = function (types_) { | |||
| var types = types_ | |||
| // support flattened arguments | |||
| if (types && !Array.isArray(types)) { | |||
| types = new Array(arguments.length) | |||
| for (var i = 0; i < types.length; i++) { | |||
| types[i] = arguments[i] | |||
| } | |||
| } | |||
| // no types, return all requested types | |||
| if (!types || types.length === 0) { | |||
| return this.negotiator.mediaTypes() | |||
| } | |||
| // no accept header, return first given type | |||
| if (!this.headers.accept) { | |||
| return types[0] | |||
| } | |||
| var mimes = types.map(extToMime) | |||
| var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) | |||
| var first = accepts[0] | |||
| return first | |||
| ? types[mimes.indexOf(first)] | |||
| : false | |||
| } | |||
| /** | |||
| * Return accepted encodings or best fit based on `encodings`. | |||
| * | |||
| * Given `Accept-Encoding: gzip, deflate` | |||
| * an array sorted by quality is returned: | |||
| * | |||
| * ['gzip', 'deflate'] | |||
| * | |||
| * @param {String|Array} encodings... | |||
| * @return {String|Array} | |||
| * @public | |||
| */ | |||
| Accepts.prototype.encoding = | |||
| Accepts.prototype.encodings = function (encodings_) { | |||
| var encodings = encodings_ | |||
| // support flattened arguments | |||
| if (encodings && !Array.isArray(encodings)) { | |||
| encodings = new Array(arguments.length) | |||
| for (var i = 0; i < encodings.length; i++) { | |||
| encodings[i] = arguments[i] | |||
| } | |||
| } | |||
| // no encodings, return all requested encodings | |||
| if (!encodings || encodings.length === 0) { | |||
| return this.negotiator.encodings() | |||
| } | |||
| return this.negotiator.encodings(encodings)[0] || false | |||
| } | |||
| /** | |||
| * Return accepted charsets or best fit based on `charsets`. | |||
| * | |||
| * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` | |||
| * an array sorted by quality is returned: | |||
| * | |||
| * ['utf-8', 'utf-7', 'iso-8859-1'] | |||
| * | |||
| * @param {String|Array} charsets... | |||
| * @return {String|Array} | |||
| * @public | |||
| */ | |||
| Accepts.prototype.charset = | |||
| Accepts.prototype.charsets = function (charsets_) { | |||
| var charsets = charsets_ | |||
| // support flattened arguments | |||
| if (charsets && !Array.isArray(charsets)) { | |||
| charsets = new Array(arguments.length) | |||
| for (var i = 0; i < charsets.length; i++) { | |||
| charsets[i] = arguments[i] | |||
| } | |||
| } | |||
| // no charsets, return all requested charsets | |||
| if (!charsets || charsets.length === 0) { | |||
| return this.negotiator.charsets() | |||
| } | |||
| return this.negotiator.charsets(charsets)[0] || false | |||
| } | |||
| /** | |||
| * Return accepted languages or best fit based on `langs`. | |||
| * | |||
| * Given `Accept-Language: en;q=0.8, es, pt` | |||
| * an array sorted by quality is returned: | |||
| * | |||
| * ['es', 'pt', 'en'] | |||
| * | |||
| * @param {String|Array} langs... | |||
| * @return {Array|String} | |||
| * @public | |||
| */ | |||
| Accepts.prototype.lang = | |||
| Accepts.prototype.langs = | |||
| Accepts.prototype.language = | |||
| Accepts.prototype.languages = function (languages_) { | |||
| var languages = languages_ | |||
| // support flattened arguments | |||
| if (languages && !Array.isArray(languages)) { | |||
| languages = new Array(arguments.length) | |||
| for (var i = 0; i < languages.length; i++) { | |||
| languages[i] = arguments[i] | |||
| } | |||
| } | |||
| // no languages, return all requested languages | |||
| if (!languages || languages.length === 0) { | |||
| return this.negotiator.languages() | |||
| } | |||
| return this.negotiator.languages(languages)[0] || false | |||
| } | |||
| /** | |||
| * Convert extnames to mime. | |||
| * | |||
| * @param {String} type | |||
| * @return {String} | |||
| * @private | |||
| */ | |||
| function extToMime (type) { | |||
| return type.indexOf('/') === -1 | |||
| ? mime.lookup(type) | |||
| : type | |||
| } | |||
| /** | |||
| * Check if mime is valid. | |||
| * | |||
| * @param {String} type | |||
| * @return {String} | |||
| * @private | |||
| */ | |||
| function validMime (type) { | |||
| return typeof type === 'string' | |||
| } | |||
| @@ -0,0 +1,113 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "accepts@~1.3.7", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "accepts@>=1.3.7 <1.4.0", | |||
| "_hasShrinkwrap": false, | |||
| "_id": "accepts@1.3.7", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/accepts", | |||
| "_nodeVersion": "8.16.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/accepts_1.3.7_1556595662948_0.6750107293886682" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "6.4.1", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "accepts", | |||
| "raw": "accepts@~1.3.7", | |||
| "rawSpec": "~1.3.7", | |||
| "scope": null, | |||
| "spec": ">=1.3.7 <1.4.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", | |||
| "_shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd", | |||
| "_shrinkwrap": null, | |||
| "_spec": "accepts@~1.3.7", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "bugs": { | |||
| "url": "https://github.com/jshttp/accepts/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| }, | |||
| { | |||
| "name": "Jonathan Ong", | |||
| "email": "me@jongleberry.com", | |||
| "url": "http://jongleberry.com" | |||
| } | |||
| ], | |||
| "dependencies": { | |||
| "mime-types": "~2.1.24", | |||
| "negotiator": "0.6.2" | |||
| }, | |||
| "description": "Higher-level content negotiation", | |||
| "devDependencies": { | |||
| "deep-equal": "1.0.1", | |||
| "eslint": "5.16.0", | |||
| "eslint-config-standard": "12.0.0", | |||
| "eslint-plugin-import": "2.17.2", | |||
| "eslint-plugin-markdown": "1.0.0", | |||
| "eslint-plugin-node": "8.0.1", | |||
| "eslint-plugin-promise": "4.1.1", | |||
| "eslint-plugin-standard": "4.0.0", | |||
| "mocha": "6.1.4", | |||
| "nyc": "14.0.0" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "fileCount": 5, | |||
| "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", | |||
| "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcx8PPCRA9TVsSAnZWagAAM+kP/jPydIHPrA4TftraRNde\nnxojlC9prOP0Sn9FxBvevf3S9zBFEa2sa5fVUP4LUkNmG57fcmroDAaXnllW\nof8elLx8Al27QtOUi5lZ36AZAJ/aYHtGcTPnLjZejZOido1Mi2h8em/4Rk7M\nK/1RhYxG48u6B1Q/ZPXyJ23r95/PqfBhzAmaAKUfYBrcCMU/WT1SPS6DLCKv\nQZ6Oj9DFFlK7R+L15vRG7U1qmyMjkOVgK+oaNev7fpR0qVtc92xhfomgfrSK\ngqTrj05bKu4KIpJwH/T5GieWE2w7s42Q5TlmgWh/OMJNUFs9rltoe9tyetJE\nJcpTPFysR2lX5DS3YYwjgyguy515sseGMOIts0+92oE53OCKIC0FzE3IbPQw\nmXQCsUXK2IR+p3JwpIUz0oMswN4JDZ4I+BLNIy6LLibTiWw12NKdg1BWK/Yw\nJqZ5cyUW+45S3i82slyGttRABPS6WXq3CU5SqVp8+EUnwKqMceglw/b9dLfk\n0OiaPGGqUU48012PNNkqu1ERWqbb0JaGAlSrmaQRofGnceuAXvv2lCvAdhyc\n1hD32bl54Xox1ejJMCihiFJQCEOpTXrIEfXUEbyJFzSIZwaCW2uIP1OkYs9W\nPLWCaBiMcE12foiMMqv0cO1QrLYRyW1OPPttUhQoxbk//uKTMlrKPUjZM5PE\nR3Kk\r\n=HEy7\r\n-----END PGP SIGNATURE-----\r\n", | |||
| "shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd", | |||
| "tarball": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", | |||
| "unpackedSize": 16646 | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "gitHead": "2a6e060aebb52813fdb074e9e7f66da1cfa61902", | |||
| "homepage": "https://github.com/jshttp/accepts#readme", | |||
| "keywords": [ | |||
| "accept", | |||
| "accepts", | |||
| "content", | |||
| "negotiation" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "accepts", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jshttp/accepts.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --reporter spec --check-leaks --bail test/", | |||
| "test-cov": "nyc --reporter=html --reporter=text npm test", | |||
| "test-travis": "nyc --reporter=text npm test" | |||
| }, | |||
| "version": "1.3.7" | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2014 Blake Embrey (hello@blakeembrey.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. | |||
| @@ -0,0 +1,43 @@ | |||
| # Array Flatten | |||
| [![NPM version][npm-image]][npm-url] | |||
| [![NPM downloads][downloads-image]][downloads-url] | |||
| [![Build status][travis-image]][travis-url] | |||
| [![Test coverage][coveralls-image]][coveralls-url] | |||
| > Flatten an array of nested arrays into a single flat array. Accepts an optional depth. | |||
| ## Installation | |||
| ``` | |||
| npm install array-flatten --save | |||
| ``` | |||
| ## Usage | |||
| ```javascript | |||
| var flatten = require('array-flatten') | |||
| flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) | |||
| //=> [1, 2, 3, 4, 5, 6, 7, 8, 9] | |||
| flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) | |||
| //=> [1, 2, 3, [4, [5], 6], 7, 8, 9] | |||
| (function () { | |||
| flatten(arguments) //=> [1, 2, 3] | |||
| })(1, [2, 3]) | |||
| ``` | |||
| ## License | |||
| MIT | |||
| [npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat | |||
| [npm-url]: https://npmjs.org/package/array-flatten | |||
| [downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat | |||
| [downloads-url]: https://npmjs.org/package/array-flatten | |||
| [travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat | |||
| [travis-url]: https://travis-ci.org/blakeembrey/array-flatten | |||
| [coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat | |||
| [coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master | |||
| @@ -0,0 +1,64 @@ | |||
| 'use strict' | |||
| /** | |||
| * Expose `arrayFlatten`. | |||
| */ | |||
| module.exports = arrayFlatten | |||
| /** | |||
| * Recursive flatten function with depth. | |||
| * | |||
| * @param {Array} array | |||
| * @param {Array} result | |||
| * @param {Number} depth | |||
| * @return {Array} | |||
| */ | |||
| function flattenWithDepth (array, result, depth) { | |||
| for (var i = 0; i < array.length; i++) { | |||
| var value = array[i] | |||
| if (depth > 0 && Array.isArray(value)) { | |||
| flattenWithDepth(value, result, depth - 1) | |||
| } else { | |||
| result.push(value) | |||
| } | |||
| } | |||
| return result | |||
| } | |||
| /** | |||
| * Recursive flatten function. Omitting depth is slightly faster. | |||
| * | |||
| * @param {Array} array | |||
| * @param {Array} result | |||
| * @return {Array} | |||
| */ | |||
| function flattenForever (array, result) { | |||
| for (var i = 0; i < array.length; i++) { | |||
| var value = array[i] | |||
| if (Array.isArray(value)) { | |||
| flattenForever(value, result) | |||
| } else { | |||
| result.push(value) | |||
| } | |||
| } | |||
| return result | |||
| } | |||
| /** | |||
| * Flatten an array, with the ability to define a depth. | |||
| * | |||
| * @param {Array} array | |||
| * @param {Number} depth | |||
| * @return {Array} | |||
| */ | |||
| function arrayFlatten (array, depth) { | |||
| if (depth == null) { | |||
| return flattenForever(array, []) | |||
| } | |||
| return flattenWithDepth(array, [], depth) | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "array-flatten@1.1.1", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "array-flatten@1.1.1", | |||
| "_id": "array-flatten@1.1.1", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/array-flatten", | |||
| "_nodeVersion": "2.3.3", | |||
| "_npmUser": { | |||
| "email": "hello@blakeembrey.com", | |||
| "name": "blakeembrey" | |||
| }, | |||
| "_npmVersion": "2.11.3", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "array-flatten", | |||
| "raw": "array-flatten@1.1.1", | |||
| "rawSpec": "1.1.1", | |||
| "scope": null, | |||
| "spec": "1.1.1", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", | |||
| "_shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", | |||
| "_shrinkwrap": null, | |||
| "_spec": "array-flatten@1.1.1", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "hello@blakeembrey.com", | |||
| "name": "Blake Embrey", | |||
| "url": "http://blakeembrey.me" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/blakeembrey/array-flatten/issues" | |||
| }, | |||
| "dependencies": {}, | |||
| "description": "Flatten an array of nested arrays into a single flat array", | |||
| "devDependencies": { | |||
| "istanbul": "^0.3.13", | |||
| "mocha": "^2.2.4", | |||
| "pre-commit": "^1.0.7", | |||
| "standard": "^3.7.3" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", | |||
| "tarball": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" | |||
| }, | |||
| "files": [ | |||
| "LICENSE", | |||
| "array-flatten.js" | |||
| ], | |||
| "gitHead": "1963a9189229d408e1e8f585a00c8be9edbd1803", | |||
| "homepage": "https://github.com/blakeembrey/array-flatten", | |||
| "keywords": [ | |||
| "arguments", | |||
| "array", | |||
| "depth", | |||
| "flatten" | |||
| ], | |||
| "license": "MIT", | |||
| "main": "array-flatten.js", | |||
| "maintainers": [ | |||
| { | |||
| "name": "blakeembrey", | |||
| "email": "hello@blakeembrey.com" | |||
| } | |||
| ], | |||
| "name": "array-flatten", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/blakeembrey/array-flatten.git" | |||
| }, | |||
| "scripts": { | |||
| "test": "istanbul cover _mocha -- -R spec" | |||
| }, | |||
| "version": "1.1.1" | |||
| } | |||
| @@ -0,0 +1,609 @@ | |||
| 1.19.0 / 2019-04-25 | |||
| =================== | |||
| * deps: bytes@3.1.0 | |||
| - Add petabyte (`pb`) support | |||
| * deps: http-errors@1.7.2 | |||
| - Set constructor name when possible | |||
| - deps: setprototypeof@1.1.1 | |||
| - deps: statuses@'>= 1.5.0 < 2' | |||
| * deps: iconv-lite@0.4.24 | |||
| - Added encoding MIK | |||
| * deps: qs@6.7.0 | |||
| - Fix parsing array brackets after index | |||
| * deps: raw-body@2.4.0 | |||
| - deps: bytes@3.1.0 | |||
| - deps: http-errors@1.7.2 | |||
| - deps: iconv-lite@0.4.24 | |||
| * deps: type-is@~1.6.17 | |||
| - deps: mime-types@~2.1.24 | |||
| - perf: prevent internal `throw` on invalid type | |||
| 1.18.3 / 2018-05-14 | |||
| =================== | |||
| * Fix stack trace for strict json parse error | |||
| * deps: depd@~1.1.2 | |||
| - perf: remove argument reassignment | |||
| * deps: http-errors@~1.6.3 | |||
| - deps: depd@~1.1.2 | |||
| - deps: setprototypeof@1.1.0 | |||
| - deps: statuses@'>= 1.3.1 < 2' | |||
| * deps: iconv-lite@0.4.23 | |||
| - Fix loading encoding with year appended | |||
| - Fix deprecation warnings on Node.js 10+ | |||
| * deps: qs@6.5.2 | |||
| * deps: raw-body@2.3.3 | |||
| - deps: http-errors@1.6.3 | |||
| - deps: iconv-lite@0.4.23 | |||
| * deps: type-is@~1.6.16 | |||
| - deps: mime-types@~2.1.18 | |||
| 1.18.2 / 2017-09-22 | |||
| =================== | |||
| * deps: debug@2.6.9 | |||
| * perf: remove argument reassignment | |||
| 1.18.1 / 2017-09-12 | |||
| =================== | |||
| * deps: content-type@~1.0.4 | |||
| - perf: remove argument reassignment | |||
| - perf: skip parameter parsing when no parameters | |||
| * deps: iconv-lite@0.4.19 | |||
| - Fix ISO-8859-1 regression | |||
| - Update Windows-1255 | |||
| * deps: qs@6.5.1 | |||
| - Fix parsing & compacting very deep objects | |||
| * deps: raw-body@2.3.2 | |||
| - deps: iconv-lite@0.4.19 | |||
| 1.18.0 / 2017-09-08 | |||
| =================== | |||
| * Fix JSON strict violation error to match native parse error | |||
| * Include the `body` property on verify errors | |||
| * Include the `type` property on all generated errors | |||
| * Use `http-errors` to set status code on errors | |||
| * deps: bytes@3.0.0 | |||
| * deps: debug@2.6.8 | |||
| * deps: depd@~1.1.1 | |||
| - Remove unnecessary `Buffer` loading | |||
| * deps: http-errors@~1.6.2 | |||
| - deps: depd@1.1.1 | |||
| * deps: iconv-lite@0.4.18 | |||
| - Add support for React Native | |||
| - Add a warning if not loaded as utf-8 | |||
| - Fix CESU-8 decoding in Node.js 8 | |||
| - Improve speed of ISO-8859-1 encoding | |||
| * deps: qs@6.5.0 | |||
| * deps: raw-body@2.3.1 | |||
| - Use `http-errors` for standard emitted errors | |||
| - deps: bytes@3.0.0 | |||
| - deps: iconv-lite@0.4.18 | |||
| - perf: skip buffer decoding on overage chunk | |||
| * perf: prevent internal `throw` when missing charset | |||
| 1.17.2 / 2017-05-17 | |||
| =================== | |||
| * deps: debug@2.6.7 | |||
| - Fix `DEBUG_MAX_ARRAY_LENGTH` | |||
| - deps: ms@2.0.0 | |||
| * deps: type-is@~1.6.15 | |||
| - deps: mime-types@~2.1.15 | |||
| 1.17.1 / 2017-03-06 | |||
| =================== | |||
| * deps: qs@6.4.0 | |||
| - Fix regression parsing keys starting with `[` | |||
| 1.17.0 / 2017-03-01 | |||
| =================== | |||
| * deps: http-errors@~1.6.1 | |||
| - Make `message` property enumerable for `HttpError`s | |||
| - deps: setprototypeof@1.0.3 | |||
| * deps: qs@6.3.1 | |||
| - Fix compacting nested arrays | |||
| 1.16.1 / 2017-02-10 | |||
| =================== | |||
| * deps: debug@2.6.1 | |||
| - Fix deprecation messages in WebStorm and other editors | |||
| - Undeprecate `DEBUG_FD` set to `1` or `2` | |||
| 1.16.0 / 2017-01-17 | |||
| =================== | |||
| * deps: debug@2.6.0 | |||
| - Allow colors in workers | |||
| - Deprecated `DEBUG_FD` environment variable | |||
| - Fix error when running under React Native | |||
| - Use same color for same namespace | |||
| - deps: ms@0.7.2 | |||
| * deps: http-errors@~1.5.1 | |||
| - deps: inherits@2.0.3 | |||
| - deps: setprototypeof@1.0.2 | |||
| - deps: statuses@'>= 1.3.1 < 2' | |||
| * deps: iconv-lite@0.4.15 | |||
| - Added encoding MS-31J | |||
| - Added encoding MS-932 | |||
| - Added encoding MS-936 | |||
| - Added encoding MS-949 | |||
| - Added encoding MS-950 | |||
| - Fix GBK/GB18030 handling of Euro character | |||
| * deps: qs@6.2.1 | |||
| - Fix array parsing from skipping empty values | |||
| * deps: raw-body@~2.2.0 | |||
| - deps: iconv-lite@0.4.15 | |||
| * deps: type-is@~1.6.14 | |||
| - deps: mime-types@~2.1.13 | |||
| 1.15.2 / 2016-06-19 | |||
| =================== | |||
| * deps: bytes@2.4.0 | |||
| * deps: content-type@~1.0.2 | |||
| - perf: enable strict mode | |||
| * deps: http-errors@~1.5.0 | |||
| - Use `setprototypeof` module to replace `__proto__` setting | |||
| - deps: statuses@'>= 1.3.0 < 2' | |||
| - perf: enable strict mode | |||
| * deps: qs@6.2.0 | |||
| * deps: raw-body@~2.1.7 | |||
| - deps: bytes@2.4.0 | |||
| - perf: remove double-cleanup on happy path | |||
| * deps: type-is@~1.6.13 | |||
| - deps: mime-types@~2.1.11 | |||
| 1.15.1 / 2016-05-05 | |||
| =================== | |||
| * deps: bytes@2.3.0 | |||
| - Drop partial bytes on all parsed units | |||
| - Fix parsing byte string that looks like hex | |||
| * deps: raw-body@~2.1.6 | |||
| - deps: bytes@2.3.0 | |||
| * deps: type-is@~1.6.12 | |||
| - deps: mime-types@~2.1.10 | |||
| 1.15.0 / 2016-02-10 | |||
| =================== | |||
| * deps: http-errors@~1.4.0 | |||
| - Add `HttpError` export, for `err instanceof createError.HttpError` | |||
| - deps: inherits@2.0.1 | |||
| - deps: statuses@'>= 1.2.1 < 2' | |||
| * deps: qs@6.1.0 | |||
| * deps: type-is@~1.6.11 | |||
| - deps: mime-types@~2.1.9 | |||
| 1.14.2 / 2015-12-16 | |||
| =================== | |||
| * deps: bytes@2.2.0 | |||
| * deps: iconv-lite@0.4.13 | |||
| * deps: qs@5.2.0 | |||
| * deps: raw-body@~2.1.5 | |||
| - deps: bytes@2.2.0 | |||
| - deps: iconv-lite@0.4.13 | |||
| * deps: type-is@~1.6.10 | |||
| - deps: mime-types@~2.1.8 | |||
| 1.14.1 / 2015-09-27 | |||
| =================== | |||
| * Fix issue where invalid charset results in 400 when `verify` used | |||
| * deps: iconv-lite@0.4.12 | |||
| - Fix CESU-8 decoding in Node.js 4.x | |||
| * deps: raw-body@~2.1.4 | |||
| - Fix masking critical errors from `iconv-lite` | |||
| - deps: iconv-lite@0.4.12 | |||
| * deps: type-is@~1.6.9 | |||
| - deps: mime-types@~2.1.7 | |||
| 1.14.0 / 2015-09-16 | |||
| =================== | |||
| * Fix JSON strict parse error to match syntax errors | |||
| * Provide static `require` analysis in `urlencoded` parser | |||
| * deps: depd@~1.1.0 | |||
| - Support web browser loading | |||
| * deps: qs@5.1.0 | |||
| * deps: raw-body@~2.1.3 | |||
| - Fix sync callback when attaching data listener causes sync read | |||
| * deps: type-is@~1.6.8 | |||
| - Fix type error when given invalid type to match against | |||
| - deps: mime-types@~2.1.6 | |||
| 1.13.3 / 2015-07-31 | |||
| =================== | |||
| * deps: type-is@~1.6.6 | |||
| - deps: mime-types@~2.1.4 | |||
| 1.13.2 / 2015-07-05 | |||
| =================== | |||
| * deps: iconv-lite@0.4.11 | |||
| * deps: qs@4.0.0 | |||
| - Fix dropping parameters like `hasOwnProperty` | |||
| - Fix user-visible incompatibilities from 3.1.0 | |||
| - Fix various parsing edge cases | |||
| * deps: raw-body@~2.1.2 | |||
| - Fix error stack traces to skip `makeError` | |||
| - deps: iconv-lite@0.4.11 | |||
| * deps: type-is@~1.6.4 | |||
| - deps: mime-types@~2.1.2 | |||
| - perf: enable strict mode | |||
| - perf: remove argument reassignment | |||
| 1.13.1 / 2015-06-16 | |||
| =================== | |||
| * deps: qs@2.4.2 | |||
| - Downgraded from 3.1.0 because of user-visible incompatibilities | |||
| 1.13.0 / 2015-06-14 | |||
| =================== | |||
| * Add `statusCode` property on `Error`s, in addition to `status` | |||
| * Change `type` default to `application/json` for JSON parser | |||
| * Change `type` default to `application/x-www-form-urlencoded` for urlencoded parser | |||
| * Provide static `require` analysis | |||
| * Use the `http-errors` module to generate errors | |||
| * deps: bytes@2.1.0 | |||
| - Slight optimizations | |||
| * deps: iconv-lite@0.4.10 | |||
| - The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails | |||
| - Leading BOM is now removed when decoding | |||
| * deps: on-finished@~2.3.0 | |||
| - Add defined behavior for HTTP `CONNECT` requests | |||
| - Add defined behavior for HTTP `Upgrade` requests | |||
| - deps: ee-first@1.1.1 | |||
| * deps: qs@3.1.0 | |||
| - Fix dropping parameters like `hasOwnProperty` | |||
| - Fix various parsing edge cases | |||
| - Parsed object now has `null` prototype | |||
| * deps: raw-body@~2.1.1 | |||
| - Use `unpipe` module for unpiping requests | |||
| - deps: iconv-lite@0.4.10 | |||
| * deps: type-is@~1.6.3 | |||
| - deps: mime-types@~2.1.1 | |||
| - perf: reduce try block size | |||
| - perf: remove bitwise operations | |||
| * perf: enable strict mode | |||
| * perf: remove argument reassignment | |||
| * perf: remove delete call | |||
| 1.12.4 / 2015-05-10 | |||
| =================== | |||
| * deps: debug@~2.2.0 | |||
| * deps: qs@2.4.2 | |||
| - Fix allowing parameters like `constructor` | |||
| * deps: on-finished@~2.2.1 | |||
| * deps: raw-body@~2.0.1 | |||
| - Fix a false-positive when unpiping in Node.js 0.8 | |||
| - deps: bytes@2.0.1 | |||
| * deps: type-is@~1.6.2 | |||
| - deps: mime-types@~2.0.11 | |||
| 1.12.3 / 2015-04-15 | |||
| =================== | |||
| * Slight efficiency improvement when not debugging | |||
| * deps: depd@~1.0.1 | |||
| * deps: iconv-lite@0.4.8 | |||
| - Add encoding alias UNICODE-1-1-UTF-7 | |||
| * deps: raw-body@1.3.4 | |||
| - Fix hanging callback if request aborts during read | |||
| - deps: iconv-lite@0.4.8 | |||
| 1.12.2 / 2015-03-16 | |||
| =================== | |||
| * deps: qs@2.4.1 | |||
| - Fix error when parameter `hasOwnProperty` is present | |||
| 1.12.1 / 2015-03-15 | |||
| =================== | |||
| * deps: debug@~2.1.3 | |||
| - Fix high intensity foreground color for bold | |||
| - deps: ms@0.7.0 | |||
| * deps: type-is@~1.6.1 | |||
| - deps: mime-types@~2.0.10 | |||
| 1.12.0 / 2015-02-13 | |||
| =================== | |||
| * add `debug` messages | |||
| * accept a function for the `type` option | |||
| * use `content-type` to parse `Content-Type` headers | |||
| * deps: iconv-lite@0.4.7 | |||
| - Gracefully support enumerables on `Object.prototype` | |||
| * deps: raw-body@1.3.3 | |||
| - deps: iconv-lite@0.4.7 | |||
| * deps: type-is@~1.6.0 | |||
| - fix argument reassignment | |||
| - fix false-positives in `hasBody` `Transfer-Encoding` check | |||
| - support wildcard for both type and subtype (`*/*`) | |||
| - deps: mime-types@~2.0.9 | |||
| 1.11.0 / 2015-01-30 | |||
| =================== | |||
| * make internal `extended: true` depth limit infinity | |||
| * deps: type-is@~1.5.6 | |||
| - deps: mime-types@~2.0.8 | |||
| 1.10.2 / 2015-01-20 | |||
| =================== | |||
| * deps: iconv-lite@0.4.6 | |||
| - Fix rare aliases of single-byte encodings | |||
| * deps: raw-body@1.3.2 | |||
| - deps: iconv-lite@0.4.6 | |||
| 1.10.1 / 2015-01-01 | |||
| =================== | |||
| * deps: on-finished@~2.2.0 | |||
| * deps: type-is@~1.5.5 | |||
| - deps: mime-types@~2.0.7 | |||
| 1.10.0 / 2014-12-02 | |||
| =================== | |||
| * make internal `extended: true` array limit dynamic | |||
| 1.9.3 / 2014-11-21 | |||
| ================== | |||
| * deps: iconv-lite@0.4.5 | |||
| - Fix Windows-31J and X-SJIS encoding support | |||
| * deps: qs@2.3.3 | |||
| - Fix `arrayLimit` behavior | |||
| * deps: raw-body@1.3.1 | |||
| - deps: iconv-lite@0.4.5 | |||
| * deps: type-is@~1.5.3 | |||
| - deps: mime-types@~2.0.3 | |||
| 1.9.2 / 2014-10-27 | |||
| ================== | |||
| * deps: qs@2.3.2 | |||
| - Fix parsing of mixed objects and values | |||
| 1.9.1 / 2014-10-22 | |||
| ================== | |||
| * deps: on-finished@~2.1.1 | |||
| - Fix handling of pipelined requests | |||
| * deps: qs@2.3.0 | |||
| - Fix parsing of mixed implicit and explicit arrays | |||
| * deps: type-is@~1.5.2 | |||
| - deps: mime-types@~2.0.2 | |||
| 1.9.0 / 2014-09-24 | |||
| ================== | |||
| * include the charset in "unsupported charset" error message | |||
| * include the encoding in "unsupported content encoding" error message | |||
| * deps: depd@~1.0.0 | |||
| 1.8.4 / 2014-09-23 | |||
| ================== | |||
| * fix content encoding to be case-insensitive | |||
| 1.8.3 / 2014-09-19 | |||
| ================== | |||
| * deps: qs@2.2.4 | |||
| - Fix issue with object keys starting with numbers truncated | |||
| 1.8.2 / 2014-09-15 | |||
| ================== | |||
| * deps: depd@0.4.5 | |||
| 1.8.1 / 2014-09-07 | |||
| ================== | |||
| * deps: media-typer@0.3.0 | |||
| * deps: type-is@~1.5.1 | |||
| 1.8.0 / 2014-09-05 | |||
| ================== | |||
| * make empty-body-handling consistent between chunked requests | |||
| - empty `json` produces `{}` | |||
| - empty `raw` produces `new Buffer(0)` | |||
| - empty `text` produces `''` | |||
| - empty `urlencoded` produces `{}` | |||
| * deps: qs@2.2.3 | |||
| - Fix issue where first empty value in array is discarded | |||
| * deps: type-is@~1.5.0 | |||
| - fix `hasbody` to be true for `content-length: 0` | |||
| 1.7.0 / 2014-09-01 | |||
| ================== | |||
| * add `parameterLimit` option to `urlencoded` parser | |||
| * change `urlencoded` extended array limit to 100 | |||
| * respond with 413 when over `parameterLimit` in `urlencoded` | |||
| 1.6.7 / 2014-08-29 | |||
| ================== | |||
| * deps: qs@2.2.2 | |||
| - Remove unnecessary cloning | |||
| 1.6.6 / 2014-08-27 | |||
| ================== | |||
| * deps: qs@2.2.0 | |||
| - Array parsing fix | |||
| - Performance improvements | |||
| 1.6.5 / 2014-08-16 | |||
| ================== | |||
| * deps: on-finished@2.1.0 | |||
| 1.6.4 / 2014-08-14 | |||
| ================== | |||
| * deps: qs@1.2.2 | |||
| 1.6.3 / 2014-08-10 | |||
| ================== | |||
| * deps: qs@1.2.1 | |||
| 1.6.2 / 2014-08-07 | |||
| ================== | |||
| * deps: qs@1.2.0 | |||
| - Fix parsing array of objects | |||
| 1.6.1 / 2014-08-06 | |||
| ================== | |||
| * deps: qs@1.1.0 | |||
| - Accept urlencoded square brackets | |||
| - Accept empty values in implicit array notation | |||
| 1.6.0 / 2014-08-05 | |||
| ================== | |||
| * deps: qs@1.0.2 | |||
| - Complete rewrite | |||
| - Limits array length to 20 | |||
| - Limits object depth to 5 | |||
| - Limits parameters to 1,000 | |||
| 1.5.2 / 2014-07-27 | |||
| ================== | |||
| * deps: depd@0.4.4 | |||
| - Work-around v8 generating empty stack traces | |||
| 1.5.1 / 2014-07-26 | |||
| ================== | |||
| * deps: depd@0.4.3 | |||
| - Fix exception when global `Error.stackTraceLimit` is too low | |||
| 1.5.0 / 2014-07-20 | |||
| ================== | |||
| * deps: depd@0.4.2 | |||
| - Add `TRACE_DEPRECATION` environment variable | |||
| - Remove non-standard grey color from color output | |||
| - Support `--no-deprecation` argument | |||
| - Support `--trace-deprecation` argument | |||
| * deps: iconv-lite@0.4.4 | |||
| - Added encoding UTF-7 | |||
| * deps: raw-body@1.3.0 | |||
| - deps: iconv-lite@0.4.4 | |||
| - Added encoding UTF-7 | |||
| - Fix `Cannot switch to old mode now` error on Node.js 0.10+ | |||
| * deps: type-is@~1.3.2 | |||
| 1.4.3 / 2014-06-19 | |||
| ================== | |||
| * deps: type-is@1.3.1 | |||
| - fix global variable leak | |||
| 1.4.2 / 2014-06-19 | |||
| ================== | |||
| * deps: type-is@1.3.0 | |||
| - improve type parsing | |||
| 1.4.1 / 2014-06-19 | |||
| ================== | |||
| * fix urlencoded extended deprecation message | |||
| 1.4.0 / 2014-06-19 | |||
| ================== | |||
| * add `text` parser | |||
| * add `raw` parser | |||
| * check accepted charset in content-type (accepts utf-8) | |||
| * check accepted encoding in content-encoding (accepts identity) | |||
| * deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed | |||
| * deprecate `urlencoded()` without provided `extended` option | |||
| * lazy-load urlencoded parsers | |||
| * parsers split into files for reduced mem usage | |||
| * support gzip and deflate bodies | |||
| - set `inflate: false` to turn off | |||
| * deps: raw-body@1.2.2 | |||
| - Support all encodings from `iconv-lite` | |||
| 1.3.1 / 2014-06-11 | |||
| ================== | |||
| * deps: type-is@1.2.1 | |||
| - Switch dependency from mime to mime-types@1.0.0 | |||
| 1.3.0 / 2014-05-31 | |||
| ================== | |||
| * add `extended` option to urlencoded parser | |||
| 1.2.2 / 2014-05-27 | |||
| ================== | |||
| * deps: raw-body@1.1.6 | |||
| - assert stream encoding on node.js 0.8 | |||
| - assert stream encoding on node.js < 0.10.6 | |||
| - deps: bytes@1 | |||
| 1.2.1 / 2014-05-26 | |||
| ================== | |||
| * invoke `next(err)` after request fully read | |||
| - prevents hung responses and socket hang ups | |||
| 1.2.0 / 2014-05-11 | |||
| ================== | |||
| * add `verify` option | |||
| * deps: type-is@1.2.0 | |||
| - support suffix matching | |||
| 1.1.2 / 2014-05-11 | |||
| ================== | |||
| * improve json parser speed | |||
| 1.1.1 / 2014-05-11 | |||
| ================== | |||
| * fix repeated limit parsing with every request | |||
| 1.1.0 / 2014-05-10 | |||
| ================== | |||
| * add `type` option | |||
| * deps: pin for safety and consistency | |||
| 1.0.2 / 2014-04-14 | |||
| ================== | |||
| * use `type-is` module | |||
| 1.0.1 / 2014-03-20 | |||
| ================== | |||
| * lower default limits to 100kb | |||
| @@ -0,0 +1,23 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2014 Jonathan Ong <me@jongleberry.com> | |||
| Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.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. | |||
| @@ -0,0 +1,443 @@ | |||
| # body-parser | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Node.js body parsing middleware. | |||
| Parse incoming request bodies in a middleware before your handlers, available | |||
| under the `req.body` property. | |||
| **Note** As `req.body`'s shape is based on user-controlled input, all | |||
| properties and values in this object are untrusted and should be validated | |||
| before trusting. For example, `req.body.foo.toString()` may fail in multiple | |||
| ways, for example the `foo` property may not be there or may not be a string, | |||
| and `toString` may not be a function and instead a string or other user input. | |||
| [Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/). | |||
| _This does not handle multipart bodies_, due to their complex and typically | |||
| large nature. For multipart bodies, you may be interested in the following | |||
| modules: | |||
| * [busboy](https://www.npmjs.org/package/busboy#readme) and | |||
| [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme) | |||
| * [multiparty](https://www.npmjs.org/package/multiparty#readme) and | |||
| [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme) | |||
| * [formidable](https://www.npmjs.org/package/formidable#readme) | |||
| * [multer](https://www.npmjs.org/package/multer#readme) | |||
| This module provides the following parsers: | |||
| * [JSON body parser](#bodyparserjsonoptions) | |||
| * [Raw body parser](#bodyparserrawoptions) | |||
| * [Text body parser](#bodyparsertextoptions) | |||
| * [URL-encoded form body parser](#bodyparserurlencodedoptions) | |||
| Other body parsers you might be interested in: | |||
| - [body](https://www.npmjs.org/package/body#readme) | |||
| - [co-body](https://www.npmjs.org/package/co-body#readme) | |||
| ## Installation | |||
| ```sh | |||
| $ npm install body-parser | |||
| ``` | |||
| ## API | |||
| <!-- eslint-disable no-unused-vars --> | |||
| ```js | |||
| var bodyParser = require('body-parser') | |||
| ``` | |||
| The `bodyParser` object exposes various factories to create middlewares. All | |||
| middlewares will populate the `req.body` property with the parsed body when | |||
| the `Content-Type` request header matches the `type` option, or an empty | |||
| object (`{}`) if there was no body to parse, the `Content-Type` was not matched, | |||
| or an error occurred. | |||
| The various errors returned by this module are described in the | |||
| [errors section](#errors). | |||
| ### bodyParser.json([options]) | |||
| Returns middleware that only parses `json` and only looks at requests where | |||
| the `Content-Type` header matches the `type` option. This parser accepts any | |||
| Unicode encoding of the body and supports automatic inflation of `gzip` and | |||
| `deflate` encodings. | |||
| A new `body` object containing the parsed data is populated on the `request` | |||
| object after the middleware (i.e. `req.body`). | |||
| #### Options | |||
| The `json` function takes an optional `options` object that may contain any of | |||
| the following keys: | |||
| ##### inflate | |||
| When set to `true`, then deflated (compressed) bodies will be inflated; when | |||
| `false`, deflated bodies are rejected. Defaults to `true`. | |||
| ##### limit | |||
| Controls the maximum request body size. If this is a number, then the value | |||
| specifies the number of bytes; if it is a string, the value is passed to the | |||
| [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults | |||
| to `'100kb'`. | |||
| ##### reviver | |||
| The `reviver` option is passed directly to `JSON.parse` as the second | |||
| argument. You can find more information on this argument | |||
| [in the MDN documentation about JSON.parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter). | |||
| ##### strict | |||
| When set to `true`, will only accept arrays and objects; when `false` will | |||
| accept anything `JSON.parse` accepts. Defaults to `true`. | |||
| ##### type | |||
| The `type` option is used to determine what media type the middleware will | |||
| parse. This option can be a string, array of strings, or a function. If not a | |||
| function, `type` option is passed directly to the | |||
| [type-is](https://www.npmjs.org/package/type-is#readme) library and this can | |||
| be an extension name (like `json`), a mime type (like `application/json`), or | |||
| a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type` | |||
| option is called as `fn(req)` and the request is parsed if it returns a truthy | |||
| value. Defaults to `application/json`. | |||
| ##### verify | |||
| The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, | |||
| where `buf` is a `Buffer` of the raw request body and `encoding` is the | |||
| encoding of the request. The parsing can be aborted by throwing an error. | |||
| ### bodyParser.raw([options]) | |||
| Returns middleware that parses all bodies as a `Buffer` and only looks at | |||
| requests where the `Content-Type` header matches the `type` option. This | |||
| parser supports automatic inflation of `gzip` and `deflate` encodings. | |||
| A new `body` object containing the parsed data is populated on the `request` | |||
| object after the middleware (i.e. `req.body`). This will be a `Buffer` object | |||
| of the body. | |||
| #### Options | |||
| The `raw` function takes an optional `options` object that may contain any of | |||
| the following keys: | |||
| ##### inflate | |||
| When set to `true`, then deflated (compressed) bodies will be inflated; when | |||
| `false`, deflated bodies are rejected. Defaults to `true`. | |||
| ##### limit | |||
| Controls the maximum request body size. If this is a number, then the value | |||
| specifies the number of bytes; if it is a string, the value is passed to the | |||
| [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults | |||
| to `'100kb'`. | |||
| ##### type | |||
| The `type` option is used to determine what media type the middleware will | |||
| parse. This option can be a string, array of strings, or a function. | |||
| If not a function, `type` option is passed directly to the | |||
| [type-is](https://www.npmjs.org/package/type-is#readme) library and this | |||
| can be an extension name (like `bin`), a mime type (like | |||
| `application/octet-stream`), or a mime type with a wildcard (like `*/*` or | |||
| `application/*`). If a function, the `type` option is called as `fn(req)` | |||
| and the request is parsed if it returns a truthy value. Defaults to | |||
| `application/octet-stream`. | |||
| ##### verify | |||
| The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, | |||
| where `buf` is a `Buffer` of the raw request body and `encoding` is the | |||
| encoding of the request. The parsing can be aborted by throwing an error. | |||
| ### bodyParser.text([options]) | |||
| Returns middleware that parses all bodies as a string and only looks at | |||
| requests where the `Content-Type` header matches the `type` option. This | |||
| parser supports automatic inflation of `gzip` and `deflate` encodings. | |||
| A new `body` string containing the parsed data is populated on the `request` | |||
| object after the middleware (i.e. `req.body`). This will be a string of the | |||
| body. | |||
| #### Options | |||
| The `text` function takes an optional `options` object that may contain any of | |||
| the following keys: | |||
| ##### defaultCharset | |||
| Specify the default character set for the text content if the charset is not | |||
| specified in the `Content-Type` header of the request. Defaults to `utf-8`. | |||
| ##### inflate | |||
| When set to `true`, then deflated (compressed) bodies will be inflated; when | |||
| `false`, deflated bodies are rejected. Defaults to `true`. | |||
| ##### limit | |||
| Controls the maximum request body size. If this is a number, then the value | |||
| specifies the number of bytes; if it is a string, the value is passed to the | |||
| [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults | |||
| to `'100kb'`. | |||
| ##### type | |||
| The `type` option is used to determine what media type the middleware will | |||
| parse. This option can be a string, array of strings, or a function. If not | |||
| a function, `type` option is passed directly to the | |||
| [type-is](https://www.npmjs.org/package/type-is#readme) library and this can | |||
| be an extension name (like `txt`), a mime type (like `text/plain`), or a mime | |||
| type with a wildcard (like `*/*` or `text/*`). If a function, the `type` | |||
| option is called as `fn(req)` and the request is parsed if it returns a | |||
| truthy value. Defaults to `text/plain`. | |||
| ##### verify | |||
| The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, | |||
| where `buf` is a `Buffer` of the raw request body and `encoding` is the | |||
| encoding of the request. The parsing can be aborted by throwing an error. | |||
| ### bodyParser.urlencoded([options]) | |||
| Returns middleware that only parses `urlencoded` bodies and only looks at | |||
| requests where the `Content-Type` header matches the `type` option. This | |||
| parser accepts only UTF-8 encoding of the body and supports automatic | |||
| inflation of `gzip` and `deflate` encodings. | |||
| A new `body` object containing the parsed data is populated on the `request` | |||
| object after the middleware (i.e. `req.body`). This object will contain | |||
| key-value pairs, where the value can be a string or array (when `extended` is | |||
| `false`), or any type (when `extended` is `true`). | |||
| #### Options | |||
| The `urlencoded` function takes an optional `options` object that may contain | |||
| any of the following keys: | |||
| ##### extended | |||
| The `extended` option allows to choose between parsing the URL-encoded data | |||
| with the `querystring` library (when `false`) or the `qs` library (when | |||
| `true`). The "extended" syntax allows for rich objects and arrays to be | |||
| encoded into the URL-encoded format, allowing for a JSON-like experience | |||
| with URL-encoded. For more information, please | |||
| [see the qs library](https://www.npmjs.org/package/qs#readme). | |||
| Defaults to `true`, but using the default has been deprecated. Please | |||
| research into the difference between `qs` and `querystring` and choose the | |||
| appropriate setting. | |||
| ##### inflate | |||
| When set to `true`, then deflated (compressed) bodies will be inflated; when | |||
| `false`, deflated bodies are rejected. Defaults to `true`. | |||
| ##### limit | |||
| Controls the maximum request body size. If this is a number, then the value | |||
| specifies the number of bytes; if it is a string, the value is passed to the | |||
| [bytes](https://www.npmjs.com/package/bytes) library for parsing. Defaults | |||
| to `'100kb'`. | |||
| ##### parameterLimit | |||
| The `parameterLimit` option controls the maximum number of parameters that | |||
| are allowed in the URL-encoded data. If a request contains more parameters | |||
| than this value, a 413 will be returned to the client. Defaults to `1000`. | |||
| ##### type | |||
| The `type` option is used to determine what media type the middleware will | |||
| parse. This option can be a string, array of strings, or a function. If not | |||
| a function, `type` option is passed directly to the | |||
| [type-is](https://www.npmjs.org/package/type-is#readme) library and this can | |||
| be an extension name (like `urlencoded`), a mime type (like | |||
| `application/x-www-form-urlencoded`), or a mime type with a wildcard (like | |||
| `*/x-www-form-urlencoded`). If a function, the `type` option is called as | |||
| `fn(req)` and the request is parsed if it returns a truthy value. Defaults | |||
| to `application/x-www-form-urlencoded`. | |||
| ##### verify | |||
| The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`, | |||
| where `buf` is a `Buffer` of the raw request body and `encoding` is the | |||
| encoding of the request. The parsing can be aborted by throwing an error. | |||
| ## Errors | |||
| The middlewares provided by this module create errors depending on the error | |||
| condition during parsing. The errors will typically have a `status`/`statusCode` | |||
| property that contains the suggested HTTP response code, an `expose` property | |||
| to determine if the `message` property should be displayed to the client, a | |||
| `type` property to determine the type of error without matching against the | |||
| `message`, and a `body` property containing the read body, if available. | |||
| The following are the common errors emitted, though any error can come through | |||
| for various reasons. | |||
| ### content encoding unsupported | |||
| This error will occur when the request had a `Content-Encoding` header that | |||
| contained an encoding but the "inflation" option was set to `false`. The | |||
| `status` property is set to `415`, the `type` property is set to | |||
| `'encoding.unsupported'`, and the `charset` property will be set to the | |||
| encoding that is unsupported. | |||
| ### request aborted | |||
| This error will occur when the request is aborted by the client before reading | |||
| the body has finished. The `received` property will be set to the number of | |||
| bytes received before the request was aborted and the `expected` property is | |||
| set to the number of expected bytes. The `status` property is set to `400` | |||
| and `type` property is set to `'request.aborted'`. | |||
| ### request entity too large | |||
| This error will occur when the request body's size is larger than the "limit" | |||
| option. The `limit` property will be set to the byte limit and the `length` | |||
| property will be set to the request body's length. The `status` property is | |||
| set to `413` and the `type` property is set to `'entity.too.large'`. | |||
| ### request size did not match content length | |||
| This error will occur when the request's length did not match the length from | |||
| the `Content-Length` header. This typically occurs when the request is malformed, | |||
| typically when the `Content-Length` header was calculated based on characters | |||
| instead of bytes. The `status` property is set to `400` and the `type` property | |||
| is set to `'request.size.invalid'`. | |||
| ### stream encoding should not be set | |||
| This error will occur when something called the `req.setEncoding` method prior | |||
| to this middleware. This module operates directly on bytes only and you cannot | |||
| call `req.setEncoding` when using this module. The `status` property is set to | |||
| `500` and the `type` property is set to `'stream.encoding.set'`. | |||
| ### too many parameters | |||
| This error will occur when the content of the request exceeds the configured | |||
| `parameterLimit` for the `urlencoded` parser. The `status` property is set to | |||
| `413` and the `type` property is set to `'parameters.too.many'`. | |||
| ### unsupported charset "BOGUS" | |||
| This error will occur when the request had a charset parameter in the | |||
| `Content-Type` header, but the `iconv-lite` module does not support it OR the | |||
| parser does not support it. The charset is contained in the message as well | |||
| as in the `charset` property. The `status` property is set to `415`, the | |||
| `type` property is set to `'charset.unsupported'`, and the `charset` property | |||
| is set to the charset that is unsupported. | |||
| ### unsupported content encoding "bogus" | |||
| This error will occur when the request had a `Content-Encoding` header that | |||
| contained an unsupported encoding. The encoding is contained in the message | |||
| as well as in the `encoding` property. The `status` property is set to `415`, | |||
| the `type` property is set to `'encoding.unsupported'`, and the `encoding` | |||
| property is set to the encoding that is unsupported. | |||
| ## Examples | |||
| ### Express/Connect top-level generic | |||
| This example demonstrates adding a generic JSON and URL-encoded parser as a | |||
| top-level middleware, which will parse the bodies of all incoming requests. | |||
| This is the simplest setup. | |||
| ```js | |||
| var express = require('express') | |||
| var bodyParser = require('body-parser') | |||
| var app = express() | |||
| // parse application/x-www-form-urlencoded | |||
| app.use(bodyParser.urlencoded({ extended: false })) | |||
| // parse application/json | |||
| app.use(bodyParser.json()) | |||
| app.use(function (req, res) { | |||
| res.setHeader('Content-Type', 'text/plain') | |||
| res.write('you posted:\n') | |||
| res.end(JSON.stringify(req.body, null, 2)) | |||
| }) | |||
| ``` | |||
| ### Express route-specific | |||
| This example demonstrates adding body parsers specifically to the routes that | |||
| need them. In general, this is the most recommended way to use body-parser with | |||
| Express. | |||
| ```js | |||
| var express = require('express') | |||
| var bodyParser = require('body-parser') | |||
| var app = express() | |||
| // create application/json parser | |||
| var jsonParser = bodyParser.json() | |||
| // create application/x-www-form-urlencoded parser | |||
| var urlencodedParser = bodyParser.urlencoded({ extended: false }) | |||
| // POST /login gets urlencoded bodies | |||
| app.post('/login', urlencodedParser, function (req, res) { | |||
| res.send('welcome, ' + req.body.username) | |||
| }) | |||
| // POST /api/users gets JSON bodies | |||
| app.post('/api/users', jsonParser, function (req, res) { | |||
| // create user in req.body | |||
| }) | |||
| ``` | |||
| ### Change accepted type for parsers | |||
| All the parsers accept a `type` option which allows you to change the | |||
| `Content-Type` that the middleware will parse. | |||
| ```js | |||
| var express = require('express') | |||
| var bodyParser = require('body-parser') | |||
| var app = express() | |||
| // parse various different custom JSON types as JSON | |||
| app.use(bodyParser.json({ type: 'application/*+json' })) | |||
| // parse some custom thing into a Buffer | |||
| app.use(bodyParser.raw({ type: 'application/vnd.custom-type' })) | |||
| // parse an HTML body into a string | |||
| app.use(bodyParser.text({ type: 'text/html' })) | |||
| ``` | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/body-parser.svg | |||
| [npm-url]: https://npmjs.org/package/body-parser | |||
| [travis-image]: https://img.shields.io/travis/expressjs/body-parser/master.svg | |||
| [travis-url]: https://travis-ci.org/expressjs/body-parser | |||
| [coveralls-image]: https://img.shields.io/coveralls/expressjs/body-parser/master.svg | |||
| [coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master | |||
| [downloads-image]: https://img.shields.io/npm/dm/body-parser.svg | |||
| [downloads-url]: https://npmjs.org/package/body-parser | |||
| @@ -0,0 +1,157 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var deprecate = require('depd')('body-parser') | |||
| /** | |||
| * Cache of loaded parsers. | |||
| * @private | |||
| */ | |||
| var parsers = Object.create(null) | |||
| /** | |||
| * @typedef Parsers | |||
| * @type {function} | |||
| * @property {function} json | |||
| * @property {function} raw | |||
| * @property {function} text | |||
| * @property {function} urlencoded | |||
| */ | |||
| /** | |||
| * Module exports. | |||
| * @type {Parsers} | |||
| */ | |||
| exports = module.exports = deprecate.function(bodyParser, | |||
| 'bodyParser: use individual json/urlencoded middlewares') | |||
| /** | |||
| * JSON parser. | |||
| * @public | |||
| */ | |||
| Object.defineProperty(exports, 'json', { | |||
| configurable: true, | |||
| enumerable: true, | |||
| get: createParserGetter('json') | |||
| }) | |||
| /** | |||
| * Raw parser. | |||
| * @public | |||
| */ | |||
| Object.defineProperty(exports, 'raw', { | |||
| configurable: true, | |||
| enumerable: true, | |||
| get: createParserGetter('raw') | |||
| }) | |||
| /** | |||
| * Text parser. | |||
| * @public | |||
| */ | |||
| Object.defineProperty(exports, 'text', { | |||
| configurable: true, | |||
| enumerable: true, | |||
| get: createParserGetter('text') | |||
| }) | |||
| /** | |||
| * URL-encoded parser. | |||
| * @public | |||
| */ | |||
| Object.defineProperty(exports, 'urlencoded', { | |||
| configurable: true, | |||
| enumerable: true, | |||
| get: createParserGetter('urlencoded') | |||
| }) | |||
| /** | |||
| * Create a middleware to parse json and urlencoded bodies. | |||
| * | |||
| * @param {object} [options] | |||
| * @return {function} | |||
| * @deprecated | |||
| * @public | |||
| */ | |||
| function bodyParser (options) { | |||
| var opts = {} | |||
| // exclude type option | |||
| if (options) { | |||
| for (var prop in options) { | |||
| if (prop !== 'type') { | |||
| opts[prop] = options[prop] | |||
| } | |||
| } | |||
| } | |||
| var _urlencoded = exports.urlencoded(opts) | |||
| var _json = exports.json(opts) | |||
| return function bodyParser (req, res, next) { | |||
| _json(req, res, function (err) { | |||
| if (err) return next(err) | |||
| _urlencoded(req, res, next) | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Create a getter for loading a parser. | |||
| * @private | |||
| */ | |||
| function createParserGetter (name) { | |||
| return function get () { | |||
| return loadParser(name) | |||
| } | |||
| } | |||
| /** | |||
| * Load a parser module. | |||
| * @private | |||
| */ | |||
| function loadParser (parserName) { | |||
| var parser = parsers[parserName] | |||
| if (parser !== undefined) { | |||
| return parser | |||
| } | |||
| // this uses a switch for static require analysis | |||
| switch (parserName) { | |||
| case 'json': | |||
| parser = require('./lib/types/json') | |||
| break | |||
| case 'raw': | |||
| parser = require('./lib/types/raw') | |||
| break | |||
| case 'text': | |||
| parser = require('./lib/types/text') | |||
| break | |||
| case 'urlencoded': | |||
| parser = require('./lib/types/urlencoded') | |||
| break | |||
| } | |||
| // store to prevent invoking require() | |||
| return (parsers[parserName] = parser) | |||
| } | |||
| @@ -0,0 +1,181 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var createError = require('http-errors') | |||
| var getBody = require('raw-body') | |||
| var iconv = require('iconv-lite') | |||
| var onFinished = require('on-finished') | |||
| var zlib = require('zlib') | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = read | |||
| /** | |||
| * Read a request into a buffer and parse. | |||
| * | |||
| * @param {object} req | |||
| * @param {object} res | |||
| * @param {function} next | |||
| * @param {function} parse | |||
| * @param {function} debug | |||
| * @param {object} options | |||
| * @private | |||
| */ | |||
| function read (req, res, next, parse, debug, options) { | |||
| var length | |||
| var opts = options | |||
| var stream | |||
| // flag as parsed | |||
| req._body = true | |||
| // read options | |||
| var encoding = opts.encoding !== null | |||
| ? opts.encoding | |||
| : null | |||
| var verify = opts.verify | |||
| try { | |||
| // get the content stream | |||
| stream = contentstream(req, debug, opts.inflate) | |||
| length = stream.length | |||
| stream.length = undefined | |||
| } catch (err) { | |||
| return next(err) | |||
| } | |||
| // set raw-body options | |||
| opts.length = length | |||
| opts.encoding = verify | |||
| ? null | |||
| : encoding | |||
| // assert charset is supported | |||
| if (opts.encoding === null && encoding !== null && !iconv.encodingExists(encoding)) { | |||
| return next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { | |||
| charset: encoding.toLowerCase(), | |||
| type: 'charset.unsupported' | |||
| })) | |||
| } | |||
| // read body | |||
| debug('read body') | |||
| getBody(stream, opts, function (error, body) { | |||
| if (error) { | |||
| var _error | |||
| if (error.type === 'encoding.unsupported') { | |||
| // echo back charset | |||
| _error = createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', { | |||
| charset: encoding.toLowerCase(), | |||
| type: 'charset.unsupported' | |||
| }) | |||
| } else { | |||
| // set status code on error | |||
| _error = createError(400, error) | |||
| } | |||
| // read off entire request | |||
| stream.resume() | |||
| onFinished(req, function onfinished () { | |||
| next(createError(400, _error)) | |||
| }) | |||
| return | |||
| } | |||
| // verify | |||
| if (verify) { | |||
| try { | |||
| debug('verify body') | |||
| verify(req, res, body, encoding) | |||
| } catch (err) { | |||
| next(createError(403, err, { | |||
| body: body, | |||
| type: err.type || 'entity.verify.failed' | |||
| })) | |||
| return | |||
| } | |||
| } | |||
| // parse | |||
| var str = body | |||
| try { | |||
| debug('parse body') | |||
| str = typeof body !== 'string' && encoding !== null | |||
| ? iconv.decode(body, encoding) | |||
| : body | |||
| req.body = parse(str) | |||
| } catch (err) { | |||
| next(createError(400, err, { | |||
| body: str, | |||
| type: err.type || 'entity.parse.failed' | |||
| })) | |||
| return | |||
| } | |||
| next() | |||
| }) | |||
| } | |||
| /** | |||
| * Get the content stream of the request. | |||
| * | |||
| * @param {object} req | |||
| * @param {function} debug | |||
| * @param {boolean} [inflate=true] | |||
| * @return {object} | |||
| * @api private | |||
| */ | |||
| function contentstream (req, debug, inflate) { | |||
| var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase() | |||
| var length = req.headers['content-length'] | |||
| var stream | |||
| debug('content-encoding "%s"', encoding) | |||
| if (inflate === false && encoding !== 'identity') { | |||
| throw createError(415, 'content encoding unsupported', { | |||
| encoding: encoding, | |||
| type: 'encoding.unsupported' | |||
| }) | |||
| } | |||
| switch (encoding) { | |||
| case 'deflate': | |||
| stream = zlib.createInflate() | |||
| debug('inflate body') | |||
| req.pipe(stream) | |||
| break | |||
| case 'gzip': | |||
| stream = zlib.createGunzip() | |||
| debug('gunzip body') | |||
| req.pipe(stream) | |||
| break | |||
| case 'identity': | |||
| stream = req | |||
| stream.length = length | |||
| break | |||
| default: | |||
| throw createError(415, 'unsupported content encoding "' + encoding + '"', { | |||
| encoding: encoding, | |||
| type: 'encoding.unsupported' | |||
| }) | |||
| } | |||
| return stream | |||
| } | |||
| @@ -0,0 +1,230 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014 Jonathan Ong | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var bytes = require('bytes') | |||
| var contentType = require('content-type') | |||
| var createError = require('http-errors') | |||
| var debug = require('debug')('body-parser:json') | |||
| var read = require('../read') | |||
| var typeis = require('type-is') | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = json | |||
| /** | |||
| * RegExp to match the first non-space in a string. | |||
| * | |||
| * Allowed whitespace is defined in RFC 7159: | |||
| * | |||
| * ws = *( | |||
| * %x20 / ; Space | |||
| * %x09 / ; Horizontal tab | |||
| * %x0A / ; Line feed or New line | |||
| * %x0D ) ; Carriage return | |||
| */ | |||
| var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*(.)/ // eslint-disable-line no-control-regex | |||
| /** | |||
| * Create a middleware to parse JSON bodies. | |||
| * | |||
| * @param {object} [options] | |||
| * @return {function} | |||
| * @public | |||
| */ | |||
| function json (options) { | |||
| var opts = options || {} | |||
| var limit = typeof opts.limit !== 'number' | |||
| ? bytes.parse(opts.limit || '100kb') | |||
| : opts.limit | |||
| var inflate = opts.inflate !== false | |||
| var reviver = opts.reviver | |||
| var strict = opts.strict !== false | |||
| var type = opts.type || 'application/json' | |||
| var verify = opts.verify || false | |||
| if (verify !== false && typeof verify !== 'function') { | |||
| throw new TypeError('option verify must be function') | |||
| } | |||
| // create the appropriate type checking function | |||
| var shouldParse = typeof type !== 'function' | |||
| ? typeChecker(type) | |||
| : type | |||
| function parse (body) { | |||
| if (body.length === 0) { | |||
| // special-case empty json body, as it's a common client-side mistake | |||
| // TODO: maybe make this configurable or part of "strict" option | |||
| return {} | |||
| } | |||
| if (strict) { | |||
| var first = firstchar(body) | |||
| if (first !== '{' && first !== '[') { | |||
| debug('strict violation') | |||
| throw createStrictSyntaxError(body, first) | |||
| } | |||
| } | |||
| try { | |||
| debug('parse json') | |||
| return JSON.parse(body, reviver) | |||
| } catch (e) { | |||
| throw normalizeJsonSyntaxError(e, { | |||
| message: e.message, | |||
| stack: e.stack | |||
| }) | |||
| } | |||
| } | |||
| return function jsonParser (req, res, next) { | |||
| if (req._body) { | |||
| debug('body already parsed') | |||
| next() | |||
| return | |||
| } | |||
| req.body = req.body || {} | |||
| // skip requests without bodies | |||
| if (!typeis.hasBody(req)) { | |||
| debug('skip empty body') | |||
| next() | |||
| return | |||
| } | |||
| debug('content-type %j', req.headers['content-type']) | |||
| // determine if request should be parsed | |||
| if (!shouldParse(req)) { | |||
| debug('skip parsing') | |||
| next() | |||
| return | |||
| } | |||
| // assert charset per RFC 7159 sec 8.1 | |||
| var charset = getCharset(req) || 'utf-8' | |||
| if (charset.substr(0, 4) !== 'utf-') { | |||
| debug('invalid charset') | |||
| next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { | |||
| charset: charset, | |||
| type: 'charset.unsupported' | |||
| })) | |||
| return | |||
| } | |||
| // read | |||
| read(req, res, next, parse, debug, { | |||
| encoding: charset, | |||
| inflate: inflate, | |||
| limit: limit, | |||
| verify: verify | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Create strict violation syntax error matching native error. | |||
| * | |||
| * @param {string} str | |||
| * @param {string} char | |||
| * @return {Error} | |||
| * @private | |||
| */ | |||
| function createStrictSyntaxError (str, char) { | |||
| var index = str.indexOf(char) | |||
| var partial = str.substring(0, index) + '#' | |||
| try { | |||
| JSON.parse(partial); /* istanbul ignore next */ throw new SyntaxError('strict violation') | |||
| } catch (e) { | |||
| return normalizeJsonSyntaxError(e, { | |||
| message: e.message.replace('#', char), | |||
| stack: e.stack | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the first non-whitespace character in a string. | |||
| * | |||
| * @param {string} str | |||
| * @return {function} | |||
| * @private | |||
| */ | |||
| function firstchar (str) { | |||
| return FIRST_CHAR_REGEXP.exec(str)[1] | |||
| } | |||
| /** | |||
| * Get the charset of a request. | |||
| * | |||
| * @param {object} req | |||
| * @api private | |||
| */ | |||
| function getCharset (req) { | |||
| try { | |||
| return (contentType.parse(req).parameters.charset || '').toLowerCase() | |||
| } catch (e) { | |||
| return undefined | |||
| } | |||
| } | |||
| /** | |||
| * Normalize a SyntaxError for JSON.parse. | |||
| * | |||
| * @param {SyntaxError} error | |||
| * @param {object} obj | |||
| * @return {SyntaxError} | |||
| */ | |||
| function normalizeJsonSyntaxError (error, obj) { | |||
| var keys = Object.getOwnPropertyNames(error) | |||
| for (var i = 0; i < keys.length; i++) { | |||
| var key = keys[i] | |||
| if (key !== 'stack' && key !== 'message') { | |||
| delete error[key] | |||
| } | |||
| } | |||
| // replace stack before message for Node.js 0.10 and below | |||
| error.stack = obj.stack.replace(error.message, obj.message) | |||
| error.message = obj.message | |||
| return error | |||
| } | |||
| /** | |||
| * Get the simple type checker. | |||
| * | |||
| * @param {string} type | |||
| * @return {function} | |||
| */ | |||
| function typeChecker (type) { | |||
| return function checkType (req) { | |||
| return Boolean(typeis(req, type)) | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| */ | |||
| var bytes = require('bytes') | |||
| var debug = require('debug')('body-parser:raw') | |||
| var read = require('../read') | |||
| var typeis = require('type-is') | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = raw | |||
| /** | |||
| * Create a middleware to parse raw bodies. | |||
| * | |||
| * @param {object} [options] | |||
| * @return {function} | |||
| * @api public | |||
| */ | |||
| function raw (options) { | |||
| var opts = options || {} | |||
| var inflate = opts.inflate !== false | |||
| var limit = typeof opts.limit !== 'number' | |||
| ? bytes.parse(opts.limit || '100kb') | |||
| : opts.limit | |||
| var type = opts.type || 'application/octet-stream' | |||
| var verify = opts.verify || false | |||
| if (verify !== false && typeof verify !== 'function') { | |||
| throw new TypeError('option verify must be function') | |||
| } | |||
| // create the appropriate type checking function | |||
| var shouldParse = typeof type !== 'function' | |||
| ? typeChecker(type) | |||
| : type | |||
| function parse (buf) { | |||
| return buf | |||
| } | |||
| return function rawParser (req, res, next) { | |||
| if (req._body) { | |||
| debug('body already parsed') | |||
| next() | |||
| return | |||
| } | |||
| req.body = req.body || {} | |||
| // skip requests without bodies | |||
| if (!typeis.hasBody(req)) { | |||
| debug('skip empty body') | |||
| next() | |||
| return | |||
| } | |||
| debug('content-type %j', req.headers['content-type']) | |||
| // determine if request should be parsed | |||
| if (!shouldParse(req)) { | |||
| debug('skip parsing') | |||
| next() | |||
| return | |||
| } | |||
| // read | |||
| read(req, res, next, parse, debug, { | |||
| encoding: null, | |||
| inflate: inflate, | |||
| limit: limit, | |||
| verify: verify | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the simple type checker. | |||
| * | |||
| * @param {string} type | |||
| * @return {function} | |||
| */ | |||
| function typeChecker (type) { | |||
| return function checkType (req) { | |||
| return Boolean(typeis(req, type)) | |||
| } | |||
| } | |||
| @@ -0,0 +1,121 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| */ | |||
| var bytes = require('bytes') | |||
| var contentType = require('content-type') | |||
| var debug = require('debug')('body-parser:text') | |||
| var read = require('../read') | |||
| var typeis = require('type-is') | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = text | |||
| /** | |||
| * Create a middleware to parse text bodies. | |||
| * | |||
| * @param {object} [options] | |||
| * @return {function} | |||
| * @api public | |||
| */ | |||
| function text (options) { | |||
| var opts = options || {} | |||
| var defaultCharset = opts.defaultCharset || 'utf-8' | |||
| var inflate = opts.inflate !== false | |||
| var limit = typeof opts.limit !== 'number' | |||
| ? bytes.parse(opts.limit || '100kb') | |||
| : opts.limit | |||
| var type = opts.type || 'text/plain' | |||
| var verify = opts.verify || false | |||
| if (verify !== false && typeof verify !== 'function') { | |||
| throw new TypeError('option verify must be function') | |||
| } | |||
| // create the appropriate type checking function | |||
| var shouldParse = typeof type !== 'function' | |||
| ? typeChecker(type) | |||
| : type | |||
| function parse (buf) { | |||
| return buf | |||
| } | |||
| return function textParser (req, res, next) { | |||
| if (req._body) { | |||
| debug('body already parsed') | |||
| next() | |||
| return | |||
| } | |||
| req.body = req.body || {} | |||
| // skip requests without bodies | |||
| if (!typeis.hasBody(req)) { | |||
| debug('skip empty body') | |||
| next() | |||
| return | |||
| } | |||
| debug('content-type %j', req.headers['content-type']) | |||
| // determine if request should be parsed | |||
| if (!shouldParse(req)) { | |||
| debug('skip parsing') | |||
| next() | |||
| return | |||
| } | |||
| // get charset | |||
| var charset = getCharset(req) || defaultCharset | |||
| // read | |||
| read(req, res, next, parse, debug, { | |||
| encoding: charset, | |||
| inflate: inflate, | |||
| limit: limit, | |||
| verify: verify | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the charset of a request. | |||
| * | |||
| * @param {object} req | |||
| * @api private | |||
| */ | |||
| function getCharset (req) { | |||
| try { | |||
| return (contentType.parse(req).parameters.charset || '').toLowerCase() | |||
| } catch (e) { | |||
| return undefined | |||
| } | |||
| } | |||
| /** | |||
| * Get the simple type checker. | |||
| * | |||
| * @param {string} type | |||
| * @return {function} | |||
| */ | |||
| function typeChecker (type) { | |||
| return function checkType (req) { | |||
| return Boolean(typeis(req, type)) | |||
| } | |||
| } | |||
| @@ -0,0 +1,284 @@ | |||
| /*! | |||
| * body-parser | |||
| * Copyright(c) 2014 Jonathan Ong | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var bytes = require('bytes') | |||
| var contentType = require('content-type') | |||
| var createError = require('http-errors') | |||
| var debug = require('debug')('body-parser:urlencoded') | |||
| var deprecate = require('depd')('body-parser') | |||
| var read = require('../read') | |||
| var typeis = require('type-is') | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = urlencoded | |||
| /** | |||
| * Cache of parser modules. | |||
| */ | |||
| var parsers = Object.create(null) | |||
| /** | |||
| * Create a middleware to parse urlencoded bodies. | |||
| * | |||
| * @param {object} [options] | |||
| * @return {function} | |||
| * @public | |||
| */ | |||
| function urlencoded (options) { | |||
| var opts = options || {} | |||
| // notice because option default will flip in next major | |||
| if (opts.extended === undefined) { | |||
| deprecate('undefined extended: provide extended option') | |||
| } | |||
| var extended = opts.extended !== false | |||
| var inflate = opts.inflate !== false | |||
| var limit = typeof opts.limit !== 'number' | |||
| ? bytes.parse(opts.limit || '100kb') | |||
| : opts.limit | |||
| var type = opts.type || 'application/x-www-form-urlencoded' | |||
| var verify = opts.verify || false | |||
| if (verify !== false && typeof verify !== 'function') { | |||
| throw new TypeError('option verify must be function') | |||
| } | |||
| // create the appropriate query parser | |||
| var queryparse = extended | |||
| ? extendedparser(opts) | |||
| : simpleparser(opts) | |||
| // create the appropriate type checking function | |||
| var shouldParse = typeof type !== 'function' | |||
| ? typeChecker(type) | |||
| : type | |||
| function parse (body) { | |||
| return body.length | |||
| ? queryparse(body) | |||
| : {} | |||
| } | |||
| return function urlencodedParser (req, res, next) { | |||
| if (req._body) { | |||
| debug('body already parsed') | |||
| next() | |||
| return | |||
| } | |||
| req.body = req.body || {} | |||
| // skip requests without bodies | |||
| if (!typeis.hasBody(req)) { | |||
| debug('skip empty body') | |||
| next() | |||
| return | |||
| } | |||
| debug('content-type %j', req.headers['content-type']) | |||
| // determine if request should be parsed | |||
| if (!shouldParse(req)) { | |||
| debug('skip parsing') | |||
| next() | |||
| return | |||
| } | |||
| // assert charset | |||
| var charset = getCharset(req) || 'utf-8' | |||
| if (charset !== 'utf-8') { | |||
| debug('invalid charset') | |||
| next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { | |||
| charset: charset, | |||
| type: 'charset.unsupported' | |||
| })) | |||
| return | |||
| } | |||
| // read | |||
| read(req, res, next, parse, debug, { | |||
| debug: debug, | |||
| encoding: charset, | |||
| inflate: inflate, | |||
| limit: limit, | |||
| verify: verify | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the extended query parser. | |||
| * | |||
| * @param {object} options | |||
| */ | |||
| function extendedparser (options) { | |||
| var parameterLimit = options.parameterLimit !== undefined | |||
| ? options.parameterLimit | |||
| : 1000 | |||
| var parse = parser('qs') | |||
| if (isNaN(parameterLimit) || parameterLimit < 1) { | |||
| throw new TypeError('option parameterLimit must be a positive number') | |||
| } | |||
| if (isFinite(parameterLimit)) { | |||
| parameterLimit = parameterLimit | 0 | |||
| } | |||
| return function queryparse (body) { | |||
| var paramCount = parameterCount(body, parameterLimit) | |||
| if (paramCount === undefined) { | |||
| debug('too many parameters') | |||
| throw createError(413, 'too many parameters', { | |||
| type: 'parameters.too.many' | |||
| }) | |||
| } | |||
| var arrayLimit = Math.max(100, paramCount) | |||
| debug('parse extended urlencoding') | |||
| return parse(body, { | |||
| allowPrototypes: true, | |||
| arrayLimit: arrayLimit, | |||
| depth: Infinity, | |||
| parameterLimit: parameterLimit | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the charset of a request. | |||
| * | |||
| * @param {object} req | |||
| * @api private | |||
| */ | |||
| function getCharset (req) { | |||
| try { | |||
| return (contentType.parse(req).parameters.charset || '').toLowerCase() | |||
| } catch (e) { | |||
| return undefined | |||
| } | |||
| } | |||
| /** | |||
| * Count the number of parameters, stopping once limit reached | |||
| * | |||
| * @param {string} body | |||
| * @param {number} limit | |||
| * @api private | |||
| */ | |||
| function parameterCount (body, limit) { | |||
| var count = 0 | |||
| var index = 0 | |||
| while ((index = body.indexOf('&', index)) !== -1) { | |||
| count++ | |||
| index++ | |||
| if (count === limit) { | |||
| return undefined | |||
| } | |||
| } | |||
| return count | |||
| } | |||
| /** | |||
| * Get parser for module name dynamically. | |||
| * | |||
| * @param {string} name | |||
| * @return {function} | |||
| * @api private | |||
| */ | |||
| function parser (name) { | |||
| var mod = parsers[name] | |||
| if (mod !== undefined) { | |||
| return mod.parse | |||
| } | |||
| // this uses a switch for static require analysis | |||
| switch (name) { | |||
| case 'qs': | |||
| mod = require('qs') | |||
| break | |||
| case 'querystring': | |||
| mod = require('querystring') | |||
| break | |||
| } | |||
| // store to prevent invoking require() | |||
| parsers[name] = mod | |||
| return mod.parse | |||
| } | |||
| /** | |||
| * Get the simple query parser. | |||
| * | |||
| * @param {object} options | |||
| */ | |||
| function simpleparser (options) { | |||
| var parameterLimit = options.parameterLimit !== undefined | |||
| ? options.parameterLimit | |||
| : 1000 | |||
| var parse = parser('querystring') | |||
| if (isNaN(parameterLimit) || parameterLimit < 1) { | |||
| throw new TypeError('option parameterLimit must be a positive number') | |||
| } | |||
| if (isFinite(parameterLimit)) { | |||
| parameterLimit = parameterLimit | 0 | |||
| } | |||
| return function queryparse (body) { | |||
| var paramCount = parameterCount(body, parameterLimit) | |||
| if (paramCount === undefined) { | |||
| debug('too many parameters') | |||
| throw createError(413, 'too many parameters', { | |||
| type: 'parameters.too.many' | |||
| }) | |||
| } | |||
| debug('parse urlencoding') | |||
| return parse(body, undefined, undefined, { maxKeys: parameterLimit }) | |||
| } | |||
| } | |||
| /** | |||
| * Get the simple type checker. | |||
| * | |||
| * @param {string} type | |||
| * @return {function} | |||
| */ | |||
| function typeChecker (type) { | |||
| return function checkType (req) { | |||
| return Boolean(typeis(req, type)) | |||
| } | |||
| } | |||
| @@ -0,0 +1,117 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "body-parser@1.19.0", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "body-parser@1.19.0", | |||
| "_hasShrinkwrap": false, | |||
| "_id": "body-parser@1.19.0", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/body-parser", | |||
| "_nodeVersion": "8.16.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/body-parser_1.19.0_1556249483843_0.8465662994525756" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "6.4.1", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "body-parser", | |||
| "raw": "body-parser@1.19.0", | |||
| "rawSpec": "1.19.0", | |||
| "scope": null, | |||
| "spec": "1.19.0", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", | |||
| "_shasum": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a", | |||
| "_shrinkwrap": null, | |||
| "_spec": "body-parser@1.19.0", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "bugs": { | |||
| "url": "https://github.com/expressjs/body-parser/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| }, | |||
| { | |||
| "name": "Jonathan Ong", | |||
| "email": "me@jongleberry.com", | |||
| "url": "http://jongleberry.com" | |||
| } | |||
| ], | |||
| "dependencies": { | |||
| "bytes": "3.1.0", | |||
| "content-type": "~1.0.4", | |||
| "debug": "2.6.9", | |||
| "depd": "~1.1.2", | |||
| "http-errors": "1.7.2", | |||
| "iconv-lite": "0.4.24", | |||
| "on-finished": "~2.3.0", | |||
| "qs": "6.7.0", | |||
| "raw-body": "2.4.0", | |||
| "type-is": "~1.6.17" | |||
| }, | |||
| "description": "Node.js body parsing middleware", | |||
| "devDependencies": { | |||
| "eslint": "5.16.0", | |||
| "eslint-config-standard": "12.0.0", | |||
| "eslint-plugin-import": "2.17.2", | |||
| "eslint-plugin-markdown": "1.0.0", | |||
| "eslint-plugin-node": "8.0.1", | |||
| "eslint-plugin-promise": "4.1.1", | |||
| "eslint-plugin-standard": "4.0.0", | |||
| "istanbul": "0.4.5", | |||
| "methods": "1.1.2", | |||
| "mocha": "6.1.4", | |||
| "safe-buffer": "5.1.2", | |||
| "supertest": "4.0.2" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "fileCount": 10, | |||
| "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", | |||
| "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcwnuMCRA9TVsSAnZWagAA2zMP/3i2Q8pQBJx4azFOeuub\n/s3F445wJrDoAKA+6zSOLFMYYasZ0iF60NoE4taDupDF1hzpC4gCYgy9ZezQ\n75kKKBC48jCQP6Urx1tj6VUPzWqG6xdQMjhZpXrkK+EF5XYtAspb8+YSxaw4\nzf4atEm+7Q3N1qwvyfi8T/KQaK7WV6wC513pXTZv8SCtetX/4jBJwA4uUqLh\nXbuO5GcsjNEDmfX91YFKbb2+TvL2kuJkxVVdjeVv+UDLAs8AL+6afVJTe2vB\nmY+9CmSN2egWYDEXgpIowRTXzvasLJ8kQQH0dhseRrnF/k8cxX61VsT0MYEB\nd7mVyXFJE2WrN/HgiVCa9XSzLNn2bp/tyoz3W8TTSCqWOaY2cgbpFBUcBqWY\nmZSkqGqBj0lAJ3qMJw9tfIKiGtLEqsBwRoHTt6yQRsPTTD0wY3WzQTzedpS7\nPKEPDqrqMhDJpjv7vHZyP0E85lSYoDAMYPQ33fYvNbiuIMU4eDxoNJWUImXJ\nTN3uRKDn9QeE8mLTeglLVIu5+4FrDQNNjK6HHcetM89H8F4FGxGl090/H07x\nqc9A2Fe2yCeM6BICsO3BIRt0eClHS6jD15tMDbx9hx4Z4Qt+IgTn0NS4Ebj7\nW1V7qu/d6ajepEVd2kCXQkvJvslxzIGDxXo6OvTN757kROAWoYZNyGefqnou\nHXEH\r\n=IvFh\r\n-----END PGP SIGNATURE-----\r\n", | |||
| "shasum": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a", | |||
| "tarball": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", | |||
| "unpackedSize": 56375 | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.8" | |||
| }, | |||
| "gitHead": "998b265db57a80ae75ea51c55f6a191e2d168a60", | |||
| "homepage": "https://github.com/expressjs/body-parser#readme", | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "body-parser", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/expressjs/body-parser.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/" | |||
| }, | |||
| "version": "1.19.0" | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| 3.1.0 / 2019-01-22 | |||
| ================== | |||
| * Add petabyte (`pb`) support | |||
| 3.0.0 / 2017-08-31 | |||
| ================== | |||
| * Change "kB" to "KB" in format output | |||
| * Remove support for Node.js 0.6 | |||
| * Remove support for ComponentJS | |||
| 2.5.0 / 2017-03-24 | |||
| ================== | |||
| * Add option "unit" | |||
| 2.4.0 / 2016-06-01 | |||
| ================== | |||
| * Add option "unitSeparator" | |||
| 2.3.0 / 2016-02-15 | |||
| ================== | |||
| * Drop partial bytes on all parsed units | |||
| * Fix non-finite numbers to `.format` to return `null` | |||
| * Fix parsing byte string that looks like hex | |||
| * perf: hoist regular expressions | |||
| 2.2.0 / 2015-11-13 | |||
| ================== | |||
| * add option "decimalPlaces" | |||
| * add option "fixedDecimals" | |||
| 2.1.0 / 2015-05-21 | |||
| ================== | |||
| * add `.format` export | |||
| * add `.parse` export | |||
| 2.0.2 / 2015-05-20 | |||
| ================== | |||
| * remove map recreation | |||
| * remove unnecessary object construction | |||
| 2.0.1 / 2015-05-07 | |||
| ================== | |||
| * fix browserify require | |||
| * remove node.extend dependency | |||
| 2.0.0 / 2015-04-12 | |||
| ================== | |||
| * add option "case" | |||
| * add option "thousandsSeparator" | |||
| * return "null" on invalid parse input | |||
| * support proper round-trip: bytes(bytes(num)) === num | |||
| * units no longer case sensitive when parsing | |||
| 1.0.0 / 2014-05-05 | |||
| ================== | |||
| * add negative support. fixes #6 | |||
| 0.3.0 / 2014-03-19 | |||
| ================== | |||
| * added terabyte support | |||
| 0.2.1 / 2013-04-01 | |||
| ================== | |||
| * add .component | |||
| 0.2.0 / 2012-10-28 | |||
| ================== | |||
| * bytes(200).should.eql('200b') | |||
| 0.1.0 / 2012-07-04 | |||
| ================== | |||
| * add bytes to string conversion [yields] | |||
| @@ -0,0 +1,23 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca> | |||
| Copyright (c) 2015 Jed Watson <jed.watson@me.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. | |||
| @@ -0,0 +1,126 @@ | |||
| # Bytes utility | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Utility to parse a string bytes (ex: `1TB`) to bytes (`1099511627776`) and vice-versa. | |||
| ## Installation | |||
| This is a [Node.js](https://nodejs.org/en/) module available through the | |||
| [npm registry](https://www.npmjs.com/). Installation is done using the | |||
| [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | |||
| ```bash | |||
| $ npm install bytes | |||
| ``` | |||
| ## Usage | |||
| ```js | |||
| var bytes = require('bytes'); | |||
| ``` | |||
| #### bytes.format(number value, [options]): string|null | |||
| Format the given value in bytes into a string. If the value is negative, it is kept as such. If it is a float, it is | |||
| rounded. | |||
| **Arguments** | |||
| | Name | Type | Description | | |||
| |---------|----------|--------------------| | |||
| | value | `number` | Value in bytes | | |||
| | options | `Object` | Conversion options | | |||
| **Options** | |||
| | Property | Type | Description | | |||
| |-------------------|--------|-----------------------------------------------------------------------------------------| | |||
| | decimalPlaces | `number`|`null` | Maximum number of decimal places to include in output. Default value to `2`. | | |||
| | fixedDecimals | `boolean`|`null` | Whether to always display the maximum number of decimal places. Default value to `false` | | |||
| | thousandsSeparator | `string`|`null` | Example of values: `' '`, `','` and `.`... Default value to `''`. | | |||
| | unit | `string`|`null` | The unit in which the result will be returned (B/KB/MB/GB/TB). Default value to `''` (which means auto detect). | | |||
| | unitSeparator | `string`|`null` | Separator to use between number and unit. Default value to `''`. | | |||
| **Returns** | |||
| | Name | Type | Description | | |||
| |---------|------------------|-------------------------------------------------| | |||
| | results | `string`|`null` | Return null upon error. String value otherwise. | | |||
| **Example** | |||
| ```js | |||
| bytes(1024); | |||
| // output: '1KB' | |||
| bytes(1000); | |||
| // output: '1000B' | |||
| bytes(1000, {thousandsSeparator: ' '}); | |||
| // output: '1 000B' | |||
| bytes(1024 * 1.7, {decimalPlaces: 0}); | |||
| // output: '2KB' | |||
| bytes(1024, {unitSeparator: ' '}); | |||
| // output: '1 KB' | |||
| ``` | |||
| #### bytes.parse(string|number value): number|null | |||
| Parse the string value into an integer in bytes. If no unit is given, or `value` | |||
| is a number, it is assumed the value is in bytes. | |||
| Supported units and abbreviations are as follows and are case-insensitive: | |||
| * `b` for bytes | |||
| * `kb` for kilobytes | |||
| * `mb` for megabytes | |||
| * `gb` for gigabytes | |||
| * `tb` for terabytes | |||
| * `pb` for petabytes | |||
| The units are in powers of two, not ten. This means 1kb = 1024b according to this parser. | |||
| **Arguments** | |||
| | Name | Type | Description | | |||
| |---------------|--------|--------------------| | |||
| | value | `string`|`number` | String to parse, or number in bytes. | | |||
| **Returns** | |||
| | Name | Type | Description | | |||
| |---------|-------------|-------------------------| | |||
| | results | `number`|`null` | Return null upon error. Value in bytes otherwise. | | |||
| **Example** | |||
| ```js | |||
| bytes('1KB'); | |||
| // output: 1024 | |||
| bytes('1024'); | |||
| // output: 1024 | |||
| bytes(1024); | |||
| // output: 1KB | |||
| ``` | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [coveralls-image]: https://badgen.net/coveralls/c/github/visionmedia/bytes.js/master | |||
| [coveralls-url]: https://coveralls.io/r/visionmedia/bytes.js?branch=master | |||
| [downloads-image]: https://badgen.net/npm/dm/bytes | |||
| [downloads-url]: https://npmjs.org/package/bytes | |||
| [npm-image]: https://badgen.net/npm/node/bytes | |||
| [npm-url]: https://npmjs.org/package/bytes | |||
| [travis-image]: https://badgen.net/travis/visionmedia/bytes.js/master | |||
| [travis-url]: https://travis-ci.org/visionmedia/bytes.js | |||
| @@ -0,0 +1,162 @@ | |||
| /*! | |||
| * bytes | |||
| * Copyright(c) 2012-2014 TJ Holowaychuk | |||
| * Copyright(c) 2015 Jed Watson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict'; | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = bytes; | |||
| module.exports.format = format; | |||
| module.exports.parse = parse; | |||
| /** | |||
| * Module variables. | |||
| * @private | |||
| */ | |||
| var formatThousandsRegExp = /\B(?=(\d{3})+(?!\d))/g; | |||
| var formatDecimalsRegExp = /(?:\.0*|(\.[^0]+)0+)$/; | |||
| var map = { | |||
| b: 1, | |||
| kb: 1 << 10, | |||
| mb: 1 << 20, | |||
| gb: 1 << 30, | |||
| tb: Math.pow(1024, 4), | |||
| pb: Math.pow(1024, 5), | |||
| }; | |||
| var parseRegExp = /^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i; | |||
| /** | |||
| * Convert the given value in bytes into a string or parse to string to an integer in bytes. | |||
| * | |||
| * @param {string|number} value | |||
| * @param {{ | |||
| * case: [string], | |||
| * decimalPlaces: [number] | |||
| * fixedDecimals: [boolean] | |||
| * thousandsSeparator: [string] | |||
| * unitSeparator: [string] | |||
| * }} [options] bytes options. | |||
| * | |||
| * @returns {string|number|null} | |||
| */ | |||
| function bytes(value, options) { | |||
| if (typeof value === 'string') { | |||
| return parse(value); | |||
| } | |||
| if (typeof value === 'number') { | |||
| return format(value, options); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * Format the given value in bytes into a string. | |||
| * | |||
| * If the value is negative, it is kept as such. If it is a float, | |||
| * it is rounded. | |||
| * | |||
| * @param {number} value | |||
| * @param {object} [options] | |||
| * @param {number} [options.decimalPlaces=2] | |||
| * @param {number} [options.fixedDecimals=false] | |||
| * @param {string} [options.thousandsSeparator=] | |||
| * @param {string} [options.unit=] | |||
| * @param {string} [options.unitSeparator=] | |||
| * | |||
| * @returns {string|null} | |||
| * @public | |||
| */ | |||
| function format(value, options) { | |||
| if (!Number.isFinite(value)) { | |||
| return null; | |||
| } | |||
| var mag = Math.abs(value); | |||
| var thousandsSeparator = (options && options.thousandsSeparator) || ''; | |||
| var unitSeparator = (options && options.unitSeparator) || ''; | |||
| var decimalPlaces = (options && options.decimalPlaces !== undefined) ? options.decimalPlaces : 2; | |||
| var fixedDecimals = Boolean(options && options.fixedDecimals); | |||
| var unit = (options && options.unit) || ''; | |||
| if (!unit || !map[unit.toLowerCase()]) { | |||
| if (mag >= map.pb) { | |||
| unit = 'PB'; | |||
| } else if (mag >= map.tb) { | |||
| unit = 'TB'; | |||
| } else if (mag >= map.gb) { | |||
| unit = 'GB'; | |||
| } else if (mag >= map.mb) { | |||
| unit = 'MB'; | |||
| } else if (mag >= map.kb) { | |||
| unit = 'KB'; | |||
| } else { | |||
| unit = 'B'; | |||
| } | |||
| } | |||
| var val = value / map[unit.toLowerCase()]; | |||
| var str = val.toFixed(decimalPlaces); | |||
| if (!fixedDecimals) { | |||
| str = str.replace(formatDecimalsRegExp, '$1'); | |||
| } | |||
| if (thousandsSeparator) { | |||
| str = str.replace(formatThousandsRegExp, thousandsSeparator); | |||
| } | |||
| return str + unitSeparator + unit; | |||
| } | |||
| /** | |||
| * Parse the string value into an integer in bytes. | |||
| * | |||
| * If no unit is given, it is assumed the value is in bytes. | |||
| * | |||
| * @param {number|string} val | |||
| * | |||
| * @returns {number|null} | |||
| * @public | |||
| */ | |||
| function parse(val) { | |||
| if (typeof val === 'number' && !isNaN(val)) { | |||
| return val; | |||
| } | |||
| if (typeof val !== 'string') { | |||
| return null; | |||
| } | |||
| // Test if the string passed is valid | |||
| var results = parseRegExp.exec(val); | |||
| var floatValue; | |||
| var unit = 'b'; | |||
| if (!results) { | |||
| // Nothing could be extracted from the given string | |||
| floatValue = parseInt(val, 10); | |||
| unit = 'b' | |||
| } else { | |||
| // Retrieve the value and the unit | |||
| floatValue = parseFloat(results[1]); | |||
| unit = results[4].toLowerCase(); | |||
| } | |||
| return Math.floor(map[unit] * floatValue); | |||
| } | |||
| @@ -0,0 +1,115 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "bytes@3.1.0", | |||
| "/var/www/noelle.codes/node/node_modules/body-parser" | |||
| ] | |||
| ], | |||
| "_from": "bytes@3.1.0", | |||
| "_hasShrinkwrap": false, | |||
| "_id": "bytes@3.1.0", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/bytes", | |||
| "_nodeVersion": "8.15.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/bytes_3.1.0_1548218614714_0.7781245590502732" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "6.4.1", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "bytes", | |||
| "raw": "bytes@3.1.0", | |||
| "rawSpec": "3.1.0", | |||
| "scope": null, | |||
| "spec": "3.1.0", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/body-parser", | |||
| "/raw-body" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", | |||
| "_shasum": "f6cf7933a360e0588fa9fde85651cdc7f805d1f6", | |||
| "_shrinkwrap": null, | |||
| "_spec": "bytes@3.1.0", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/body-parser", | |||
| "author": { | |||
| "email": "tj@vision-media.ca", | |||
| "name": "TJ Holowaychuk", | |||
| "url": "http://tjholowaychuk.com" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/visionmedia/bytes.js/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Jed Watson", | |||
| "email": "jed.watson@me.com" | |||
| }, | |||
| { | |||
| "name": "Théo FIDRY", | |||
| "email": "theo.fidry@gmail.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "Utility to parse a string bytes to bytes and vice-versa", | |||
| "devDependencies": { | |||
| "eslint": "5.12.1", | |||
| "mocha": "5.2.0", | |||
| "nyc": "13.1.0" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "fileCount": 5, | |||
| "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", | |||
| "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcR/D3CRA9TVsSAnZWagAAKxQP/jm6fmIJFjJzEpnOmOQu\n4tOWELz5luZxpItaWETqZxSAqm0cU4PiqWdkzVV7KJPgKROz6IgtqW4gvya1\nUcI1LlVSQ8zNlu0UiDLOL8yz/MKjeOEdDppglxHN7Dim+tvUVu0hF/4uhuOc\nhAG1ybdaijfeGN6uBM9P6TiqQUpT2AFuS4BUfZoAW4Gfq8fYUG5RW0KsicZB\nJ0IVRreG3KXu9BOoFa+PiGXX+LIG45yE7vMNXbWULyE5vnkBdJJK8L45lFPJ\nSHGKqYK/WIyFEnDBEQgXK9pDsbz9UvPRJFqRfrHyAkfifpTekhpKTNvaj+bC\nvuokTgppKHo8h3l3wFpXKO/Zb/UQFYH1N0dKFO+NSv4gR47Bez6O2Q0Y1ZdE\nHJmZRrFCRzr/m1VT3fZmDwDPJxjZ5kyATliI1lttyOInGlVJg+VR0XFrn0d4\nYOSKxgqTS5jIOPBNZgvt7lYGdBt9TnGk7VYMEdwHm9jfx4Hdj2aEhj3x5mss\nxlVX6q1+5Qg0Am5EWgRMYnODh9Q0oLH4Zaxi4lJr+hSp/6Ln+0IXPNcgT0lj\n+77CxeAxOQG6Aj5G6H5e45x2CGCavny5rsR133vCGBnHGuRcNOSvgZ3BmUvH\n2JB4YSQCAxX/Ku6phJepP0Ktv8gKMWohF+AM2b4oHlUnW4Ny6B7w7PMJoscM\nlFdb\r\n=oAEj\r\n-----END PGP SIGNATURE-----\r\n", | |||
| "shasum": "f6cf7933a360e0588fa9fde85651cdc7f805d1f6", | |||
| "tarball": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", | |||
| "unpackedSize": 10997 | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.8" | |||
| }, | |||
| "gitHead": "49ac709cb210af60e35957c069bb2cd07f335cfd", | |||
| "homepage": "https://github.com/visionmedia/bytes.js#readme", | |||
| "keywords": [ | |||
| "byte", | |||
| "bytes", | |||
| "convert", | |||
| "converter", | |||
| "parse", | |||
| "parser", | |||
| "utility" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| }, | |||
| { | |||
| "name": "tjholowaychuk", | |||
| "email": "tj@vision-media.ca" | |||
| } | |||
| ], | |||
| "name": "bytes", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/visionmedia/bytes.js.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint .", | |||
| "test": "mocha --check-leaks --reporter spec", | |||
| "test-ci": "nyc --reporter=text npm test", | |||
| "test-cov": "nyc --reporter=html --reporter=text npm test" | |||
| }, | |||
| "version": "3.1.0" | |||
| } | |||
| @@ -0,0 +1,55 @@ | |||
| 0.5.3 / 2018-12-17 | |||
| ================== | |||
| * Use `safe-buffer` for improved Buffer API | |||
| 0.5.2 / 2016-12-08 | |||
| ================== | |||
| * Fix `parse` to accept any linear whitespace character | |||
| 0.5.1 / 2016-01-17 | |||
| ================== | |||
| * perf: enable strict mode | |||
| 0.5.0 / 2014-10-11 | |||
| ================== | |||
| * Add `parse` function | |||
| 0.4.0 / 2014-09-21 | |||
| ================== | |||
| * Expand non-Unicode `filename` to the full ISO-8859-1 charset | |||
| 0.3.0 / 2014-09-20 | |||
| ================== | |||
| * Add `fallback` option | |||
| * Add `type` option | |||
| 0.2.0 / 2014-09-19 | |||
| ================== | |||
| * Reduce ambiguity of file names with hex escape in buggy browsers | |||
| 0.1.2 / 2014-09-19 | |||
| ================== | |||
| * Fix periodic invalid Unicode filename header | |||
| 0.1.1 / 2014-09-19 | |||
| ================== | |||
| * Fix invalid characters appearing in `filename*` parameter | |||
| 0.1.0 / 2014-09-18 | |||
| ================== | |||
| * Make the `filename` argument optional | |||
| 0.0.0 / 2014-09-18 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,22 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2014-2017 Douglas Christopher Wilson | |||
| 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. | |||
| @@ -0,0 +1,148 @@ | |||
| # content-disposition | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Create and parse HTTP `Content-Disposition` header | |||
| ## Installation | |||
| ```sh | |||
| $ npm install content-disposition | |||
| ``` | |||
| ## API | |||
| <!-- eslint-disable no-unused-vars --> | |||
| ```js | |||
| var contentDisposition = require('content-disposition') | |||
| ``` | |||
| ### contentDisposition(filename, options) | |||
| Create an attachment `Content-Disposition` header value using the given file name, | |||
| if supplied. The `filename` is optional and if no file name is desired, but you | |||
| want to specify `options`, set `filename` to `undefined`. | |||
| <!-- eslint-disable no-undef --> | |||
| ```js | |||
| res.setHeader('Content-Disposition', contentDisposition('∫ maths.pdf')) | |||
| ``` | |||
| **note** HTTP headers are of the ISO-8859-1 character set. If you are writing this | |||
| header through a means different from `setHeader` in Node.js, you'll want to specify | |||
| the `'binary'` encoding in Node.js. | |||
| #### Options | |||
| `contentDisposition` accepts these properties in the options object. | |||
| ##### fallback | |||
| If the `filename` option is outside ISO-8859-1, then the file name is actually | |||
| stored in a supplemental field for clients that support Unicode file names and | |||
| a ISO-8859-1 version of the file name is automatically generated. | |||
| This specifies the ISO-8859-1 file name to override the automatic generation or | |||
| disables the generation all together, defaults to `true`. | |||
| - A string will specify the ISO-8859-1 file name to use in place of automatic | |||
| generation. | |||
| - `false` will disable including a ISO-8859-1 file name and only include the | |||
| Unicode version (unless the file name is already ISO-8859-1). | |||
| - `true` will enable automatic generation if the file name is outside ISO-8859-1. | |||
| If the `filename` option is ISO-8859-1 and this option is specified and has a | |||
| different value, then the `filename` option is encoded in the extended field | |||
| and this set as the fallback field, even though they are both ISO-8859-1. | |||
| ##### type | |||
| Specifies the disposition type, defaults to `"attachment"`. This can also be | |||
| `"inline"`, or any other value (all values except inline are treated like | |||
| `attachment`, but can convey additional information if both parties agree to | |||
| it). The type is normalized to lower-case. | |||
| ### contentDisposition.parse(string) | |||
| <!-- eslint-disable no-undef, no-unused-vars --> | |||
| ```js | |||
| var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt') | |||
| ``` | |||
| Parse a `Content-Disposition` header string. This automatically handles extended | |||
| ("Unicode") parameters by decoding them and providing them under the standard | |||
| parameter name. This will return an object with the following properties (examples | |||
| are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`): | |||
| - `type`: The disposition type (always lower case). Example: `'attachment'` | |||
| - `parameters`: An object of the parameters in the disposition (name of parameter | |||
| always lower case and extended versions replace non-extended versions). Example: | |||
| `{filename: "€ rates.txt"}` | |||
| ## Examples | |||
| ### Send a file for download | |||
| ```js | |||
| var contentDisposition = require('content-disposition') | |||
| var destroy = require('destroy') | |||
| var fs = require('fs') | |||
| var http = require('http') | |||
| var onFinished = require('on-finished') | |||
| var filePath = '/path/to/public/plans.pdf' | |||
| http.createServer(function onRequest (req, res) { | |||
| // set headers | |||
| res.setHeader('Content-Type', 'application/pdf') | |||
| res.setHeader('Content-Disposition', contentDisposition(filePath)) | |||
| // send file | |||
| var stream = fs.createReadStream(filePath) | |||
| stream.pipe(res) | |||
| onFinished(res, function () { | |||
| destroy(stream) | |||
| }) | |||
| }) | |||
| ``` | |||
| ## Testing | |||
| ```sh | |||
| $ npm test | |||
| ``` | |||
| ## References | |||
| - [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616] | |||
| - [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987] | |||
| - [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266] | |||
| - [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231] | |||
| [rfc-2616]: https://tools.ietf.org/html/rfc2616 | |||
| [rfc-5987]: https://tools.ietf.org/html/rfc5987 | |||
| [rfc-6266]: https://tools.ietf.org/html/rfc6266 | |||
| [tc-2231]: http://greenbytes.de/tech/tc2231/ | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/content-disposition.svg | |||
| [npm-url]: https://npmjs.org/package/content-disposition | |||
| [node-version-image]: https://img.shields.io/node/v/content-disposition.svg | |||
| [node-version-url]: https://nodejs.org/en/download | |||
| [travis-image]: https://img.shields.io/travis/jshttp/content-disposition.svg | |||
| [travis-url]: https://travis-ci.org/jshttp/content-disposition | |||
| [coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg | |||
| [coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master | |||
| [downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg | |||
| [downloads-url]: https://npmjs.org/package/content-disposition | |||
| @@ -0,0 +1,458 @@ | |||
| /*! | |||
| * content-disposition | |||
| * Copyright(c) 2014-2017 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = contentDisposition | |||
| module.exports.parse = parse | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var basename = require('path').basename | |||
| var Buffer = require('safe-buffer').Buffer | |||
| /** | |||
| * RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%") | |||
| * @private | |||
| */ | |||
| var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g // eslint-disable-line no-control-regex | |||
| /** | |||
| * RegExp to match percent encoding escape. | |||
| * @private | |||
| */ | |||
| var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/ | |||
| var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g | |||
| /** | |||
| * RegExp to match non-latin1 characters. | |||
| * @private | |||
| */ | |||
| var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g | |||
| /** | |||
| * RegExp to match quoted-pair in RFC 2616 | |||
| * | |||
| * quoted-pair = "\" CHAR | |||
| * CHAR = <any US-ASCII character (octets 0 - 127)> | |||
| * @private | |||
| */ | |||
| var QESC_REGEXP = /\\([\u0000-\u007f])/g // eslint-disable-line no-control-regex | |||
| /** | |||
| * RegExp to match chars that must be quoted-pair in RFC 2616 | |||
| * @private | |||
| */ | |||
| var QUOTE_REGEXP = /([\\"])/g | |||
| /** | |||
| * RegExp for various RFC 2616 grammar | |||
| * | |||
| * parameter = token "=" ( token | quoted-string ) | |||
| * token = 1*<any CHAR except CTLs or separators> | |||
| * separators = "(" | ")" | "<" | ">" | "@" | |||
| * | "," | ";" | ":" | "\" | <"> | |||
| * | "/" | "[" | "]" | "?" | "=" | |||
| * | "{" | "}" | SP | HT | |||
| * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) | |||
| * qdtext = <any TEXT except <">> | |||
| * quoted-pair = "\" CHAR | |||
| * CHAR = <any US-ASCII character (octets 0 - 127)> | |||
| * TEXT = <any OCTET except CTLs, but including LWS> | |||
| * LWS = [CRLF] 1*( SP | HT ) | |||
| * CRLF = CR LF | |||
| * CR = <US-ASCII CR, carriage return (13)> | |||
| * LF = <US-ASCII LF, linefeed (10)> | |||
| * SP = <US-ASCII SP, space (32)> | |||
| * HT = <US-ASCII HT, horizontal-tab (9)> | |||
| * CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)> | |||
| * OCTET = <any 8-bit sequence of data> | |||
| * @private | |||
| */ | |||
| var PARAM_REGEXP = /;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g // eslint-disable-line no-control-regex | |||
| var TEXT_REGEXP = /^[\x20-\x7e\x80-\xff]+$/ | |||
| var TOKEN_REGEXP = /^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/ | |||
| /** | |||
| * RegExp for various RFC 5987 grammar | |||
| * | |||
| * ext-value = charset "'" [ language ] "'" value-chars | |||
| * charset = "UTF-8" / "ISO-8859-1" / mime-charset | |||
| * mime-charset = 1*mime-charsetc | |||
| * mime-charsetc = ALPHA / DIGIT | |||
| * / "!" / "#" / "$" / "%" / "&" | |||
| * / "+" / "-" / "^" / "_" / "`" | |||
| * / "{" / "}" / "~" | |||
| * language = ( 2*3ALPHA [ extlang ] ) | |||
| * / 4ALPHA | |||
| * / 5*8ALPHA | |||
| * extlang = *3( "-" 3ALPHA ) | |||
| * value-chars = *( pct-encoded / attr-char ) | |||
| * pct-encoded = "%" HEXDIG HEXDIG | |||
| * attr-char = ALPHA / DIGIT | |||
| * / "!" / "#" / "$" / "&" / "+" / "-" / "." | |||
| * / "^" / "_" / "`" / "|" / "~" | |||
| * @private | |||
| */ | |||
| var EXT_VALUE_REGEXP = /^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/ | |||
| /** | |||
| * RegExp for various RFC 6266 grammar | |||
| * | |||
| * disposition-type = "inline" | "attachment" | disp-ext-type | |||
| * disp-ext-type = token | |||
| * disposition-parm = filename-parm | disp-ext-parm | |||
| * filename-parm = "filename" "=" value | |||
| * | "filename*" "=" ext-value | |||
| * disp-ext-parm = token "=" value | |||
| * | ext-token "=" ext-value | |||
| * ext-token = <the characters in token, followed by "*"> | |||
| * @private | |||
| */ | |||
| var DISPOSITION_TYPE_REGEXP = /^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/ // eslint-disable-line no-control-regex | |||
| /** | |||
| * Create an attachment Content-Disposition header. | |||
| * | |||
| * @param {string} [filename] | |||
| * @param {object} [options] | |||
| * @param {string} [options.type=attachment] | |||
| * @param {string|boolean} [options.fallback=true] | |||
| * @return {string} | |||
| * @public | |||
| */ | |||
| function contentDisposition (filename, options) { | |||
| var opts = options || {} | |||
| // get type | |||
| var type = opts.type || 'attachment' | |||
| // get parameters | |||
| var params = createparams(filename, opts.fallback) | |||
| // format into string | |||
| return format(new ContentDisposition(type, params)) | |||
| } | |||
| /** | |||
| * Create parameters object from filename and fallback. | |||
| * | |||
| * @param {string} [filename] | |||
| * @param {string|boolean} [fallback=true] | |||
| * @return {object} | |||
| * @private | |||
| */ | |||
| function createparams (filename, fallback) { | |||
| if (filename === undefined) { | |||
| return | |||
| } | |||
| var params = {} | |||
| if (typeof filename !== 'string') { | |||
| throw new TypeError('filename must be a string') | |||
| } | |||
| // fallback defaults to true | |||
| if (fallback === undefined) { | |||
| fallback = true | |||
| } | |||
| if (typeof fallback !== 'string' && typeof fallback !== 'boolean') { | |||
| throw new TypeError('fallback must be a string or boolean') | |||
| } | |||
| if (typeof fallback === 'string' && NON_LATIN1_REGEXP.test(fallback)) { | |||
| throw new TypeError('fallback must be ISO-8859-1 string') | |||
| } | |||
| // restrict to file base name | |||
| var name = basename(filename) | |||
| // determine if name is suitable for quoted string | |||
| var isQuotedString = TEXT_REGEXP.test(name) | |||
| // generate fallback name | |||
| var fallbackName = typeof fallback !== 'string' | |||
| ? fallback && getlatin1(name) | |||
| : basename(fallback) | |||
| var hasFallback = typeof fallbackName === 'string' && fallbackName !== name | |||
| // set extended filename parameter | |||
| if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) { | |||
| params['filename*'] = name | |||
| } | |||
| // set filename parameter | |||
| if (isQuotedString || hasFallback) { | |||
| params.filename = hasFallback | |||
| ? fallbackName | |||
| : name | |||
| } | |||
| return params | |||
| } | |||
| /** | |||
| * Format object to Content-Disposition header. | |||
| * | |||
| * @param {object} obj | |||
| * @param {string} obj.type | |||
| * @param {object} [obj.parameters] | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function format (obj) { | |||
| var parameters = obj.parameters | |||
| var type = obj.type | |||
| if (!type || typeof type !== 'string' || !TOKEN_REGEXP.test(type)) { | |||
| throw new TypeError('invalid type') | |||
| } | |||
| // start with normalized type | |||
| var string = String(type).toLowerCase() | |||
| // append parameters | |||
| if (parameters && typeof parameters === 'object') { | |||
| var param | |||
| var params = Object.keys(parameters).sort() | |||
| for (var i = 0; i < params.length; i++) { | |||
| param = params[i] | |||
| var val = param.substr(-1) === '*' | |||
| ? ustring(parameters[param]) | |||
| : qstring(parameters[param]) | |||
| string += '; ' + param + '=' + val | |||
| } | |||
| } | |||
| return string | |||
| } | |||
| /** | |||
| * Decode a RFC 6987 field value (gracefully). | |||
| * | |||
| * @param {string} str | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function decodefield (str) { | |||
| var match = EXT_VALUE_REGEXP.exec(str) | |||
| if (!match) { | |||
| throw new TypeError('invalid extended field value') | |||
| } | |||
| var charset = match[1].toLowerCase() | |||
| var encoded = match[2] | |||
| var value | |||
| // to binary string | |||
| var binary = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode) | |||
| switch (charset) { | |||
| case 'iso-8859-1': | |||
| value = getlatin1(binary) | |||
| break | |||
| case 'utf-8': | |||
| value = Buffer.from(binary, 'binary').toString('utf8') | |||
| break | |||
| default: | |||
| throw new TypeError('unsupported charset in extended field') | |||
| } | |||
| return value | |||
| } | |||
| /** | |||
| * Get ISO-8859-1 version of string. | |||
| * | |||
| * @param {string} val | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function getlatin1 (val) { | |||
| // simple Unicode -> ISO-8859-1 transformation | |||
| return String(val).replace(NON_LATIN1_REGEXP, '?') | |||
| } | |||
| /** | |||
| * Parse Content-Disposition header string. | |||
| * | |||
| * @param {string} string | |||
| * @return {object} | |||
| * @public | |||
| */ | |||
| function parse (string) { | |||
| if (!string || typeof string !== 'string') { | |||
| throw new TypeError('argument string is required') | |||
| } | |||
| var match = DISPOSITION_TYPE_REGEXP.exec(string) | |||
| if (!match) { | |||
| throw new TypeError('invalid type format') | |||
| } | |||
| // normalize type | |||
| var index = match[0].length | |||
| var type = match[1].toLowerCase() | |||
| var key | |||
| var names = [] | |||
| var params = {} | |||
| var value | |||
| // calculate index to start at | |||
| index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';' | |||
| ? index - 1 | |||
| : index | |||
| // match parameters | |||
| while ((match = PARAM_REGEXP.exec(string))) { | |||
| if (match.index !== index) { | |||
| throw new TypeError('invalid parameter format') | |||
| } | |||
| index += match[0].length | |||
| key = match[1].toLowerCase() | |||
| value = match[2] | |||
| if (names.indexOf(key) !== -1) { | |||
| throw new TypeError('invalid duplicate parameter') | |||
| } | |||
| names.push(key) | |||
| if (key.indexOf('*') + 1 === key.length) { | |||
| // decode extended value | |||
| key = key.slice(0, -1) | |||
| value = decodefield(value) | |||
| // overwrite existing value | |||
| params[key] = value | |||
| continue | |||
| } | |||
| if (typeof params[key] === 'string') { | |||
| continue | |||
| } | |||
| if (value[0] === '"') { | |||
| // remove quotes and escapes | |||
| value = value | |||
| .substr(1, value.length - 2) | |||
| .replace(QESC_REGEXP, '$1') | |||
| } | |||
| params[key] = value | |||
| } | |||
| if (index !== -1 && index !== string.length) { | |||
| throw new TypeError('invalid parameter format') | |||
| } | |||
| return new ContentDisposition(type, params) | |||
| } | |||
| /** | |||
| * Percent decode a single character. | |||
| * | |||
| * @param {string} str | |||
| * @param {string} hex | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function pdecode (str, hex) { | |||
| return String.fromCharCode(parseInt(hex, 16)) | |||
| } | |||
| /** | |||
| * Percent encode a single character. | |||
| * | |||
| * @param {string} char | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function pencode (char) { | |||
| return '%' + String(char) | |||
| .charCodeAt(0) | |||
| .toString(16) | |||
| .toUpperCase() | |||
| } | |||
| /** | |||
| * Quote a string for HTTP. | |||
| * | |||
| * @param {string} val | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function qstring (val) { | |||
| var str = String(val) | |||
| return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' | |||
| } | |||
| /** | |||
| * Encode a Unicode string for HTTP (RFC 5987). | |||
| * | |||
| * @param {string} val | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function ustring (val) { | |||
| var str = String(val) | |||
| // percent encode as UTF-8 | |||
| var encoded = encodeURIComponent(str) | |||
| .replace(ENCODE_URL_ATTR_CHAR_REGEXP, pencode) | |||
| return 'UTF-8\'\'' + encoded | |||
| } | |||
| /** | |||
| * Class for parsed Content-Disposition header for v8 optimization | |||
| * | |||
| * @public | |||
| * @param {string} type | |||
| * @param {object} parameters | |||
| * @constructor | |||
| */ | |||
| function ContentDisposition (type, parameters) { | |||
| this.type = type | |||
| this.parameters = parameters | |||
| } | |||
| @@ -0,0 +1,105 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "content-disposition@0.5.3", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "content-disposition@0.5.3", | |||
| "_hasShrinkwrap": false, | |||
| "_id": "content-disposition@0.5.3", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/content-disposition", | |||
| "_nodeVersion": "8.14.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/content-disposition_0.5.3_1545077932478_0.35856888210069715" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "6.4.1", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "content-disposition", | |||
| "raw": "content-disposition@0.5.3", | |||
| "rawSpec": "0.5.3", | |||
| "scope": null, | |||
| "spec": "0.5.3", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", | |||
| "_shasum": "e130caf7e7279087c5616c2007d0485698984fbd", | |||
| "_shrinkwrap": null, | |||
| "_spec": "content-disposition@0.5.3", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "Douglas Christopher Wilson" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/jshttp/content-disposition/issues" | |||
| }, | |||
| "dependencies": { | |||
| "safe-buffer": "5.1.2" | |||
| }, | |||
| "description": "Create and parse Content-Disposition header", | |||
| "devDependencies": { | |||
| "deep-equal": "1.0.1", | |||
| "eslint": "5.10.0", | |||
| "eslint-config-standard": "12.0.0", | |||
| "eslint-plugin-import": "2.14.0", | |||
| "eslint-plugin-markdown": "1.0.0-rc.1", | |||
| "eslint-plugin-node": "7.0.1", | |||
| "eslint-plugin-promise": "4.0.1", | |||
| "eslint-plugin-standard": "4.0.0", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "5.2.0" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "fileCount": 5, | |||
| "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", | |||
| "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGAStCRA9TVsSAnZWagAAvYUP/1EacAGPVQ+v81km3r0i\n9KorME5iKSDmfrmTmwPqebr9nzY/KupheRlT5dHnxcrSaLVbWRPdxWIG1YbP\nMel73EUEea8hE+CW5X1ThiEAG/UwaNGH5LI0J/K9WG+AHlPRd7soSrPtZ2gV\nnWWKx9g5tjE4j3qH8fhMb+cmrZOAR5xq19st5w5YC1gchmxJftw+VjuyWneW\nOMylWGW3aBAD1lL3uRgdG+FddffUydUsjshi1U0Dq4Pd4JP/skJBJpnF2DmM\nFtbKJd2X+Ff1632wakl2htvnhpDoRwnY60Xkzuz8GeQqi31j8Ll5rvneEMcA\nl5ZJSW3VHJJYJQ0xCay/snWqCo4M40fwFheunTpsXcvjwNxH8qktRTR/8MxU\nHFWQHOUZrK3iNNOOLV4lo8BaQc+8vvqjkBShxOEs0U9ZVNU1lHD3ieBKjGVB\nM29v2L4RTA0URwNP+5a9GCwFz1BJoOLiZcdMu7VsA7cG4cE4eFfbHW3dl3Tx\nekcfYc0dVI2XQZA02RzHNHrgy+gUrpZtp+takxq5buU7fSMX327eJLyOhGzM\n63bThVu5bH7CpOzRvbZNkupDbWgHfue16RKouL0Hr4+lrYdc4TuU8HLCYs+K\n5SP+gtxAvbs6FDp5IOf8OptfYYQsi26GOnW5AzcyeHUyPWFLkT5sLb4Ihi7s\nwfu6\r\n=iuNE\r\n-----END PGP SIGNATURE-----\r\n", | |||
| "shasum": "e130caf7e7279087c5616c2007d0485698984fbd", | |||
| "tarball": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", | |||
| "unpackedSize": 19115 | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "gitHead": "f6d7cba7ea09dfea1492d5ffe438fe2f2e3cc3bb", | |||
| "homepage": "https://github.com/jshttp/content-disposition#readme", | |||
| "keywords": [ | |||
| "content-disposition", | |||
| "http", | |||
| "res", | |||
| "rfc6266" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "content-disposition", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jshttp/content-disposition.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --reporter spec --bail --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | |||
| }, | |||
| "version": "0.5.3" | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| 1.0.4 / 2017-09-11 | |||
| ================== | |||
| * perf: skip parameter parsing when no parameters | |||
| 1.0.3 / 2017-09-10 | |||
| ================== | |||
| * perf: remove argument reassignment | |||
| 1.0.2 / 2016-05-09 | |||
| ================== | |||
| * perf: enable strict mode | |||
| 1.0.1 / 2015-02-13 | |||
| ================== | |||
| * Improve missing `Content-Type` header error message | |||
| 1.0.0 / 2015-02-01 | |||
| ================== | |||
| * Initial implementation, derived from `media-typer@0.3.0` | |||
| @@ -0,0 +1,22 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2015 Douglas Christopher Wilson | |||
| 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. | |||
| @@ -0,0 +1,92 @@ | |||
| # content-type | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Create and parse HTTP Content-Type header according to RFC 7231 | |||
| ## Installation | |||
| ```sh | |||
| $ npm install content-type | |||
| ``` | |||
| ## API | |||
| ```js | |||
| var contentType = require('content-type') | |||
| ``` | |||
| ### contentType.parse(string) | |||
| ```js | |||
| var obj = contentType.parse('image/svg+xml; charset=utf-8') | |||
| ``` | |||
| Parse a content type string. This will return an object with the following | |||
| properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`): | |||
| - `type`: The media type (the type and subtype, always lower case). | |||
| Example: `'image/svg+xml'` | |||
| - `parameters`: An object of the parameters in the media type (name of parameter | |||
| always lower case). Example: `{charset: 'utf-8'}` | |||
| Throws a `TypeError` if the string is missing or invalid. | |||
| ### contentType.parse(req) | |||
| ```js | |||
| var obj = contentType.parse(req) | |||
| ``` | |||
| Parse the `content-type` header from the given `req`. Short-cut for | |||
| `contentType.parse(req.headers['content-type'])`. | |||
| Throws a `TypeError` if the `Content-Type` header is missing or invalid. | |||
| ### contentType.parse(res) | |||
| ```js | |||
| var obj = contentType.parse(res) | |||
| ``` | |||
| Parse the `content-type` header set on the given `res`. Short-cut for | |||
| `contentType.parse(res.getHeader('content-type'))`. | |||
| Throws a `TypeError` if the `Content-Type` header is missing or invalid. | |||
| ### contentType.format(obj) | |||
| ```js | |||
| var str = contentType.format({type: 'image/svg+xml'}) | |||
| ``` | |||
| Format an object into a content type string. This will return a string of the | |||
| content type for the given object with the following properties (examples are | |||
| shown that produce the string `'image/svg+xml; charset=utf-8'`): | |||
| - `type`: The media type (will be lower-cased). Example: `'image/svg+xml'` | |||
| - `parameters`: An object of the parameters in the media type (name of the | |||
| parameter will be lower-cased). Example: `{charset: 'utf-8'}` | |||
| Throws a `TypeError` if the object contains an invalid type or parameter names. | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/content-type.svg | |||
| [npm-url]: https://npmjs.org/package/content-type | |||
| [node-version-image]: https://img.shields.io/node/v/content-type.svg | |||
| [node-version-url]: http://nodejs.org/download/ | |||
| [travis-image]: https://img.shields.io/travis/jshttp/content-type/master.svg | |||
| [travis-url]: https://travis-ci.org/jshttp/content-type | |||
| [coveralls-image]: https://img.shields.io/coveralls/jshttp/content-type/master.svg | |||
| [coveralls-url]: https://coveralls.io/r/jshttp/content-type | |||
| [downloads-image]: https://img.shields.io/npm/dm/content-type.svg | |||
| [downloads-url]: https://npmjs.org/package/content-type | |||
| @@ -0,0 +1,222 @@ | |||
| /*! | |||
| * content-type | |||
| * Copyright(c) 2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1 | |||
| * | |||
| * parameter = token "=" ( token / quoted-string ) | |||
| * token = 1*tchar | |||
| * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" | |||
| * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" | |||
| * / DIGIT / ALPHA | |||
| * ; any VCHAR, except delimiters | |||
| * quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE | |||
| * qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text | |||
| * obs-text = %x80-FF | |||
| * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) | |||
| */ | |||
| var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g | |||
| var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/ | |||
| var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ | |||
| /** | |||
| * RegExp to match quoted-pair in RFC 7230 sec 3.2.6 | |||
| * | |||
| * quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text ) | |||
| * obs-text = %x80-FF | |||
| */ | |||
| var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g | |||
| /** | |||
| * RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6 | |||
| */ | |||
| var QUOTE_REGEXP = /([\\"])/g | |||
| /** | |||
| * RegExp to match type in RFC 7231 sec 3.1.1.1 | |||
| * | |||
| * media-type = type "/" subtype | |||
| * type = token | |||
| * subtype = token | |||
| */ | |||
| var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/ | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| exports.format = format | |||
| exports.parse = parse | |||
| /** | |||
| * Format object to media type. | |||
| * | |||
| * @param {object} obj | |||
| * @return {string} | |||
| * @public | |||
| */ | |||
| function format (obj) { | |||
| if (!obj || typeof obj !== 'object') { | |||
| throw new TypeError('argument obj is required') | |||
| } | |||
| var parameters = obj.parameters | |||
| var type = obj.type | |||
| if (!type || !TYPE_REGEXP.test(type)) { | |||
| throw new TypeError('invalid type') | |||
| } | |||
| var string = type | |||
| // append parameters | |||
| if (parameters && typeof parameters === 'object') { | |||
| var param | |||
| var params = Object.keys(parameters).sort() | |||
| for (var i = 0; i < params.length; i++) { | |||
| param = params[i] | |||
| if (!TOKEN_REGEXP.test(param)) { | |||
| throw new TypeError('invalid parameter name') | |||
| } | |||
| string += '; ' + param + '=' + qstring(parameters[param]) | |||
| } | |||
| } | |||
| return string | |||
| } | |||
| /** | |||
| * Parse media type to object. | |||
| * | |||
| * @param {string|object} string | |||
| * @return {Object} | |||
| * @public | |||
| */ | |||
| function parse (string) { | |||
| if (!string) { | |||
| throw new TypeError('argument string is required') | |||
| } | |||
| // support req/res-like objects as argument | |||
| var header = typeof string === 'object' | |||
| ? getcontenttype(string) | |||
| : string | |||
| if (typeof header !== 'string') { | |||
| throw new TypeError('argument string is required to be a string') | |||
| } | |||
| var index = header.indexOf(';') | |||
| var type = index !== -1 | |||
| ? header.substr(0, index).trim() | |||
| : header.trim() | |||
| if (!TYPE_REGEXP.test(type)) { | |||
| throw new TypeError('invalid media type') | |||
| } | |||
| var obj = new ContentType(type.toLowerCase()) | |||
| // parse parameters | |||
| if (index !== -1) { | |||
| var key | |||
| var match | |||
| var value | |||
| PARAM_REGEXP.lastIndex = index | |||
| while ((match = PARAM_REGEXP.exec(header))) { | |||
| if (match.index !== index) { | |||
| throw new TypeError('invalid parameter format') | |||
| } | |||
| index += match[0].length | |||
| key = match[1].toLowerCase() | |||
| value = match[2] | |||
| if (value[0] === '"') { | |||
| // remove quotes and escapes | |||
| value = value | |||
| .substr(1, value.length - 2) | |||
| .replace(QESC_REGEXP, '$1') | |||
| } | |||
| obj.parameters[key] = value | |||
| } | |||
| if (index !== header.length) { | |||
| throw new TypeError('invalid parameter format') | |||
| } | |||
| } | |||
| return obj | |||
| } | |||
| /** | |||
| * Get content-type from req/res objects. | |||
| * | |||
| * @param {object} | |||
| * @return {Object} | |||
| * @private | |||
| */ | |||
| function getcontenttype (obj) { | |||
| var header | |||
| if (typeof obj.getHeader === 'function') { | |||
| // res-like | |||
| header = obj.getHeader('content-type') | |||
| } else if (typeof obj.headers === 'object') { | |||
| // req-like | |||
| header = obj.headers && obj.headers['content-type'] | |||
| } | |||
| if (typeof header !== 'string') { | |||
| throw new TypeError('content-type header is missing from object') | |||
| } | |||
| return header | |||
| } | |||
| /** | |||
| * Quote a string if necessary. | |||
| * | |||
| * @param {string} val | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function qstring (val) { | |||
| var str = String(val) | |||
| // no need to quote tokens | |||
| if (TOKEN_REGEXP.test(str)) { | |||
| return str | |||
| } | |||
| if (str.length > 0 && !TEXT_REGEXP.test(str)) { | |||
| throw new TypeError('invalid parameter value') | |||
| } | |||
| return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"' | |||
| } | |||
| /** | |||
| * Class to represent a content type. | |||
| * @private | |||
| */ | |||
| function ContentType (type) { | |||
| this.parameters = Object.create(null) | |||
| this.type = type | |||
| } | |||
| @@ -0,0 +1,105 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "content-type@~1.0.4", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "content-type@>=1.0.4 <1.1.0", | |||
| "_id": "content-type@1.0.4", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/content-type", | |||
| "_nodeVersion": "6.11.3", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/content-type-1.0.4.tgz_1505166155546_0.06956395204178989" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "5.3.0", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "content-type", | |||
| "raw": "content-type@~1.0.4", | |||
| "rawSpec": "~1.0.4", | |||
| "scope": null, | |||
| "spec": ">=1.0.4 <1.1.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/body-parser", | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", | |||
| "_shasum": "e138cc75e040c727b1966fe5e5f8c9aee256fe3b", | |||
| "_shrinkwrap": null, | |||
| "_spec": "content-type@~1.0.4", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "Douglas Christopher Wilson" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/jshttp/content-type/issues" | |||
| }, | |||
| "dependencies": {}, | |||
| "description": "Create and parse HTTP Content-Type header", | |||
| "devDependencies": { | |||
| "eslint": "3.19.0", | |||
| "eslint-config-standard": "10.2.1", | |||
| "eslint-plugin-import": "2.7.0", | |||
| "eslint-plugin-node": "5.1.1", | |||
| "eslint-plugin-promise": "3.5.0", | |||
| "eslint-plugin-standard": "3.0.1", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "~1.21.5" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", | |||
| "shasum": "e138cc75e040c727b1966fe5e5f8c9aee256fe3b", | |||
| "tarball": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "files": [ | |||
| "HISTORY.md", | |||
| "LICENSE", | |||
| "README.md", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "d22f8ac6c407789c906bd6fed137efde8f772b09", | |||
| "homepage": "https://github.com/jshttp/content-type#readme", | |||
| "keywords": [ | |||
| "content-type", | |||
| "http", | |||
| "req", | |||
| "res", | |||
| "rfc7231" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "content-type", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jshttp/content-type.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint .", | |||
| "test": "mocha --reporter spec --check-leaks --bail test/", | |||
| "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" | |||
| }, | |||
| "version": "1.0.4" | |||
| } | |||
| @@ -0,0 +1,4 @@ | |||
| support | |||
| test | |||
| examples | |||
| *.sock | |||
| @@ -0,0 +1,38 @@ | |||
| 1.0.6 / 2015-02-03 | |||
| ================== | |||
| * use `npm test` instead of `make test` to run tests | |||
| * clearer assertion messages when checking input | |||
| 1.0.5 / 2014-09-05 | |||
| ================== | |||
| * add license to package.json | |||
| 1.0.4 / 2014-06-25 | |||
| ================== | |||
| * corrected avoidance of timing attacks (thanks @tenbits!) | |||
| 1.0.3 / 2014-01-28 | |||
| ================== | |||
| * [incorrect] fix for timing attacks | |||
| 1.0.2 / 2014-01-28 | |||
| ================== | |||
| * fix missing repository warning | |||
| * fix typo in test | |||
| 1.0.1 / 2013-04-15 | |||
| ================== | |||
| * Revert "Changed underlying HMAC algo. to sha512." | |||
| * Revert "Fix for timing attacks on MAC verification." | |||
| 0.0.1 / 2010-01-03 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,42 @@ | |||
| # cookie-signature | |||
| Sign and unsign cookies. | |||
| ## Example | |||
| ```js | |||
| var cookie = require('cookie-signature'); | |||
| var val = cookie.sign('hello', 'tobiiscool'); | |||
| val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI'); | |||
| var val = cookie.sign('hello', 'tobiiscool'); | |||
| cookie.unsign(val, 'tobiiscool').should.equal('hello'); | |||
| cookie.unsign(val, 'luna').should.be.false; | |||
| ``` | |||
| ## License | |||
| (The MIT License) | |||
| Copyright (c) 2012 LearnBoost <tj@learnboost.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. | |||
| @@ -0,0 +1,51 @@ | |||
| /** | |||
| * Module dependencies. | |||
| */ | |||
| var crypto = require('crypto'); | |||
| /** | |||
| * Sign the given `val` with `secret`. | |||
| * | |||
| * @param {String} val | |||
| * @param {String} secret | |||
| * @return {String} | |||
| * @api private | |||
| */ | |||
| exports.sign = function(val, secret){ | |||
| if ('string' != typeof val) throw new TypeError("Cookie value must be provided as a string."); | |||
| if ('string' != typeof secret) throw new TypeError("Secret string must be provided."); | |||
| return val + '.' + crypto | |||
| .createHmac('sha256', secret) | |||
| .update(val) | |||
| .digest('base64') | |||
| .replace(/\=+$/, ''); | |||
| }; | |||
| /** | |||
| * Unsign and decode the given `val` with `secret`, | |||
| * returning `false` if the signature is invalid. | |||
| * | |||
| * @param {String} val | |||
| * @param {String} secret | |||
| * @return {String|Boolean} | |||
| * @api private | |||
| */ | |||
| exports.unsign = function(val, secret){ | |||
| if ('string' != typeof val) throw new TypeError("Signed cookie string must be provided."); | |||
| if ('string' != typeof secret) throw new TypeError("Secret string must be provided."); | |||
| var str = val.slice(0, val.lastIndexOf('.')) | |||
| , mac = exports.sign(str, secret); | |||
| return sha1(mac) == sha1(val) ? str : false; | |||
| }; | |||
| /** | |||
| * Private | |||
| */ | |||
| function sha1(str){ | |||
| return crypto.createHash('sha1').update(str).digest('hex'); | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "cookie-signature@1.0.6", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "cookie-signature@1.0.6", | |||
| "_id": "cookie-signature@1.0.6", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/cookie-signature", | |||
| "_nodeVersion": "0.10.36", | |||
| "_npmUser": { | |||
| "email": "natevw@yahoo.com", | |||
| "name": "natevw" | |||
| }, | |||
| "_npmVersion": "2.3.0", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "cookie-signature", | |||
| "raw": "cookie-signature@1.0.6", | |||
| "rawSpec": "1.0.6", | |||
| "scope": null, | |||
| "spec": "1.0.6", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | |||
| "_shasum": "e303a882b342cc3ee8ca513a79999734dab3ae2c", | |||
| "_shrinkwrap": null, | |||
| "_spec": "cookie-signature@1.0.6", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "tj@learnboost.com", | |||
| "name": "TJ Holowaychuk" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/visionmedia/node-cookie-signature/issues" | |||
| }, | |||
| "dependencies": {}, | |||
| "description": "Sign and unsign cookies", | |||
| "devDependencies": { | |||
| "mocha": "*", | |||
| "should": "*" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "e303a882b342cc3ee8ca513a79999734dab3ae2c", | |||
| "tarball": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" | |||
| }, | |||
| "gitHead": "391b56cf44d88c493491b7e3fc53208cfb976d2a", | |||
| "homepage": "https://github.com/visionmedia/node-cookie-signature", | |||
| "keywords": [ | |||
| "cookie", | |||
| "sign", | |||
| "unsign" | |||
| ], | |||
| "license": "MIT", | |||
| "main": "index", | |||
| "maintainers": [ | |||
| { | |||
| "name": "tjholowaychuk", | |||
| "email": "tj@vision-media.ca" | |||
| }, | |||
| { | |||
| "name": "natevw", | |||
| "email": "natevw@yahoo.com" | |||
| } | |||
| ], | |||
| "name": "cookie-signature", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/visionmedia/node-cookie-signature.git" | |||
| }, | |||
| "scripts": { | |||
| "test": "mocha --require should --reporter spec" | |||
| }, | |||
| "version": "1.0.6" | |||
| } | |||
| @@ -0,0 +1,123 @@ | |||
| 0.4.0 / 2019-05-15 | |||
| ================== | |||
| * Add `SameSite=None` support | |||
| 0.3.1 / 2016-05-26 | |||
| ================== | |||
| * Fix `sameSite: true` to work with draft-7 clients | |||
| - `true` now sends `SameSite=Strict` instead of `SameSite` | |||
| 0.3.0 / 2016-05-26 | |||
| ================== | |||
| * Add `sameSite` option | |||
| - Replaces `firstPartyOnly` option, never implemented by browsers | |||
| * Improve error message when `encode` is not a function | |||
| * Improve error message when `expires` is not a `Date` | |||
| 0.2.4 / 2016-05-20 | |||
| ================== | |||
| * perf: enable strict mode | |||
| * perf: use for loop in parse | |||
| * perf: use string concatination for serialization | |||
| 0.2.3 / 2015-10-25 | |||
| ================== | |||
| * Fix cookie `Max-Age` to never be a floating point number | |||
| 0.2.2 / 2015-09-17 | |||
| ================== | |||
| * Fix regression when setting empty cookie value | |||
| - Ease the new restriction, which is just basic header-level validation | |||
| * Fix typo in invalid value errors | |||
| 0.2.1 / 2015-09-17 | |||
| ================== | |||
| * Throw on invalid values provided to `serialize` | |||
| - Ensures the resulting string is a valid HTTP header value | |||
| 0.2.0 / 2015-08-13 | |||
| ================== | |||
| * Add `firstPartyOnly` option | |||
| * Throw better error for invalid argument to parse | |||
| * perf: hoist regular expression | |||
| 0.1.5 / 2015-09-17 | |||
| ================== | |||
| * Fix regression when setting empty cookie value | |||
| - Ease the new restriction, which is just basic header-level validation | |||
| * Fix typo in invalid value errors | |||
| 0.1.4 / 2015-09-17 | |||
| ================== | |||
| * Throw better error for invalid argument to parse | |||
| * Throw on invalid values provided to `serialize` | |||
| - Ensures the resulting string is a valid HTTP header value | |||
| 0.1.3 / 2015-05-19 | |||
| ================== | |||
| * Reduce the scope of try-catch deopt | |||
| * Remove argument reassignments | |||
| 0.1.2 / 2014-04-16 | |||
| ================== | |||
| * Remove unnecessary files from npm package | |||
| 0.1.1 / 2014-02-23 | |||
| ================== | |||
| * Fix bad parse when cookie value contained a comma | |||
| * Fix support for `maxAge` of `0` | |||
| 0.1.0 / 2013-05-01 | |||
| ================== | |||
| * Add `decode` option | |||
| * Add `encode` option | |||
| 0.0.6 / 2013-04-08 | |||
| ================== | |||
| * Ignore cookie parts missing `=` | |||
| 0.0.5 / 2012-10-29 | |||
| ================== | |||
| * Return raw cookie value if value unescape errors | |||
| 0.0.4 / 2012-06-21 | |||
| ================== | |||
| * Use encode/decodeURIComponent for cookie encoding/decoding | |||
| - Improve server/client interoperability | |||
| 0.0.3 / 2012-06-06 | |||
| ================== | |||
| * Only escape special characters per the cookie RFC | |||
| 0.0.2 / 2012-06-01 | |||
| ================== | |||
| * Fix `maxAge` option to not throw error | |||
| 0.0.1 / 2012-05-28 | |||
| ================== | |||
| * Add more tests | |||
| 0.0.0 / 2012-05-28 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,24 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com> | |||
| Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.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. | |||
| @@ -0,0 +1,253 @@ | |||
| # cookie | |||
| [![NPM Version][npm-version-image]][npm-url] | |||
| [![NPM Downloads][npm-downloads-image]][npm-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Basic HTTP cookie parser and serializer for HTTP servers. | |||
| ## Installation | |||
| ```sh | |||
| $ npm install cookie | |||
| ``` | |||
| ## API | |||
| ```js | |||
| var cookie = require('cookie'); | |||
| ``` | |||
| ### cookie.parse(str, options) | |||
| Parse an HTTP `Cookie` header string and returning an object of all cookie name-value pairs. | |||
| The `str` argument is the string representing a `Cookie` header value and `options` is an | |||
| optional object containing additional parsing options. | |||
| ```js | |||
| var cookies = cookie.parse('foo=bar; equation=E%3Dmc%5E2'); | |||
| // { foo: 'bar', equation: 'E=mc^2' } | |||
| ``` | |||
| #### Options | |||
| `cookie.parse` accepts these properties in the options object. | |||
| ##### decode | |||
| Specifies a function that will be used to decode a cookie's value. Since the value of a cookie | |||
| has a limited character set (and must be a simple string), this function can be used to decode | |||
| a previously-encoded cookie value into a JavaScript string or other object. | |||
| The default function is the global `decodeURIComponent`, which will decode any URL-encoded | |||
| sequences into their byte representations. | |||
| **note** if an error is thrown from this function, the original, non-decoded cookie value will | |||
| be returned as the cookie's value. | |||
| ### cookie.serialize(name, value, options) | |||
| Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the | |||
| name for the cookie, the `value` argument is the value to set the cookie to, and the `options` | |||
| argument is an optional object containing additional serialization options. | |||
| ```js | |||
| var setCookie = cookie.serialize('foo', 'bar'); | |||
| // foo=bar | |||
| ``` | |||
| #### Options | |||
| `cookie.serialize` accepts these properties in the options object. | |||
| ##### domain | |||
| Specifies the value for the [`Domain` `Set-Cookie` attribute][rfc-6265-5.2.3]. By default, no | |||
| domain is set, and most clients will consider the cookie to apply to only the current domain. | |||
| ##### encode | |||
| Specifies a function that will be used to encode a cookie's value. Since value of a cookie | |||
| has a limited character set (and must be a simple string), this function can be used to encode | |||
| a value into a string suited for a cookie's value. | |||
| The default function is the global `encodeURIComponent`, which will encode a JavaScript string | |||
| into UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range. | |||
| ##### expires | |||
| Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute][rfc-6265-5.2.1]. | |||
| By default, no expiration is set, and most clients will consider this a "non-persistent cookie" and | |||
| will delete it on a condition like exiting a web browser application. | |||
| **note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and | |||
| `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, | |||
| so if both are set, they should point to the same date and time. | |||
| ##### httpOnly | |||
| Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute][rfc-6265-5.2.6]. When truthy, | |||
| the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly` attribute is not set. | |||
| **note** be careful when setting this to `true`, as compliant clients will not allow client-side | |||
| JavaScript to see the cookie in `document.cookie`. | |||
| ##### maxAge | |||
| Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute][rfc-6265-5.2.2]. | |||
| The given number will be converted to an integer by rounding down. By default, no maximum age is set. | |||
| **note** the [cookie storage model specification][rfc-6265-5.3] states that if both `expires` and | |||
| `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, | |||
| so if both are set, they should point to the same date and time. | |||
| ##### path | |||
| Specifies the value for the [`Path` `Set-Cookie` attribute][rfc-6265-5.2.4]. By default, the path | |||
| is considered the ["default path"][rfc-6265-5.1.4]. | |||
| ##### sameSite | |||
| Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][rfc-6265bis-03-4.1.2.7]. | |||
| - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement. | |||
| - `false` will not set the `SameSite` attribute. | |||
| - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement. | |||
| - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie. | |||
| - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement. | |||
| More information about the different enforcement levels can be found in | |||
| [the specification][rfc-6265bis-03-4.1.2.7]. | |||
| **note** This is an attribute that has not yet been fully standardized, and may change in the future. | |||
| This also means many clients may ignore this attribute until they understand it. | |||
| ##### secure | |||
| Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute][rfc-6265-5.2.5]. When truthy, | |||
| the `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. | |||
| **note** be careful when setting this to `true`, as compliant clients will not send the cookie back to | |||
| the server in the future if the browser does not have an HTTPS connection. | |||
| ## Example | |||
| The following example uses this module in conjunction with the Node.js core HTTP server | |||
| to prompt a user for their name and display it back on future visits. | |||
| ```js | |||
| var cookie = require('cookie'); | |||
| var escapeHtml = require('escape-html'); | |||
| var http = require('http'); | |||
| var url = require('url'); | |||
| function onRequest(req, res) { | |||
| // Parse the query string | |||
| var query = url.parse(req.url, true, true).query; | |||
| if (query && query.name) { | |||
| // Set a new cookie with the name | |||
| res.setHeader('Set-Cookie', cookie.serialize('name', String(query.name), { | |||
| httpOnly: true, | |||
| maxAge: 60 * 60 * 24 * 7 // 1 week | |||
| })); | |||
| // Redirect back after setting cookie | |||
| res.statusCode = 302; | |||
| res.setHeader('Location', req.headers.referer || '/'); | |||
| res.end(); | |||
| return; | |||
| } | |||
| // Parse the cookies on the request | |||
| var cookies = cookie.parse(req.headers.cookie || ''); | |||
| // Get the visitor name set in the cookie | |||
| var name = cookies.name; | |||
| res.setHeader('Content-Type', 'text/html; charset=UTF-8'); | |||
| if (name) { | |||
| res.write('<p>Welcome back, <b>' + escapeHtml(name) + '</b>!</p>'); | |||
| } else { | |||
| res.write('<p>Hello, new visitor!</p>'); | |||
| } | |||
| res.write('<form method="GET">'); | |||
| res.write('<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">'); | |||
| res.end('</form>'); | |||
| } | |||
| http.createServer(onRequest).listen(3000); | |||
| ``` | |||
| ## Testing | |||
| ```sh | |||
| $ npm test | |||
| ``` | |||
| ## Benchmark | |||
| ``` | |||
| $ npm run bench | |||
| > cookie@0.3.1 bench cookie | |||
| > node benchmark/index.js | |||
| http_parser@2.8.0 | |||
| node@6.14.2 | |||
| v8@5.1.281.111 | |||
| uv@1.16.1 | |||
| zlib@1.2.11 | |||
| ares@1.10.1-DEV | |||
| icu@58.2 | |||
| modules@48 | |||
| napi@3 | |||
| openssl@1.0.2o | |||
| > node benchmark/parse.js | |||
| cookie.parse | |||
| 6 tests completed. | |||
| simple x 1,200,691 ops/sec ±1.12% (189 runs sampled) | |||
| decode x 1,012,994 ops/sec ±0.97% (186 runs sampled) | |||
| unquote x 1,074,174 ops/sec ±2.43% (186 runs sampled) | |||
| duplicates x 438,424 ops/sec ±2.17% (184 runs sampled) | |||
| 10 cookies x 147,154 ops/sec ±1.01% (186 runs sampled) | |||
| 100 cookies x 14,274 ops/sec ±1.07% (187 runs sampled) | |||
| ``` | |||
| ## References | |||
| - [RFC 6265: HTTP State Management Mechanism][rfc-6265] | |||
| - [Same-site Cookies][rfc-6265bis-03-4.1.2.7] | |||
| [rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7 | |||
| [rfc-6265]: https://tools.ietf.org/html/rfc6265 | |||
| [rfc-6265-5.1.4]: https://tools.ietf.org/html/rfc6265#section-5.1.4 | |||
| [rfc-6265-5.2.1]: https://tools.ietf.org/html/rfc6265#section-5.2.1 | |||
| [rfc-6265-5.2.2]: https://tools.ietf.org/html/rfc6265#section-5.2.2 | |||
| [rfc-6265-5.2.3]: https://tools.ietf.org/html/rfc6265#section-5.2.3 | |||
| [rfc-6265-5.2.4]: https://tools.ietf.org/html/rfc6265#section-5.2.4 | |||
| [rfc-6265-5.2.5]: https://tools.ietf.org/html/rfc6265#section-5.2.5 | |||
| [rfc-6265-5.2.6]: https://tools.ietf.org/html/rfc6265#section-5.2.6 | |||
| [rfc-6265-5.3]: https://tools.ietf.org/html/rfc6265#section-5.3 | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/cookie/master | |||
| [coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master | |||
| [node-version-image]: https://badgen.net/npm/node/cookie | |||
| [node-version-url]: https://nodejs.org/en/download | |||
| [npm-downloads-image]: https://badgen.net/npm/dm/cookie | |||
| [npm-url]: https://npmjs.org/package/cookie | |||
| [npm-version-image]: https://badgen.net/npm/v/cookie | |||
| [travis-image]: https://badgen.net/travis/jshttp/cookie/master | |||
| [travis-url]: https://travis-ci.org/jshttp/cookie | |||
| @@ -0,0 +1,198 @@ | |||
| /*! | |||
| * cookie | |||
| * Copyright(c) 2012-2014 Roman Shtylman | |||
| * Copyright(c) 2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict'; | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| exports.parse = parse; | |||
| exports.serialize = serialize; | |||
| /** | |||
| * Module variables. | |||
| * @private | |||
| */ | |||
| var decode = decodeURIComponent; | |||
| var encode = encodeURIComponent; | |||
| var pairSplitRegExp = /; */; | |||
| /** | |||
| * RegExp to match field-content in RFC 7230 sec 3.2 | |||
| * | |||
| * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] | |||
| * field-vchar = VCHAR / obs-text | |||
| * obs-text = %x80-FF | |||
| */ | |||
| var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; | |||
| /** | |||
| * Parse a cookie header. | |||
| * | |||
| * Parse the given cookie header string into an object | |||
| * The object has the various cookies as keys(names) => values | |||
| * | |||
| * @param {string} str | |||
| * @param {object} [options] | |||
| * @return {object} | |||
| * @public | |||
| */ | |||
| function parse(str, options) { | |||
| if (typeof str !== 'string') { | |||
| throw new TypeError('argument str must be a string'); | |||
| } | |||
| var obj = {} | |||
| var opt = options || {}; | |||
| var pairs = str.split(pairSplitRegExp); | |||
| var dec = opt.decode || decode; | |||
| for (var i = 0; i < pairs.length; i++) { | |||
| var pair = pairs[i]; | |||
| var eq_idx = pair.indexOf('='); | |||
| // skip things that don't look like key=value | |||
| if (eq_idx < 0) { | |||
| continue; | |||
| } | |||
| var key = pair.substr(0, eq_idx).trim() | |||
| var val = pair.substr(++eq_idx, pair.length).trim(); | |||
| // quoted values | |||
| if ('"' == val[0]) { | |||
| val = val.slice(1, -1); | |||
| } | |||
| // only assign once | |||
| if (undefined == obj[key]) { | |||
| obj[key] = tryDecode(val, dec); | |||
| } | |||
| } | |||
| return obj; | |||
| } | |||
| /** | |||
| * Serialize data into a cookie header. | |||
| * | |||
| * Serialize the a name value pair into a cookie string suitable for | |||
| * http headers. An optional options object specified cookie parameters. | |||
| * | |||
| * serialize('foo', 'bar', { httpOnly: true }) | |||
| * => "foo=bar; httpOnly" | |||
| * | |||
| * @param {string} name | |||
| * @param {string} val | |||
| * @param {object} [options] | |||
| * @return {string} | |||
| * @public | |||
| */ | |||
| function serialize(name, val, options) { | |||
| var opt = options || {}; | |||
| var enc = opt.encode || encode; | |||
| if (typeof enc !== 'function') { | |||
| throw new TypeError('option encode is invalid'); | |||
| } | |||
| if (!fieldContentRegExp.test(name)) { | |||
| throw new TypeError('argument name is invalid'); | |||
| } | |||
| var value = enc(val); | |||
| if (value && !fieldContentRegExp.test(value)) { | |||
| throw new TypeError('argument val is invalid'); | |||
| } | |||
| var str = name + '=' + value; | |||
| if (null != opt.maxAge) { | |||
| var maxAge = opt.maxAge - 0; | |||
| if (isNaN(maxAge)) throw new Error('maxAge should be a Number'); | |||
| str += '; Max-Age=' + Math.floor(maxAge); | |||
| } | |||
| if (opt.domain) { | |||
| if (!fieldContentRegExp.test(opt.domain)) { | |||
| throw new TypeError('option domain is invalid'); | |||
| } | |||
| str += '; Domain=' + opt.domain; | |||
| } | |||
| if (opt.path) { | |||
| if (!fieldContentRegExp.test(opt.path)) { | |||
| throw new TypeError('option path is invalid'); | |||
| } | |||
| str += '; Path=' + opt.path; | |||
| } | |||
| if (opt.expires) { | |||
| if (typeof opt.expires.toUTCString !== 'function') { | |||
| throw new TypeError('option expires is invalid'); | |||
| } | |||
| str += '; Expires=' + opt.expires.toUTCString(); | |||
| } | |||
| if (opt.httpOnly) { | |||
| str += '; HttpOnly'; | |||
| } | |||
| if (opt.secure) { | |||
| str += '; Secure'; | |||
| } | |||
| if (opt.sameSite) { | |||
| var sameSite = typeof opt.sameSite === 'string' | |||
| ? opt.sameSite.toLowerCase() : opt.sameSite; | |||
| switch (sameSite) { | |||
| case true: | |||
| str += '; SameSite=Strict'; | |||
| break; | |||
| case 'lax': | |||
| str += '; SameSite=Lax'; | |||
| break; | |||
| case 'strict': | |||
| str += '; SameSite=Strict'; | |||
| break; | |||
| case 'none': | |||
| str += '; SameSite=None'; | |||
| break; | |||
| default: | |||
| throw new TypeError('option sameSite is invalid'); | |||
| } | |||
| } | |||
| return str; | |||
| } | |||
| /** | |||
| * Try decoding a string using a decoding function. | |||
| * | |||
| * @param {string} str | |||
| * @param {function} decode | |||
| * @private | |||
| */ | |||
| function tryDecode(str, decode) { | |||
| try { | |||
| return decode(str); | |||
| } catch (e) { | |||
| return str; | |||
| } | |||
| } | |||
| @@ -0,0 +1,105 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "cookie@0.4.0", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "cookie@0.4.0", | |||
| "_hasShrinkwrap": false, | |||
| "_id": "cookie@0.4.0", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/cookie", | |||
| "_nodeVersion": "8.16.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/cookie_0.4.0_1557977167056_0.23732140409492142" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "6.4.1", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "cookie", | |||
| "raw": "cookie@0.4.0", | |||
| "rawSpec": "0.4.0", | |||
| "scope": null, | |||
| "spec": "0.4.0", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", | |||
| "_shasum": "beb437e7022b3b6d49019d088665303ebe9c14ba", | |||
| "_shrinkwrap": null, | |||
| "_spec": "cookie@0.4.0", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "shtylman@gmail.com", | |||
| "name": "Roman Shtylman" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/jshttp/cookie/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "HTTP server cookie parsing and serialization", | |||
| "devDependencies": { | |||
| "beautify-benchmark": "0.2.4", | |||
| "benchmark": "2.1.4", | |||
| "eslint": "5.16.0", | |||
| "eslint-plugin-markdown": "1.0.0", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "6.1.4" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "fileCount": 5, | |||
| "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", | |||
| "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc3NhPCRA9TVsSAnZWagAADA4P/0Y8HkoR7zm45iuEtjAd\nEfcXA4oFAC9rTJtAWNcmDGwTW1HxfIX3M9ci8WSjlwbEqWsvE6XJYq4yjhZq\ncwj7IRftR1aGaGusZPrBQTXnwqMvRKTFG4ZMwH/IeeoEtmBq9hJJZX8yXjNL\nZbaAq84JTiGriMb9kjS+sizB6dHMUrCN4SDTP6EUEAVuF6lIVrikG3G6i7am\nqXeFIVXJQFn31/MRV/258l6eOefuPTlgWqpiBBLSScxSOSsyLhW2+FTpZ1Ga\n8wqAhQVf0JATKrElCH5x2u2slNxOI8FltAwxfMFHzN/5Q2XlOFznqFqoO1l6\nEYF0NgJQZXBQuKWIAVIyqwBZ5fQ9+lhjKtVqCGbcw9I2U+TRK0eHMNDgI+pR\nebdSwAhVWGTp0o2ahqhQBW/CB+tPgIjgy0lPRg5ioPs9noBb6AZZ5H9I0Ffm\niWO1FsneQYbFL+2IM/P3rIQefwFTParMXRuq70XxuVcU+cTXNi4X8lzH8KiJ\ncnq3Pit6czof7+OvNBWQAIq++d6z1tMq+ELOqp7L0QogZl7OGI/nFtZQrTbn\n2VtTg4su5j/zkE350pwTXirnRkS/9AiignuLco2H9PspMxEadPnmmakwErZJ\n+KXAFLAHZhgxfa7meSbFFoYDarbpuizUzDDULbUM0murTVR2dAYZUnCByEoi\nvmIe\r\n=Oa0u\r\n-----END PGP SIGNATURE-----\r\n", | |||
| "shasum": "beb437e7022b3b6d49019d088665303ebe9c14ba", | |||
| "tarball": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", | |||
| "unpackedSize": 17858 | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "gitHead": "aec1177c7da67e3b3273df96cf476824dbc9ae09", | |||
| "homepage": "https://github.com/jshttp/cookie#readme", | |||
| "keywords": [ | |||
| "cookie", | |||
| "cookies" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "cookie", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jshttp/cookie.git" | |||
| }, | |||
| "scripts": { | |||
| "bench": "node benchmark/index.js", | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --reporter spec --bail --check-leaks test/", | |||
| "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | |||
| "version": "node scripts/version-history.js && git add HISTORY.md" | |||
| }, | |||
| "version": "0.4.0" | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve | |||
| @@ -0,0 +1,11 @@ | |||
| { | |||
| "env": { | |||
| "browser": true, | |||
| "node": true | |||
| }, | |||
| "rules": { | |||
| "no-console": 0, | |||
| "no-empty": [1, { "allowEmptyCatch": true }] | |||
| }, | |||
| "extends": "eslint:recommended" | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| support | |||
| test | |||
| examples | |||
| example | |||
| *.sock | |||
| dist | |||
| yarn.lock | |||
| coverage | |||
| bower.json | |||
| @@ -0,0 +1,14 @@ | |||
| language: node_js | |||
| node_js: | |||
| - "6" | |||
| - "5" | |||
| - "4" | |||
| install: | |||
| - make node_modules | |||
| script: | |||
| - make lint | |||
| - make test | |||
| - make coveralls | |||
| @@ -0,0 +1,362 @@ | |||
| 2.6.9 / 2017-09-22 | |||
| ================== | |||
| * remove ReDoS regexp in %o formatter (#504) | |||
| 2.6.8 / 2017-05-18 | |||
| ================== | |||
| * Fix: Check for undefined on browser globals (#462, @marbemac) | |||
| 2.6.7 / 2017-05-16 | |||
| ================== | |||
| * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom) | |||
| * Fix: Inline extend function in node implementation (#452, @dougwilson) | |||
| * Docs: Fix typo (#455, @msasad) | |||
| 2.6.5 / 2017-04-27 | |||
| ================== | |||
| * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek) | |||
| * Misc: clean up browser reference checks (#447, @thebigredgeek) | |||
| * Misc: add npm-debug.log to .gitignore (@thebigredgeek) | |||
| 2.6.4 / 2017-04-20 | |||
| ================== | |||
| * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo) | |||
| * Chore: ignore bower.json in npm installations. (#437, @joaovieira) | |||
| * Misc: update "ms" to v0.7.3 (@tootallnate) | |||
| 2.6.3 / 2017-03-13 | |||
| ================== | |||
| * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts) | |||
| * Docs: Changelog fix (@thebigredgeek) | |||
| 2.6.2 / 2017-03-10 | |||
| ================== | |||
| * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin) | |||
| * Docs: Add backers and sponsors from Open Collective (#422, @piamancini) | |||
| * Docs: Add Slackin invite badge (@tootallnate) | |||
| 2.6.1 / 2017-02-10 | |||
| ================== | |||
| * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error | |||
| * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0) | |||
| * Fix: IE8 "Expected identifier" error (#414, @vgoma) | |||
| * Fix: Namespaces would not disable once enabled (#409, @musikov) | |||
| 2.6.0 / 2016-12-28 | |||
| ================== | |||
| * Fix: added better null pointer checks for browser useColors (@thebigredgeek) | |||
| * Improvement: removed explicit `window.debug` export (#404, @tootallnate) | |||
| * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate) | |||
| 2.5.2 / 2016-12-25 | |||
| ================== | |||
| * Fix: reference error on window within webworkers (#393, @KlausTrainer) | |||
| * Docs: fixed README typo (#391, @lurch) | |||
| * Docs: added notice about v3 api discussion (@thebigredgeek) | |||
| 2.5.1 / 2016-12-20 | |||
| ================== | |||
| * Fix: babel-core compatibility | |||
| 2.5.0 / 2016-12-20 | |||
| ================== | |||
| * Fix: wrong reference in bower file (@thebigredgeek) | |||
| * Fix: webworker compatibility (@thebigredgeek) | |||
| * Fix: output formatting issue (#388, @kribblo) | |||
| * Fix: babel-loader compatibility (#383, @escwald) | |||
| * Misc: removed built asset from repo and publications (@thebigredgeek) | |||
| * Misc: moved source files to /src (#378, @yamikuronue) | |||
| * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue) | |||
| * Test: coveralls integration (#378, @yamikuronue) | |||
| * Docs: simplified language in the opening paragraph (#373, @yamikuronue) | |||
| 2.4.5 / 2016-12-17 | |||
| ================== | |||
| * Fix: `navigator` undefined in Rhino (#376, @jochenberger) | |||
| * Fix: custom log function (#379, @hsiliev) | |||
| * Improvement: bit of cleanup + linting fixes (@thebigredgeek) | |||
| * Improvement: rm non-maintainted `dist/` dir (#375, @freewil) | |||
| * Docs: simplified language in the opening paragraph. (#373, @yamikuronue) | |||
| 2.4.4 / 2016-12-14 | |||
| ================== | |||
| * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts) | |||
| 2.4.3 / 2016-12-14 | |||
| ================== | |||
| * Fix: navigation.userAgent error for react native (#364, @escwald) | |||
| 2.4.2 / 2016-12-14 | |||
| ================== | |||
| * Fix: browser colors (#367, @tootallnate) | |||
| * Misc: travis ci integration (@thebigredgeek) | |||
| * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek) | |||
| 2.4.1 / 2016-12-13 | |||
| ================== | |||
| * Fix: typo that broke the package (#356) | |||
| 2.4.0 / 2016-12-13 | |||
| ================== | |||
| * Fix: bower.json references unbuilt src entry point (#342, @justmatt) | |||
| * Fix: revert "handle regex special characters" (@tootallnate) | |||
| * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate) | |||
| * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate) | |||
| * Improvement: allow colors in workers (#335, @botverse) | |||
| * Improvement: use same color for same namespace. (#338, @lchenay) | |||
| 2.3.3 / 2016-11-09 | |||
| ================== | |||
| * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne) | |||
| * Fix: Returning `localStorage` saved values (#331, Levi Thomason) | |||
| * Improvement: Don't create an empty object when no `process` (Nathan Rajlich) | |||
| 2.3.2 / 2016-11-09 | |||
| ================== | |||
| * Fix: be super-safe in index.js as well (@TooTallNate) | |||
| * Fix: should check whether process exists (Tom Newby) | |||
| 2.3.1 / 2016-11-09 | |||
| ================== | |||
| * Fix: Added electron compatibility (#324, @paulcbetts) | |||
| * Improvement: Added performance optimizations (@tootallnate) | |||
| * Readme: Corrected PowerShell environment variable example (#252, @gimre) | |||
| * Misc: Removed yarn lock file from source control (#321, @fengmk2) | |||
| 2.3.0 / 2016-11-07 | |||
| ================== | |||
| * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic) | |||
| * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos) | |||
| * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15) | |||
| * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran) | |||
| * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom) | |||
| * Package: Update "ms" to 0.7.2 (#315, @DevSide) | |||
| * Package: removed superfluous version property from bower.json (#207 @kkirsche) | |||
| * Readme: fix USE_COLORS to DEBUG_COLORS | |||
| * Readme: Doc fixes for format string sugar (#269, @mlucool) | |||
| * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0) | |||
| * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable) | |||
| * Readme: better docs for browser support (#224, @matthewmueller) | |||
| * Tooling: Added yarn integration for development (#317, @thebigredgeek) | |||
| * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek) | |||
| * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman) | |||
| * Misc: Updated contributors (@thebigredgeek) | |||
| 2.2.0 / 2015-05-09 | |||
| ================== | |||
| * package: update "ms" to v0.7.1 (#202, @dougwilson) | |||
| * README: add logging to file example (#193, @DanielOchoa) | |||
| * README: fixed a typo (#191, @amir-s) | |||
| * browser: expose `storage` (#190, @stephenmathieson) | |||
| * Makefile: add a `distclean` target (#189, @stephenmathieson) | |||
| 2.1.3 / 2015-03-13 | |||
| ================== | |||
| * Updated stdout/stderr example (#186) | |||
| * Updated example/stdout.js to match debug current behaviour | |||
| * Renamed example/stderr.js to stdout.js | |||
| * Update Readme.md (#184) | |||
| * replace high intensity foreground color for bold (#182, #183) | |||
| 2.1.2 / 2015-03-01 | |||
| ================== | |||
| * dist: recompile | |||
| * update "ms" to v0.7.0 | |||
| * package: update "browserify" to v9.0.3 | |||
| * component: fix "ms.js" repo location | |||
| * changed bower package name | |||
| * updated documentation about using debug in a browser | |||
| * fix: security error on safari (#167, #168, @yields) | |||
| 2.1.1 / 2014-12-29 | |||
| ================== | |||
| * browser: use `typeof` to check for `console` existence | |||
| * browser: check for `console.log` truthiness (fix IE 8/9) | |||
| * browser: add support for Chrome apps | |||
| * Readme: added Windows usage remarks | |||
| * Add `bower.json` to properly support bower install | |||
| 2.1.0 / 2014-10-15 | |||
| ================== | |||
| * node: implement `DEBUG_FD` env variable support | |||
| * package: update "browserify" to v6.1.0 | |||
| * package: add "license" field to package.json (#135, @panuhorsmalahti) | |||
| 2.0.0 / 2014-09-01 | |||
| ================== | |||
| * package: update "browserify" to v5.11.0 | |||
| * node: use stderr rather than stdout for logging (#29, @stephenmathieson) | |||
| 1.0.4 / 2014-07-15 | |||
| ================== | |||
| * dist: recompile | |||
| * example: remove `console.info()` log usage | |||
| * example: add "Content-Type" UTF-8 header to browser example | |||
| * browser: place %c marker after the space character | |||
| * browser: reset the "content" color via `color: inherit` | |||
| * browser: add colors support for Firefox >= v31 | |||
| * debug: prefer an instance `log()` function over the global one (#119) | |||
| * Readme: update documentation about styled console logs for FF v31 (#116, @wryk) | |||
| 1.0.3 / 2014-07-09 | |||
| ================== | |||
| * Add support for multiple wildcards in namespaces (#122, @seegno) | |||
| * browser: fix lint | |||
| 1.0.2 / 2014-06-10 | |||
| ================== | |||
| * browser: update color palette (#113, @gscottolson) | |||
| * common: make console logging function configurable (#108, @timoxley) | |||
| * node: fix %o colors on old node <= 0.8.x | |||
| * Makefile: find node path using shell/which (#109, @timoxley) | |||
| 1.0.1 / 2014-06-06 | |||
| ================== | |||
| * browser: use `removeItem()` to clear localStorage | |||
| * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777) | |||
| * package: add "contributors" section | |||
| * node: fix comment typo | |||
| * README: list authors | |||
| 1.0.0 / 2014-06-04 | |||
| ================== | |||
| * make ms diff be global, not be scope | |||
| * debug: ignore empty strings in enable() | |||
| * node: make DEBUG_COLORS able to disable coloring | |||
| * *: export the `colors` array | |||
| * npmignore: don't publish the `dist` dir | |||
| * Makefile: refactor to use browserify | |||
| * package: add "browserify" as a dev dependency | |||
| * Readme: add Web Inspector Colors section | |||
| * node: reset terminal color for the debug content | |||
| * node: map "%o" to `util.inspect()` | |||
| * browser: map "%j" to `JSON.stringify()` | |||
| * debug: add custom "formatters" | |||
| * debug: use "ms" module for humanizing the diff | |||
| * Readme: add "bash" syntax highlighting | |||
| * browser: add Firebug color support | |||
| * browser: add colors for WebKit browsers | |||
| * node: apply log to `console` | |||
| * rewrite: abstract common logic for Node & browsers | |||
| * add .jshintrc file | |||
| 0.8.1 / 2014-04-14 | |||
| ================== | |||
| * package: re-add the "component" section | |||
| 0.8.0 / 2014-03-30 | |||
| ================== | |||
| * add `enable()` method for nodejs. Closes #27 | |||
| * change from stderr to stdout | |||
| * remove unnecessary index.js file | |||
| 0.7.4 / 2013-11-13 | |||
| ================== | |||
| * remove "browserify" key from package.json (fixes something in browserify) | |||
| 0.7.3 / 2013-10-30 | |||
| ================== | |||
| * fix: catch localStorage security error when cookies are blocked (Chrome) | |||
| * add debug(err) support. Closes #46 | |||
| * add .browser prop to package.json. Closes #42 | |||
| 0.7.2 / 2013-02-06 | |||
| ================== | |||
| * fix package.json | |||
| * fix: Mobile Safari (private mode) is broken with debug | |||
| * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript | |||
| 0.7.1 / 2013-02-05 | |||
| ================== | |||
| * add repository URL to package.json | |||
| * add DEBUG_COLORED to force colored output | |||
| * add browserify support | |||
| * fix component. Closes #24 | |||
| 0.7.0 / 2012-05-04 | |||
| ================== | |||
| * Added .component to package.json | |||
| * Added debug.component.js build | |||
| 0.6.0 / 2012-03-16 | |||
| ================== | |||
| * Added support for "-" prefix in DEBUG [Vinay Pulim] | |||
| * Added `.enabled` flag to the node version [TooTallNate] | |||
| 0.5.0 / 2012-02-02 | |||
| ================== | |||
| * Added: humanize diffs. Closes #8 | |||
| * Added `debug.disable()` to the CS variant | |||
| * Removed padding. Closes #10 | |||
| * Fixed: persist client-side variant again. Closes #9 | |||
| 0.4.0 / 2012-02-01 | |||
| ================== | |||
| * Added browser variant support for older browsers [TooTallNate] | |||
| * Added `debug.enable('project:*')` to browser variant [TooTallNate] | |||
| * Added padding to diff (moved it to the right) | |||
| 0.3.0 / 2012-01-26 | |||
| ================== | |||
| * Added millisecond diff when isatty, otherwise UTC string | |||
| 0.2.0 / 2012-01-22 | |||
| ================== | |||
| * Added wildcard support | |||
| 0.1.0 / 2011-12-02 | |||
| ================== | |||
| * Added: remove colors unless stderr isatty [TooTallNate] | |||
| 0.0.1 / 2010-01-03 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,19 @@ | |||
| (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. | |||
| @@ -0,0 +1,50 @@ | |||
| # get Makefile directory name: http://stackoverflow.com/a/5982798/376773 | |||
| THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) | |||
| THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) | |||
| # BIN directory | |||
| BIN := $(THIS_DIR)/node_modules/.bin | |||
| # Path | |||
| PATH := node_modules/.bin:$(PATH) | |||
| SHELL := /bin/bash | |||
| # applications | |||
| NODE ?= $(shell which node) | |||
| YARN ?= $(shell which yarn) | |||
| PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm)) | |||
| BROWSERIFY ?= $(NODE) $(BIN)/browserify | |||
| .FORCE: | |||
| install: node_modules | |||
| node_modules: package.json | |||
| @NODE_ENV= $(PKG) install | |||
| @touch node_modules | |||
| lint: .FORCE | |||
| eslint browser.js debug.js index.js node.js | |||
| test-node: .FORCE | |||
| istanbul cover node_modules/mocha/bin/_mocha -- test/**.js | |||
| test-browser: .FORCE | |||
| mkdir -p dist | |||
| @$(BROWSERIFY) \ | |||
| --standalone debug \ | |||
| . > dist/debug.js | |||
| karma start --single-run | |||
| rimraf dist | |||
| test: .FORCE | |||
| concurrently \ | |||
| "make test-node" \ | |||
| "make test-browser" | |||
| coveralls: | |||
| cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js | |||
| .PHONY: all install clean distclean | |||
| @@ -0,0 +1,312 @@ | |||
| # debug | |||
| [](https://travis-ci.org/visionmedia/debug) [](https://coveralls.io/github/visionmedia/debug?branch=master) [](https://visionmedia-community-slackin.now.sh/) [](#backers) | |||
| [](#sponsors) | |||
| A tiny node.js debugging utility modelled after node core's debugging technique. | |||
| **Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)** | |||
| ## Installation | |||
| ```bash | |||
| $ npm install debug | |||
| ``` | |||
| ## Usage | |||
| `debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. | |||
| Example _app.js_: | |||
| ```js | |||
| var debug = require('debug')('http') | |||
| , http = require('http') | |||
| , name = 'My App'; | |||
| // fake app | |||
| debug('booting %s', name); | |||
| http.createServer(function(req, res){ | |||
| debug(req.method + ' ' + req.url); | |||
| res.end('hello\n'); | |||
| }).listen(3000, function(){ | |||
| debug('listening'); | |||
| }); | |||
| // fake worker of some kind | |||
| require('./worker'); | |||
| ``` | |||
| Example _worker.js_: | |||
| ```js | |||
| var debug = require('debug')('worker'); | |||
| setInterval(function(){ | |||
| debug('doing some work'); | |||
| }, 1000); | |||
| ``` | |||
| The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples: | |||
|  | |||
|  | |||
| #### Windows note | |||
| On Windows the environment variable is set using the `set` command. | |||
| ```cmd | |||
| set DEBUG=*,-not_this | |||
| ``` | |||
| Note that PowerShell uses different syntax to set environment variables. | |||
| ```cmd | |||
| $env:DEBUG = "*,-not_this" | |||
| ``` | |||
| Then, run the program to be debugged as usual. | |||
| ## Millisecond diff | |||
| When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. | |||
|  | |||
| When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below: | |||
|  | |||
| ## Conventions | |||
| If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". | |||
| ## Wildcards | |||
| The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. | |||
| You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:". | |||
| ## Environment Variables | |||
| When running through Node.js, you can set a few environment variables that will | |||
| change the behavior of the debug logging: | |||
| | Name | Purpose | | |||
| |-----------|-------------------------------------------------| | |||
| | `DEBUG` | Enables/disables specific debugging namespaces. | | |||
| | `DEBUG_COLORS`| Whether or not to use colors in the debug output. | | |||
| | `DEBUG_DEPTH` | Object inspection depth. | | |||
| | `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | | |||
| __Note:__ The environment variables beginning with `DEBUG_` end up being | |||
| converted into an Options object that gets used with `%o`/`%O` formatters. | |||
| See the Node.js documentation for | |||
| [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) | |||
| for the complete list. | |||
| ## Formatters | |||
| Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters: | |||
| | Formatter | Representation | | |||
| |-----------|----------------| | |||
| | `%O` | Pretty-print an Object on multiple lines. | | |||
| | `%o` | Pretty-print an Object all on a single line. | | |||
| | `%s` | String. | | |||
| | `%d` | Number (both integer and float). | | |||
| | `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | | |||
| | `%%` | Single percent sign ('%'). This does not consume an argument. | | |||
| ### Custom formatters | |||
| You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like: | |||
| ```js | |||
| const createDebug = require('debug') | |||
| createDebug.formatters.h = (v) => { | |||
| return v.toString('hex') | |||
| } | |||
| // …elsewhere | |||
| const debug = createDebug('foo') | |||
| debug('this is hex: %h', new Buffer('hello world')) | |||
| // foo this is hex: 68656c6c6f20776f726c6421 +0ms | |||
| ``` | |||
| ## Browser support | |||
| You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), | |||
| or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), | |||
| if you don't want to build it yourself. | |||
| Debug's enable state is currently persisted by `localStorage`. | |||
| Consider the situation shown below where you have `worker:a` and `worker:b`, | |||
| and wish to debug both. You can enable this using `localStorage.debug`: | |||
| ```js | |||
| localStorage.debug = 'worker:*' | |||
| ``` | |||
| And then refresh the page. | |||
| ```js | |||
| a = debug('worker:a'); | |||
| b = debug('worker:b'); | |||
| setInterval(function(){ | |||
| a('doing some work'); | |||
| }, 1000); | |||
| setInterval(function(){ | |||
| b('doing some work'); | |||
| }, 1200); | |||
| ``` | |||
| #### Web Inspector Colors | |||
| Colors are also enabled on "Web Inspectors" that understand the `%c` formatting | |||
| option. These are WebKit web inspectors, Firefox ([since version | |||
| 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) | |||
| and the Firebug plugin for Firefox (any version). | |||
| Colored output looks something like: | |||
|  | |||
| ## Output streams | |||
| By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: | |||
| Example _stdout.js_: | |||
| ```js | |||
| var debug = require('debug'); | |||
| var error = debug('app:error'); | |||
| // by default stderr is used | |||
| error('goes to stderr!'); | |||
| var log = debug('app:log'); | |||
| // set this namespace to log via console.log | |||
| log.log = console.log.bind(console); // don't forget to bind to console! | |||
| log('goes to stdout'); | |||
| error('still goes to stderr!'); | |||
| // set all output to go via console.info | |||
| // overrides all per-namespace log settings | |||
| debug.log = console.info.bind(console); | |||
| error('now goes to stdout via console.info'); | |||
| log('still goes to stdout, but via console.info now'); | |||
| ``` | |||
| ## Authors | |||
| - TJ Holowaychuk | |||
| - Nathan Rajlich | |||
| - Andrew Rhyne | |||
| ## Backers | |||
| Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] | |||
| <a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a> | |||
| ## Sponsors | |||
| Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] | |||
| <a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a> | |||
| <a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a> | |||
| ## License | |||
| (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. | |||
| @@ -0,0 +1,19 @@ | |||
| { | |||
| "name": "debug", | |||
| "repo": "visionmedia/debug", | |||
| "description": "small debugging utility", | |||
| "version": "2.6.9", | |||
| "keywords": [ | |||
| "debug", | |||
| "log", | |||
| "debugger" | |||
| ], | |||
| "main": "src/browser.js", | |||
| "scripts": [ | |||
| "src/browser.js", | |||
| "src/debug.js" | |||
| ], | |||
| "dependencies": { | |||
| "rauchg/ms.js": "0.7.1" | |||
| } | |||
| } | |||
| @@ -0,0 +1,70 @@ | |||
| // Karma configuration | |||
| // Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC) | |||
| module.exports = function(config) { | |||
| config.set({ | |||
| // base path that will be used to resolve all patterns (eg. files, exclude) | |||
| basePath: '', | |||
| // frameworks to use | |||
| // available frameworks: https://npmjs.org/browse/keyword/karma-adapter | |||
| frameworks: ['mocha', 'chai', 'sinon'], | |||
| // list of files / patterns to load in the browser | |||
| files: [ | |||
| 'dist/debug.js', | |||
| 'test/*spec.js' | |||
| ], | |||
| // list of files to exclude | |||
| exclude: [ | |||
| 'src/node.js' | |||
| ], | |||
| // preprocess matching files before serving them to the browser | |||
| // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor | |||
| preprocessors: { | |||
| }, | |||
| // test results reporter to use | |||
| // possible values: 'dots', 'progress' | |||
| // available reporters: https://npmjs.org/browse/keyword/karma-reporter | |||
| reporters: ['progress'], | |||
| // web server port | |||
| port: 9876, | |||
| // enable / disable colors in the output (reporters and logs) | |||
| colors: true, | |||
| // level of logging | |||
| // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG | |||
| logLevel: config.LOG_INFO, | |||
| // enable / disable watching file and executing tests whenever any file changes | |||
| autoWatch: true, | |||
| // start these browsers | |||
| // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher | |||
| browsers: ['PhantomJS'], | |||
| // Continuous Integration mode | |||
| // if true, Karma captures browsers, runs the tests and exits | |||
| singleRun: false, | |||
| // Concurrency level | |||
| // how many browser should be started simultaneous | |||
| concurrency: Infinity | |||
| }) | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| module.exports = require('./src/node'); | |||
| @@ -0,0 +1,131 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "debug@2.6.9", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "debug@2.6.9", | |||
| "_id": "debug@2.6.9", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/debug", | |||
| "_nodeVersion": "8.4.0", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "nathan@tootallnate.net", | |||
| "name": "tootallnate" | |||
| }, | |||
| "_npmVersion": "5.3.0", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "debug", | |||
| "raw": "debug@2.6.9", | |||
| "rawSpec": "2.6.9", | |||
| "scope": null, | |||
| "spec": "2.6.9", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/body-parser", | |||
| "/express", | |||
| "/finalhandler", | |||
| "/send" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | |||
| "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f", | |||
| "_shrinkwrap": null, | |||
| "_spec": "debug@2.6.9", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "tj@vision-media.ca", | |||
| "name": "TJ Holowaychuk" | |||
| }, | |||
| "browser": "./src/browser.js", | |||
| "bugs": { | |||
| "url": "https://github.com/visionmedia/debug/issues" | |||
| }, | |||
| "component": { | |||
| "scripts": { | |||
| "debug/debug.js": "debug.js", | |||
| "debug/index.js": "browser.js" | |||
| } | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Nathan Rajlich", | |||
| "email": "nathan@tootallnate.net", | |||
| "url": "http://n8.io" | |||
| }, | |||
| { | |||
| "name": "Andrew Rhyne", | |||
| "email": "rhyneandrew@gmail.com" | |||
| } | |||
| ], | |||
| "dependencies": { | |||
| "ms": "2.0.0" | |||
| }, | |||
| "description": "small debugging utility", | |||
| "devDependencies": { | |||
| "browserify": "9.0.3", | |||
| "chai": "^3.5.0", | |||
| "concurrently": "^3.1.0", | |||
| "coveralls": "^2.11.15", | |||
| "eslint": "^3.12.1", | |||
| "istanbul": "^0.4.5", | |||
| "karma": "^1.3.0", | |||
| "karma-chai": "^0.1.0", | |||
| "karma-mocha": "^1.3.0", | |||
| "karma-phantomjs-launcher": "^1.0.2", | |||
| "karma-sinon": "^1.0.5", | |||
| "mocha": "^3.2.0", | |||
| "mocha-lcov-reporter": "^1.2.0", | |||
| "rimraf": "^2.5.4", | |||
| "sinon": "^1.17.6", | |||
| "sinon-chai": "^2.8.0" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | |||
| "shasum": "5d128515df134ff327e90a4c93f4e077a536341f", | |||
| "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" | |||
| }, | |||
| "gitHead": "13abeae468fea297d0dccc50bc55590809241083", | |||
| "homepage": "https://github.com/visionmedia/debug#readme", | |||
| "keywords": [ | |||
| "debug", | |||
| "debugger", | |||
| "log" | |||
| ], | |||
| "license": "MIT", | |||
| "main": "./src/index.js", | |||
| "maintainers": [ | |||
| { | |||
| "name": "thebigredgeek", | |||
| "email": "rhyneandrew@gmail.com" | |||
| }, | |||
| { | |||
| "name": "kolban", | |||
| "email": "kolban1@kolban.com" | |||
| }, | |||
| { | |||
| "name": "tootallnate", | |||
| "email": "nathan@tootallnate.net" | |||
| }, | |||
| { | |||
| "name": "tjholowaychuk", | |||
| "email": "tj@vision-media.ca" | |||
| } | |||
| ], | |||
| "name": "debug", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git://github.com/visionmedia/debug.git" | |||
| }, | |||
| "version": "2.6.9" | |||
| } | |||
| @@ -0,0 +1,185 @@ | |||
| /** | |||
| * This is the web browser implementation of `debug()`. | |||
| * | |||
| * Expose `debug()` as the module. | |||
| */ | |||
| exports = module.exports = require('./debug'); | |||
| exports.log = log; | |||
| exports.formatArgs = formatArgs; | |||
| exports.save = save; | |||
| exports.load = load; | |||
| exports.useColors = useColors; | |||
| exports.storage = 'undefined' != typeof chrome | |||
| && 'undefined' != typeof chrome.storage | |||
| ? chrome.storage.local | |||
| : localstorage(); | |||
| /** | |||
| * Colors. | |||
| */ | |||
| exports.colors = [ | |||
| 'lightseagreen', | |||
| 'forestgreen', | |||
| 'goldenrod', | |||
| 'dodgerblue', | |||
| 'darkorchid', | |||
| 'crimson' | |||
| ]; | |||
| /** | |||
| * Currently only WebKit-based Web Inspectors, Firefox >= v31, | |||
| * and the Firebug extension (any Firefox version) are known | |||
| * to support "%c" CSS customizations. | |||
| * | |||
| * TODO: add a `localStorage` variable to explicitly enable/disable colors | |||
| */ | |||
| function useColors() { | |||
| // NB: In an Electron preload script, document will be defined but not fully | |||
| // initialized. Since we know we're in Chrome, we'll just detect this case | |||
| // explicitly | |||
| if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') { | |||
| return true; | |||
| } | |||
| // is webkit? http://stackoverflow.com/a/16459606/376773 | |||
| // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 | |||
| return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || | |||
| // is firebug? http://stackoverflow.com/a/398120/376773 | |||
| (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || | |||
| // is firefox >= v31? | |||
| // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages | |||
| (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || | |||
| // double check webkit in userAgent just in case we are in a worker | |||
| (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); | |||
| } | |||
| /** | |||
| * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. | |||
| */ | |||
| exports.formatters.j = function(v) { | |||
| try { | |||
| return JSON.stringify(v); | |||
| } catch (err) { | |||
| return '[UnexpectedJSONParseError]: ' + err.message; | |||
| } | |||
| }; | |||
| /** | |||
| * Colorize log arguments if enabled. | |||
| * | |||
| * @api public | |||
| */ | |||
| function formatArgs(args) { | |||
| var useColors = this.useColors; | |||
| args[0] = (useColors ? '%c' : '') | |||
| + this.namespace | |||
| + (useColors ? ' %c' : ' ') | |||
| + args[0] | |||
| + (useColors ? '%c ' : ' ') | |||
| + '+' + exports.humanize(this.diff); | |||
| if (!useColors) return; | |||
| var c = 'color: ' + this.color; | |||
| args.splice(1, 0, c, 'color: inherit') | |||
| // the final "%c" is somewhat tricky, because there could be other | |||
| // arguments passed either before or after the %c, so we need to | |||
| // figure out the correct index to insert the CSS into | |||
| var index = 0; | |||
| var lastC = 0; | |||
| args[0].replace(/%[a-zA-Z%]/g, function(match) { | |||
| if ('%%' === match) return; | |||
| index++; | |||
| if ('%c' === match) { | |||
| // we only are interested in the *last* %c | |||
| // (the user may have provided their own) | |||
| lastC = index; | |||
| } | |||
| }); | |||
| args.splice(lastC, 0, c); | |||
| } | |||
| /** | |||
| * Invokes `console.log()` when available. | |||
| * No-op when `console.log` is not a "function". | |||
| * | |||
| * @api public | |||
| */ | |||
| function log() { | |||
| // this hackery is required for IE8/9, where | |||
| // the `console.log` function doesn't have 'apply' | |||
| return 'object' === typeof console | |||
| && console.log | |||
| && Function.prototype.apply.call(console.log, console, arguments); | |||
| } | |||
| /** | |||
| * Save `namespaces`. | |||
| * | |||
| * @param {String} namespaces | |||
| * @api private | |||
| */ | |||
| function save(namespaces) { | |||
| try { | |||
| if (null == namespaces) { | |||
| exports.storage.removeItem('debug'); | |||
| } else { | |||
| exports.storage.debug = namespaces; | |||
| } | |||
| } catch(e) {} | |||
| } | |||
| /** | |||
| * Load `namespaces`. | |||
| * | |||
| * @return {String} returns the previously persisted debug modes | |||
| * @api private | |||
| */ | |||
| function load() { | |||
| var r; | |||
| try { | |||
| r = exports.storage.debug; | |||
| } catch(e) {} | |||
| // If debug isn't set in LS, and we're in Electron, try to load $DEBUG | |||
| if (!r && typeof process !== 'undefined' && 'env' in process) { | |||
| r = process.env.DEBUG; | |||
| } | |||
| return r; | |||
| } | |||
| /** | |||
| * Enable namespaces listed in `localStorage.debug` initially. | |||
| */ | |||
| exports.enable(load()); | |||
| /** | |||
| * Localstorage attempts to return the localstorage. | |||
| * | |||
| * This is necessary because safari throws | |||
| * when a user disables cookies/localstorage | |||
| * and you attempt to access it. | |||
| * | |||
| * @return {LocalStorage} | |||
| * @api private | |||
| */ | |||
| function localstorage() { | |||
| try { | |||
| return window.localStorage; | |||
| } catch (e) {} | |||
| } | |||
| @@ -0,0 +1,202 @@ | |||
| /** | |||
| * This is the common logic for both the Node.js and web browser | |||
| * implementations of `debug()`. | |||
| * | |||
| * Expose `debug()` as the module. | |||
| */ | |||
| exports = module.exports = createDebug.debug = createDebug['default'] = createDebug; | |||
| exports.coerce = coerce; | |||
| exports.disable = disable; | |||
| exports.enable = enable; | |||
| exports.enabled = enabled; | |||
| exports.humanize = require('ms'); | |||
| /** | |||
| * The currently active debug mode names, and names to skip. | |||
| */ | |||
| exports.names = []; | |||
| exports.skips = []; | |||
| /** | |||
| * Map of special "%n" handling functions, for the debug "format" argument. | |||
| * | |||
| * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". | |||
| */ | |||
| exports.formatters = {}; | |||
| /** | |||
| * Previous log timestamp. | |||
| */ | |||
| var prevTime; | |||
| /** | |||
| * Select a color. | |||
| * @param {String} namespace | |||
| * @return {Number} | |||
| * @api private | |||
| */ | |||
| function selectColor(namespace) { | |||
| var hash = 0, i; | |||
| for (i in namespace) { | |||
| hash = ((hash << 5) - hash) + namespace.charCodeAt(i); | |||
| hash |= 0; // Convert to 32bit integer | |||
| } | |||
| return exports.colors[Math.abs(hash) % exports.colors.length]; | |||
| } | |||
| /** | |||
| * Create a debugger with the given `namespace`. | |||
| * | |||
| * @param {String} namespace | |||
| * @return {Function} | |||
| * @api public | |||
| */ | |||
| function createDebug(namespace) { | |||
| function debug() { | |||
| // disabled? | |||
| if (!debug.enabled) return; | |||
| var self = debug; | |||
| // set `diff` timestamp | |||
| var curr = +new Date(); | |||
| var ms = curr - (prevTime || curr); | |||
| self.diff = ms; | |||
| self.prev = prevTime; | |||
| self.curr = curr; | |||
| prevTime = curr; | |||
| // turn the `arguments` into a proper Array | |||
| var args = new Array(arguments.length); | |||
| for (var i = 0; i < args.length; i++) { | |||
| args[i] = arguments[i]; | |||
| } | |||
| args[0] = exports.coerce(args[0]); | |||
| if ('string' !== typeof args[0]) { | |||
| // anything else let's inspect with %O | |||
| args.unshift('%O'); | |||
| } | |||
| // apply any `formatters` transformations | |||
| var index = 0; | |||
| args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) { | |||
| // if we encounter an escaped % then don't increase the array index | |||
| if (match === '%%') return match; | |||
| index++; | |||
| var formatter = exports.formatters[format]; | |||
| if ('function' === typeof formatter) { | |||
| var val = args[index]; | |||
| match = formatter.call(self, val); | |||
| // now we need to remove `args[index]` since it's inlined in the `format` | |||
| args.splice(index, 1); | |||
| index--; | |||
| } | |||
| return match; | |||
| }); | |||
| // apply env-specific formatting (colors, etc.) | |||
| exports.formatArgs.call(self, args); | |||
| var logFn = debug.log || exports.log || console.log.bind(console); | |||
| logFn.apply(self, args); | |||
| } | |||
| debug.namespace = namespace; | |||
| debug.enabled = exports.enabled(namespace); | |||
| debug.useColors = exports.useColors(); | |||
| debug.color = selectColor(namespace); | |||
| // env-specific initialization logic for debug instances | |||
| if ('function' === typeof exports.init) { | |||
| exports.init(debug); | |||
| } | |||
| return debug; | |||
| } | |||
| /** | |||
| * Enables a debug mode by namespaces. This can include modes | |||
| * separated by a colon and wildcards. | |||
| * | |||
| * @param {String} namespaces | |||
| * @api public | |||
| */ | |||
| function enable(namespaces) { | |||
| exports.save(namespaces); | |||
| exports.names = []; | |||
| exports.skips = []; | |||
| var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); | |||
| var len = split.length; | |||
| for (var i = 0; i < len; i++) { | |||
| if (!split[i]) continue; // ignore empty strings | |||
| namespaces = split[i].replace(/\*/g, '.*?'); | |||
| if (namespaces[0] === '-') { | |||
| exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); | |||
| } else { | |||
| exports.names.push(new RegExp('^' + namespaces + '$')); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Disable debug output. | |||
| * | |||
| * @api public | |||
| */ | |||
| function disable() { | |||
| exports.enable(''); | |||
| } | |||
| /** | |||
| * Returns true if the given mode name is enabled, false otherwise. | |||
| * | |||
| * @param {String} name | |||
| * @return {Boolean} | |||
| * @api public | |||
| */ | |||
| function enabled(name) { | |||
| var i, len; | |||
| for (i = 0, len = exports.skips.length; i < len; i++) { | |||
| if (exports.skips[i].test(name)) { | |||
| return false; | |||
| } | |||
| } | |||
| for (i = 0, len = exports.names.length; i < len; i++) { | |||
| if (exports.names[i].test(name)) { | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * Coerce `val`. | |||
| * | |||
| * @param {Mixed} val | |||
| * @return {Mixed} | |||
| * @api private | |||
| */ | |||
| function coerce(val) { | |||
| if (val instanceof Error) return val.stack || val.message; | |||
| return val; | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| /** | |||
| * Detect Electron renderer process, which is node, but we should | |||
| * treat as a browser. | |||
| */ | |||
| if (typeof process !== 'undefined' && process.type === 'renderer') { | |||
| module.exports = require('./browser.js'); | |||
| } else { | |||
| module.exports = require('./node.js'); | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| module.exports = inspectorLog; | |||
| // black hole | |||
| const nullStream = new (require('stream').Writable)(); | |||
| nullStream._write = () => {}; | |||
| /** | |||
| * Outputs a `console.log()` to the Node.js Inspector console *only*. | |||
| */ | |||
| function inspectorLog() { | |||
| const stdout = console._stdout; | |||
| console._stdout = nullStream; | |||
| console.log.apply(console, arguments); | |||
| console._stdout = stdout; | |||
| } | |||
| @@ -0,0 +1,248 @@ | |||
| /** | |||
| * Module dependencies. | |||
| */ | |||
| var tty = require('tty'); | |||
| var util = require('util'); | |||
| /** | |||
| * This is the Node.js implementation of `debug()`. | |||
| * | |||
| * Expose `debug()` as the module. | |||
| */ | |||
| exports = module.exports = require('./debug'); | |||
| exports.init = init; | |||
| exports.log = log; | |||
| exports.formatArgs = formatArgs; | |||
| exports.save = save; | |||
| exports.load = load; | |||
| exports.useColors = useColors; | |||
| /** | |||
| * Colors. | |||
| */ | |||
| exports.colors = [6, 2, 3, 4, 5, 1]; | |||
| /** | |||
| * Build up the default `inspectOpts` object from the environment variables. | |||
| * | |||
| * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js | |||
| */ | |||
| exports.inspectOpts = Object.keys(process.env).filter(function (key) { | |||
| return /^debug_/i.test(key); | |||
| }).reduce(function (obj, key) { | |||
| // camel-case | |||
| var prop = key | |||
| .substring(6) | |||
| .toLowerCase() | |||
| .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() }); | |||
| // coerce string value into JS value | |||
| var val = process.env[key]; | |||
| if (/^(yes|on|true|enabled)$/i.test(val)) val = true; | |||
| else if (/^(no|off|false|disabled)$/i.test(val)) val = false; | |||
| else if (val === 'null') val = null; | |||
| else val = Number(val); | |||
| obj[prop] = val; | |||
| return obj; | |||
| }, {}); | |||
| /** | |||
| * The file descriptor to write the `debug()` calls to. | |||
| * Set the `DEBUG_FD` env variable to override with another value. i.e.: | |||
| * | |||
| * $ DEBUG_FD=3 node script.js 3>debug.log | |||
| */ | |||
| var fd = parseInt(process.env.DEBUG_FD, 10) || 2; | |||
| if (1 !== fd && 2 !== fd) { | |||
| util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')() | |||
| } | |||
| var stream = 1 === fd ? process.stdout : | |||
| 2 === fd ? process.stderr : | |||
| createWritableStdioStream(fd); | |||
| /** | |||
| * Is stdout a TTY? Colored output is enabled when `true`. | |||
| */ | |||
| function useColors() { | |||
| return 'colors' in exports.inspectOpts | |||
| ? Boolean(exports.inspectOpts.colors) | |||
| : tty.isatty(fd); | |||
| } | |||
| /** | |||
| * Map %o to `util.inspect()`, all on a single line. | |||
| */ | |||
| exports.formatters.o = function(v) { | |||
| this.inspectOpts.colors = this.useColors; | |||
| return util.inspect(v, this.inspectOpts) | |||
| .split('\n').map(function(str) { | |||
| return str.trim() | |||
| }).join(' '); | |||
| }; | |||
| /** | |||
| * Map %o to `util.inspect()`, allowing multiple lines if needed. | |||
| */ | |||
| exports.formatters.O = function(v) { | |||
| this.inspectOpts.colors = this.useColors; | |||
| return util.inspect(v, this.inspectOpts); | |||
| }; | |||
| /** | |||
| * Adds ANSI color escape codes if enabled. | |||
| * | |||
| * @api public | |||
| */ | |||
| function formatArgs(args) { | |||
| var name = this.namespace; | |||
| var useColors = this.useColors; | |||
| if (useColors) { | |||
| var c = this.color; | |||
| var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m'; | |||
| args[0] = prefix + args[0].split('\n').join('\n' + prefix); | |||
| args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m'); | |||
| } else { | |||
| args[0] = new Date().toUTCString() | |||
| + ' ' + name + ' ' + args[0]; | |||
| } | |||
| } | |||
| /** | |||
| * Invokes `util.format()` with the specified arguments and writes to `stream`. | |||
| */ | |||
| function log() { | |||
| return stream.write(util.format.apply(util, arguments) + '\n'); | |||
| } | |||
| /** | |||
| * Save `namespaces`. | |||
| * | |||
| * @param {String} namespaces | |||
| * @api private | |||
| */ | |||
| function save(namespaces) { | |||
| if (null == namespaces) { | |||
| // If you set a process.env field to null or undefined, it gets cast to the | |||
| // string 'null' or 'undefined'. Just delete instead. | |||
| delete process.env.DEBUG; | |||
| } else { | |||
| process.env.DEBUG = namespaces; | |||
| } | |||
| } | |||
| /** | |||
| * Load `namespaces`. | |||
| * | |||
| * @return {String} returns the previously persisted debug modes | |||
| * @api private | |||
| */ | |||
| function load() { | |||
| return process.env.DEBUG; | |||
| } | |||
| /** | |||
| * Copied from `node/src/node.js`. | |||
| * | |||
| * XXX: It's lame that node doesn't expose this API out-of-the-box. It also | |||
| * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame. | |||
| */ | |||
| function createWritableStdioStream (fd) { | |||
| var stream; | |||
| var tty_wrap = process.binding('tty_wrap'); | |||
| // Note stream._type is used for test-module-load-list.js | |||
| switch (tty_wrap.guessHandleType(fd)) { | |||
| case 'TTY': | |||
| stream = new tty.WriteStream(fd); | |||
| stream._type = 'tty'; | |||
| // Hack to have stream not keep the event loop alive. | |||
| // See https://github.com/joyent/node/issues/1726 | |||
| if (stream._handle && stream._handle.unref) { | |||
| stream._handle.unref(); | |||
| } | |||
| break; | |||
| case 'FILE': | |||
| var fs = require('fs'); | |||
| stream = new fs.SyncWriteStream(fd, { autoClose: false }); | |||
| stream._type = 'fs'; | |||
| break; | |||
| case 'PIPE': | |||
| case 'TCP': | |||
| var net = require('net'); | |||
| stream = new net.Socket({ | |||
| fd: fd, | |||
| readable: false, | |||
| writable: true | |||
| }); | |||
| // FIXME Should probably have an option in net.Socket to create a | |||
| // stream from an existing fd which is writable only. But for now | |||
| // we'll just add this hack and set the `readable` member to false. | |||
| // Test: ./node test/fixtures/echo.js < /etc/passwd | |||
| stream.readable = false; | |||
| stream.read = null; | |||
| stream._type = 'pipe'; | |||
| // FIXME Hack to have stream not keep the event loop alive. | |||
| // See https://github.com/joyent/node/issues/1726 | |||
| if (stream._handle && stream._handle.unref) { | |||
| stream._handle.unref(); | |||
| } | |||
| break; | |||
| default: | |||
| // Probably an error on in uv_guess_handle() | |||
| throw new Error('Implement me. Unknown stream file type!'); | |||
| } | |||
| // For supporting legacy API we put the FD here. | |||
| stream.fd = fd; | |||
| stream._isStdio = true; | |||
| return stream; | |||
| } | |||
| /** | |||
| * Init logic for `debug` instances. | |||
| * | |||
| * Create a new `inspectOpts` object in case `useColors` is set | |||
| * differently for a particular `debug` instance. | |||
| */ | |||
| function init (debug) { | |||
| debug.inspectOpts = {}; | |||
| var keys = Object.keys(exports.inspectOpts); | |||
| for (var i = 0; i < keys.length; i++) { | |||
| debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; | |||
| } | |||
| } | |||
| /** | |||
| * Enable namespaces listed in `process.env.DEBUG` initially. | |||
| */ | |||
| exports.enable(load()); | |||
| @@ -0,0 +1,96 @@ | |||
| 1.1.2 / 2018-01-11 | |||
| ================== | |||
| * perf: remove argument reassignment | |||
| * Support Node.js 0.6 to 9.x | |||
| 1.1.1 / 2017-07-27 | |||
| ================== | |||
| * Remove unnecessary `Buffer` loading | |||
| * Support Node.js 0.6 to 8.x | |||
| 1.1.0 / 2015-09-14 | |||
| ================== | |||
| * Enable strict mode in more places | |||
| * Support io.js 3.x | |||
| * Support io.js 2.x | |||
| * Support web browser loading | |||
| - Requires bundler like Browserify or webpack | |||
| 1.0.1 / 2015-04-07 | |||
| ================== | |||
| * Fix `TypeError`s when under `'use strict'` code | |||
| * Fix useless type name on auto-generated messages | |||
| * Support io.js 1.x | |||
| * Support Node.js 0.12 | |||
| 1.0.0 / 2014-09-17 | |||
| ================== | |||
| * No changes | |||
| 0.4.5 / 2014-09-09 | |||
| ================== | |||
| * Improve call speed to functions using the function wrapper | |||
| * Support Node.js 0.6 | |||
| 0.4.4 / 2014-07-27 | |||
| ================== | |||
| * Work-around v8 generating empty stack traces | |||
| 0.4.3 / 2014-07-26 | |||
| ================== | |||
| * Fix exception when global `Error.stackTraceLimit` is too low | |||
| 0.4.2 / 2014-07-19 | |||
| ================== | |||
| * Correct call site for wrapped functions and properties | |||
| 0.4.1 / 2014-07-19 | |||
| ================== | |||
| * Improve automatic message generation for function properties | |||
| 0.4.0 / 2014-07-19 | |||
| ================== | |||
| * Add `TRACE_DEPRECATION` environment variable | |||
| * Remove non-standard grey color from color output | |||
| * Support `--no-deprecation` argument | |||
| * Support `--trace-deprecation` argument | |||
| * Support `deprecate.property(fn, prop, message)` | |||
| 0.3.0 / 2014-06-16 | |||
| ================== | |||
| * Add `NO_DEPRECATION` environment variable | |||
| 0.2.0 / 2014-06-15 | |||
| ================== | |||
| * Add `deprecate.property(obj, prop, message)` | |||
| * Remove `supports-color` dependency for node.js 0.8 | |||
| 0.1.0 / 2014-06-15 | |||
| ================== | |||
| * Add `deprecate.function(fn, message)` | |||
| * Add `process.on('deprecation', fn)` emitter | |||
| * Automatically generate message when omitted from `deprecate()` | |||
| 0.0.1 / 2014-06-15 | |||
| ================== | |||
| * Fix warning for dynamic calls at singe call site | |||
| 0.0.0 / 2014-06-15 | |||
| ================== | |||
| * Initial implementation | |||
| @@ -0,0 +1,22 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2014-2017 Douglas Christopher Wilson | |||
| 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. | |||
| @@ -0,0 +1,280 @@ | |||
| # depd | |||
| [![NPM Version][npm-version-image]][npm-url] | |||
| [![NPM Downloads][npm-downloads-image]][npm-url] | |||
| [![Node.js Version][node-image]][node-url] | |||
| [![Linux Build][travis-image]][travis-url] | |||
| [![Windows Build][appveyor-image]][appveyor-url] | |||
| [![Coverage Status][coveralls-image]][coveralls-url] | |||
| Deprecate all the things | |||
| > With great modules comes great responsibility; mark things deprecated! | |||
| ## Install | |||
| This module is installed directly using `npm`: | |||
| ```sh | |||
| $ npm install depd | |||
| ``` | |||
| This module can also be bundled with systems like | |||
| [Browserify](http://browserify.org/) or [webpack](https://webpack.github.io/), | |||
| though by default this module will alter it's API to no longer display or | |||
| track deprecations. | |||
| ## API | |||
| <!-- eslint-disable no-unused-vars --> | |||
| ```js | |||
| var deprecate = require('depd')('my-module') | |||
| ``` | |||
| This library allows you to display deprecation messages to your users. | |||
| This library goes above and beyond with deprecation warnings by | |||
| introspection of the call stack (but only the bits that it is interested | |||
| in). | |||
| Instead of just warning on the first invocation of a deprecated | |||
| function and never again, this module will warn on the first invocation | |||
| of a deprecated function per unique call site, making it ideal to alert | |||
| users of all deprecated uses across the code base, rather than just | |||
| whatever happens to execute first. | |||
| The deprecation warnings from this module also include the file and line | |||
| information for the call into the module that the deprecated function was | |||
| in. | |||
| **NOTE** this library has a similar interface to the `debug` module, and | |||
| this module uses the calling file to get the boundary for the call stacks, | |||
| so you should always create a new `deprecate` object in each file and not | |||
| within some central file. | |||
| ### depd(namespace) | |||
| Create a new deprecate function that uses the given namespace name in the | |||
| messages and will display the call site prior to the stack entering the | |||
| file this function was called from. It is highly suggested you use the | |||
| name of your module as the namespace. | |||
| ### deprecate(message) | |||
| Call this function from deprecated code to display a deprecation message. | |||
| This message will appear once per unique caller site. Caller site is the | |||
| first call site in the stack in a different file from the caller of this | |||
| function. | |||
| If the message is omitted, a message is generated for you based on the site | |||
| of the `deprecate()` call and will display the name of the function called, | |||
| similar to the name displayed in a stack trace. | |||
| ### deprecate.function(fn, message) | |||
| Call this function to wrap a given function in a deprecation message on any | |||
| call to the function. An optional message can be supplied to provide a custom | |||
| message. | |||
| ### deprecate.property(obj, prop, message) | |||
| Call this function to wrap a given property on object in a deprecation message | |||
| on any accessing or setting of the property. An optional message can be supplied | |||
| to provide a custom message. | |||
| The method must be called on the object where the property belongs (not | |||
| inherited from the prototype). | |||
| If the property is a data descriptor, it will be converted to an accessor | |||
| descriptor in order to display the deprecation message. | |||
| ### process.on('deprecation', fn) | |||
| This module will allow easy capturing of deprecation errors by emitting the | |||
| errors as the type "deprecation" on the global `process`. If there are no | |||
| listeners for this type, the errors are written to STDERR as normal, but if | |||
| there are any listeners, nothing will be written to STDERR and instead only | |||
| emitted. From there, you can write the errors in a different format or to a | |||
| logging source. | |||
| The error represents the deprecation and is emitted only once with the same | |||
| rules as writing to STDERR. The error has the following properties: | |||
| - `message` - This is the message given by the library | |||
| - `name` - This is always `'DeprecationError'` | |||
| - `namespace` - This is the namespace the deprecation came from | |||
| - `stack` - This is the stack of the call to the deprecated thing | |||
| Example `error.stack` output: | |||
| ``` | |||
| DeprecationError: my-cool-module deprecated oldfunction | |||
| at Object.<anonymous> ([eval]-wrapper:6:22) | |||
| at Module._compile (module.js:456:26) | |||
| at evalScript (node.js:532:25) | |||
| at startup (node.js:80:7) | |||
| at node.js:902:3 | |||
| ``` | |||
| ### process.env.NO_DEPRECATION | |||
| As a user of modules that are deprecated, the environment variable `NO_DEPRECATION` | |||
| is provided as a quick solution to silencing deprecation warnings from being | |||
| output. The format of this is similar to that of `DEBUG`: | |||
| ```sh | |||
| $ NO_DEPRECATION=my-module,othermod node app.js | |||
| ``` | |||
| This will suppress deprecations from being output for "my-module" and "othermod". | |||
| The value is a list of comma-separated namespaces. To suppress every warning | |||
| across all namespaces, use the value `*` for a namespace. | |||
| Providing the argument `--no-deprecation` to the `node` executable will suppress | |||
| all deprecations (only available in Node.js 0.8 or higher). | |||
| **NOTE** This will not suppress the deperecations given to any "deprecation" | |||
| event listeners, just the output to STDERR. | |||
| ### process.env.TRACE_DEPRECATION | |||
| As a user of modules that are deprecated, the environment variable `TRACE_DEPRECATION` | |||
| is provided as a solution to getting more detailed location information in deprecation | |||
| warnings by including the entire stack trace. The format of this is the same as | |||
| `NO_DEPRECATION`: | |||
| ```sh | |||
| $ TRACE_DEPRECATION=my-module,othermod node app.js | |||
| ``` | |||
| This will include stack traces for deprecations being output for "my-module" and | |||
| "othermod". The value is a list of comma-separated namespaces. To trace every | |||
| warning across all namespaces, use the value `*` for a namespace. | |||
| Providing the argument `--trace-deprecation` to the `node` executable will trace | |||
| all deprecations (only available in Node.js 0.8 or higher). | |||
| **NOTE** This will not trace the deperecations silenced by `NO_DEPRECATION`. | |||
| ## Display | |||
|  | |||
| When a user calls a function in your library that you mark deprecated, they | |||
| will see the following written to STDERR (in the given colors, similar colors | |||
| and layout to the `debug` module): | |||
| ``` | |||
| bright cyan bright yellow | |||
| | | reset cyan | |||
| | | | | | |||
| ▼ ▼ ▼ ▼ | |||
| my-cool-module deprecated oldfunction [eval]-wrapper:6:22 | |||
| ▲ ▲ ▲ ▲ | |||
| | | | | | |||
| namespace | | location of mycoolmod.oldfunction() call | |||
| | deprecation message | |||
| the word "deprecated" | |||
| ``` | |||
| If the user redirects their STDERR to a file or somewhere that does not support | |||
| colors, they see (similar layout to the `debug` module): | |||
| ``` | |||
| Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22 | |||
| ▲ ▲ ▲ ▲ ▲ | |||
| | | | | | | |||
| timestamp of message namespace | | location of mycoolmod.oldfunction() call | |||
| | deprecation message | |||
| the word "deprecated" | |||
| ``` | |||
| ## Examples | |||
| ### Deprecating all calls to a function | |||
| This will display a deprecated message about "oldfunction" being deprecated | |||
| from "my-module" on STDERR. | |||
| ```js | |||
| var deprecate = require('depd')('my-cool-module') | |||
| // message automatically derived from function name | |||
| // Object.oldfunction | |||
| exports.oldfunction = deprecate.function(function oldfunction () { | |||
| // all calls to function are deprecated | |||
| }) | |||
| // specific message | |||
| exports.oldfunction = deprecate.function(function () { | |||
| // all calls to function are deprecated | |||
| }, 'oldfunction') | |||
| ``` | |||
| ### Conditionally deprecating a function call | |||
| This will display a deprecated message about "weirdfunction" being deprecated | |||
| from "my-module" on STDERR when called with less than 2 arguments. | |||
| ```js | |||
| var deprecate = require('depd')('my-cool-module') | |||
| exports.weirdfunction = function () { | |||
| if (arguments.length < 2) { | |||
| // calls with 0 or 1 args are deprecated | |||
| deprecate('weirdfunction args < 2') | |||
| } | |||
| } | |||
| ``` | |||
| When calling `deprecate` as a function, the warning is counted per call site | |||
| within your own module, so you can display different deprecations depending | |||
| on different situations and the users will still get all the warnings: | |||
| ```js | |||
| var deprecate = require('depd')('my-cool-module') | |||
| exports.weirdfunction = function () { | |||
| if (arguments.length < 2) { | |||
| // calls with 0 or 1 args are deprecated | |||
| deprecate('weirdfunction args < 2') | |||
| } else if (typeof arguments[0] !== 'string') { | |||
| // calls with non-string first argument are deprecated | |||
| deprecate('weirdfunction non-string first arg') | |||
| } | |||
| } | |||
| ``` | |||
| ### Deprecating property access | |||
| This will display a deprecated message about "oldprop" being deprecated | |||
| from "my-module" on STDERR when accessed. A deprecation will be displayed | |||
| when setting the value and when getting the value. | |||
| ```js | |||
| var deprecate = require('depd')('my-cool-module') | |||
| exports.oldprop = 'something' | |||
| // message automatically derives from property name | |||
| deprecate.property(exports, 'oldprop') | |||
| // explicit message | |||
| deprecate.property(exports, 'oldprop', 'oldprop >= 0.10') | |||
| ``` | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-version-image]: https://img.shields.io/npm/v/depd.svg | |||
| [npm-downloads-image]: https://img.shields.io/npm/dm/depd.svg | |||
| [npm-url]: https://npmjs.org/package/depd | |||
| [travis-image]: https://img.shields.io/travis/dougwilson/nodejs-depd/master.svg?label=linux | |||
| [travis-url]: https://travis-ci.org/dougwilson/nodejs-depd | |||
| [appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/nodejs-depd/master.svg?label=windows | |||
| [appveyor-url]: https://ci.appveyor.com/project/dougwilson/nodejs-depd | |||
| [coveralls-image]: https://img.shields.io/coveralls/dougwilson/nodejs-depd/master.svg | |||
| [coveralls-url]: https://coveralls.io/r/dougwilson/nodejs-depd?branch=master | |||
| [node-image]: https://img.shields.io/node/v/depd.svg | |||
| [node-url]: https://nodejs.org/en/download/ | |||
| @@ -0,0 +1,522 @@ | |||
| /*! | |||
| * depd | |||
| * Copyright(c) 2014-2017 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| /** | |||
| * Module dependencies. | |||
| */ | |||
| var callSiteToString = require('./lib/compat').callSiteToString | |||
| var eventListenerCount = require('./lib/compat').eventListenerCount | |||
| var relative = require('path').relative | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = depd | |||
| /** | |||
| * Get the path to base files on. | |||
| */ | |||
| var basePath = process.cwd() | |||
| /** | |||
| * Determine if namespace is contained in the string. | |||
| */ | |||
| function containsNamespace (str, namespace) { | |||
| var vals = str.split(/[ ,]+/) | |||
| var ns = String(namespace).toLowerCase() | |||
| for (var i = 0; i < vals.length; i++) { | |||
| var val = vals[i] | |||
| // namespace contained | |||
| if (val && (val === '*' || val.toLowerCase() === ns)) { | |||
| return true | |||
| } | |||
| } | |||
| return false | |||
| } | |||
| /** | |||
| * Convert a data descriptor to accessor descriptor. | |||
| */ | |||
| function convertDataDescriptorToAccessor (obj, prop, message) { | |||
| var descriptor = Object.getOwnPropertyDescriptor(obj, prop) | |||
| var value = descriptor.value | |||
| descriptor.get = function getter () { return value } | |||
| if (descriptor.writable) { | |||
| descriptor.set = function setter (val) { return (value = val) } | |||
| } | |||
| delete descriptor.value | |||
| delete descriptor.writable | |||
| Object.defineProperty(obj, prop, descriptor) | |||
| return descriptor | |||
| } | |||
| /** | |||
| * Create arguments string to keep arity. | |||
| */ | |||
| function createArgumentsString (arity) { | |||
| var str = '' | |||
| for (var i = 0; i < arity; i++) { | |||
| str += ', arg' + i | |||
| } | |||
| return str.substr(2) | |||
| } | |||
| /** | |||
| * Create stack string from stack. | |||
| */ | |||
| function createStackString (stack) { | |||
| var str = this.name + ': ' + this.namespace | |||
| if (this.message) { | |||
| str += ' deprecated ' + this.message | |||
| } | |||
| for (var i = 0; i < stack.length; i++) { | |||
| str += '\n at ' + callSiteToString(stack[i]) | |||
| } | |||
| return str | |||
| } | |||
| /** | |||
| * Create deprecate for namespace in caller. | |||
| */ | |||
| function depd (namespace) { | |||
| if (!namespace) { | |||
| throw new TypeError('argument namespace is required') | |||
| } | |||
| var stack = getStack() | |||
| var site = callSiteLocation(stack[1]) | |||
| var file = site[0] | |||
| function deprecate (message) { | |||
| // call to self as log | |||
| log.call(deprecate, message) | |||
| } | |||
| deprecate._file = file | |||
| deprecate._ignored = isignored(namespace) | |||
| deprecate._namespace = namespace | |||
| deprecate._traced = istraced(namespace) | |||
| deprecate._warned = Object.create(null) | |||
| deprecate.function = wrapfunction | |||
| deprecate.property = wrapproperty | |||
| return deprecate | |||
| } | |||
| /** | |||
| * Determine if namespace is ignored. | |||
| */ | |||
| function isignored (namespace) { | |||
| /* istanbul ignore next: tested in a child processs */ | |||
| if (process.noDeprecation) { | |||
| // --no-deprecation support | |||
| return true | |||
| } | |||
| var str = process.env.NO_DEPRECATION || '' | |||
| // namespace ignored | |||
| return containsNamespace(str, namespace) | |||
| } | |||
| /** | |||
| * Determine if namespace is traced. | |||
| */ | |||
| function istraced (namespace) { | |||
| /* istanbul ignore next: tested in a child processs */ | |||
| if (process.traceDeprecation) { | |||
| // --trace-deprecation support | |||
| return true | |||
| } | |||
| var str = process.env.TRACE_DEPRECATION || '' | |||
| // namespace traced | |||
| return containsNamespace(str, namespace) | |||
| } | |||
| /** | |||
| * Display deprecation message. | |||
| */ | |||
| function log (message, site) { | |||
| var haslisteners = eventListenerCount(process, 'deprecation') !== 0 | |||
| // abort early if no destination | |||
| if (!haslisteners && this._ignored) { | |||
| return | |||
| } | |||
| var caller | |||
| var callFile | |||
| var callSite | |||
| var depSite | |||
| var i = 0 | |||
| var seen = false | |||
| var stack = getStack() | |||
| var file = this._file | |||
| if (site) { | |||
| // provided site | |||
| depSite = site | |||
| callSite = callSiteLocation(stack[1]) | |||
| callSite.name = depSite.name | |||
| file = callSite[0] | |||
| } else { | |||
| // get call site | |||
| i = 2 | |||
| depSite = callSiteLocation(stack[i]) | |||
| callSite = depSite | |||
| } | |||
| // get caller of deprecated thing in relation to file | |||
| for (; i < stack.length; i++) { | |||
| caller = callSiteLocation(stack[i]) | |||
| callFile = caller[0] | |||
| if (callFile === file) { | |||
| seen = true | |||
| } else if (callFile === this._file) { | |||
| file = this._file | |||
| } else if (seen) { | |||
| break | |||
| } | |||
| } | |||
| var key = caller | |||
| ? depSite.join(':') + '__' + caller.join(':') | |||
| : undefined | |||
| if (key !== undefined && key in this._warned) { | |||
| // already warned | |||
| return | |||
| } | |||
| this._warned[key] = true | |||
| // generate automatic message from call site | |||
| var msg = message | |||
| if (!msg) { | |||
| msg = callSite === depSite || !callSite.name | |||
| ? defaultMessage(depSite) | |||
| : defaultMessage(callSite) | |||
| } | |||
| // emit deprecation if listeners exist | |||
| if (haslisteners) { | |||
| var err = DeprecationError(this._namespace, msg, stack.slice(i)) | |||
| process.emit('deprecation', err) | |||
| return | |||
| } | |||
| // format and write message | |||
| var format = process.stderr.isTTY | |||
| ? formatColor | |||
| : formatPlain | |||
| var output = format.call(this, msg, caller, stack.slice(i)) | |||
| process.stderr.write(output + '\n', 'utf8') | |||
| } | |||
| /** | |||
| * Get call site location as array. | |||
| */ | |||
| function callSiteLocation (callSite) { | |||
| var file = callSite.getFileName() || '<anonymous>' | |||
| var line = callSite.getLineNumber() | |||
| var colm = callSite.getColumnNumber() | |||
| if (callSite.isEval()) { | |||
| file = callSite.getEvalOrigin() + ', ' + file | |||
| } | |||
| var site = [file, line, colm] | |||
| site.callSite = callSite | |||
| site.name = callSite.getFunctionName() | |||
| return site | |||
| } | |||
| /** | |||
| * Generate a default message from the site. | |||
| */ | |||
| function defaultMessage (site) { | |||
| var callSite = site.callSite | |||
| var funcName = site.name | |||
| // make useful anonymous name | |||
| if (!funcName) { | |||
| funcName = '<anonymous@' + formatLocation(site) + '>' | |||
| } | |||
| var context = callSite.getThis() | |||
| var typeName = context && callSite.getTypeName() | |||
| // ignore useless type name | |||
| if (typeName === 'Object') { | |||
| typeName = undefined | |||
| } | |||
| // make useful type name | |||
| if (typeName === 'Function') { | |||
| typeName = context.name || typeName | |||
| } | |||
| return typeName && callSite.getMethodName() | |||
| ? typeName + '.' + funcName | |||
| : funcName | |||
| } | |||
| /** | |||
| * Format deprecation message without color. | |||
| */ | |||
| function formatPlain (msg, caller, stack) { | |||
| var timestamp = new Date().toUTCString() | |||
| var formatted = timestamp + | |||
| ' ' + this._namespace + | |||
| ' deprecated ' + msg | |||
| // add stack trace | |||
| if (this._traced) { | |||
| for (var i = 0; i < stack.length; i++) { | |||
| formatted += '\n at ' + callSiteToString(stack[i]) | |||
| } | |||
| return formatted | |||
| } | |||
| if (caller) { | |||
| formatted += ' at ' + formatLocation(caller) | |||
| } | |||
| return formatted | |||
| } | |||
| /** | |||
| * Format deprecation message with color. | |||
| */ | |||
| function formatColor (msg, caller, stack) { | |||
| var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' + // bold cyan | |||
| ' \x1b[33;1mdeprecated\x1b[22;39m' + // bold yellow | |||
| ' \x1b[0m' + msg + '\x1b[39m' // reset | |||
| // add stack trace | |||
| if (this._traced) { | |||
| for (var i = 0; i < stack.length; i++) { | |||
| formatted += '\n \x1b[36mat ' + callSiteToString(stack[i]) + '\x1b[39m' // cyan | |||
| } | |||
| return formatted | |||
| } | |||
| if (caller) { | |||
| formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan | |||
| } | |||
| return formatted | |||
| } | |||
| /** | |||
| * Format call site location. | |||
| */ | |||
| function formatLocation (callSite) { | |||
| return relative(basePath, callSite[0]) + | |||
| ':' + callSite[1] + | |||
| ':' + callSite[2] | |||
| } | |||
| /** | |||
| * Get the stack as array of call sites. | |||
| */ | |||
| function getStack () { | |||
| var limit = Error.stackTraceLimit | |||
| var obj = {} | |||
| var prep = Error.prepareStackTrace | |||
| Error.prepareStackTrace = prepareObjectStackTrace | |||
| Error.stackTraceLimit = Math.max(10, limit) | |||
| // capture the stack | |||
| Error.captureStackTrace(obj) | |||
| // slice this function off the top | |||
| var stack = obj.stack.slice(1) | |||
| Error.prepareStackTrace = prep | |||
| Error.stackTraceLimit = limit | |||
| return stack | |||
| } | |||
| /** | |||
| * Capture call site stack from v8. | |||
| */ | |||
| function prepareObjectStackTrace (obj, stack) { | |||
| return stack | |||
| } | |||
| /** | |||
| * Return a wrapped function in a deprecation message. | |||
| */ | |||
| function wrapfunction (fn, message) { | |||
| if (typeof fn !== 'function') { | |||
| throw new TypeError('argument fn must be a function') | |||
| } | |||
| var args = createArgumentsString(fn.length) | |||
| var deprecate = this // eslint-disable-line no-unused-vars | |||
| var stack = getStack() | |||
| var site = callSiteLocation(stack[1]) | |||
| site.name = fn.name | |||
| // eslint-disable-next-line no-eval | |||
| var deprecatedfn = eval('(function (' + args + ') {\n' + | |||
| '"use strict"\n' + | |||
| 'log.call(deprecate, message, site)\n' + | |||
| 'return fn.apply(this, arguments)\n' + | |||
| '})') | |||
| return deprecatedfn | |||
| } | |||
| /** | |||
| * Wrap property in a deprecation message. | |||
| */ | |||
| function wrapproperty (obj, prop, message) { | |||
| if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { | |||
| throw new TypeError('argument obj must be object') | |||
| } | |||
| var descriptor = Object.getOwnPropertyDescriptor(obj, prop) | |||
| if (!descriptor) { | |||
| throw new TypeError('must call property on owner object') | |||
| } | |||
| if (!descriptor.configurable) { | |||
| throw new TypeError('property must be configurable') | |||
| } | |||
| var deprecate = this | |||
| var stack = getStack() | |||
| var site = callSiteLocation(stack[1]) | |||
| // set site name | |||
| site.name = prop | |||
| // convert data descriptor | |||
| if ('value' in descriptor) { | |||
| descriptor = convertDataDescriptorToAccessor(obj, prop, message) | |||
| } | |||
| var get = descriptor.get | |||
| var set = descriptor.set | |||
| // wrap getter | |||
| if (typeof get === 'function') { | |||
| descriptor.get = function getter () { | |||
| log.call(deprecate, message, site) | |||
| return get.apply(this, arguments) | |||
| } | |||
| } | |||
| // wrap setter | |||
| if (typeof set === 'function') { | |||
| descriptor.set = function setter () { | |||
| log.call(deprecate, message, site) | |||
| return set.apply(this, arguments) | |||
| } | |||
| } | |||
| Object.defineProperty(obj, prop, descriptor) | |||
| } | |||
| /** | |||
| * Create DeprecationError for deprecation | |||
| */ | |||
| function DeprecationError (namespace, message, stack) { | |||
| var error = new Error() | |||
| var stackString | |||
| Object.defineProperty(error, 'constructor', { | |||
| value: DeprecationError | |||
| }) | |||
| Object.defineProperty(error, 'message', { | |||
| configurable: true, | |||
| enumerable: false, | |||
| value: message, | |||
| writable: true | |||
| }) | |||
| Object.defineProperty(error, 'name', { | |||
| enumerable: false, | |||
| configurable: true, | |||
| value: 'DeprecationError', | |||
| writable: true | |||
| }) | |||
| Object.defineProperty(error, 'namespace', { | |||
| configurable: true, | |||
| enumerable: false, | |||
| value: namespace, | |||
| writable: true | |||
| }) | |||
| Object.defineProperty(error, 'stack', { | |||
| configurable: true, | |||
| enumerable: false, | |||
| get: function () { | |||
| if (stackString !== undefined) { | |||
| return stackString | |||
| } | |||
| // prepare stack trace | |||
| return (stackString = createStackString.call(this, stack)) | |||
| }, | |||
| set: function setter (val) { | |||
| stackString = val | |||
| } | |||
| }) | |||
| return error | |||
| } | |||
| @@ -0,0 +1,77 @@ | |||
| /*! | |||
| * depd | |||
| * Copyright(c) 2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = depd | |||
| /** | |||
| * Create deprecate for namespace in caller. | |||
| */ | |||
| function depd (namespace) { | |||
| if (!namespace) { | |||
| throw new TypeError('argument namespace is required') | |||
| } | |||
| function deprecate (message) { | |||
| // no-op in browser | |||
| } | |||
| deprecate._file = undefined | |||
| deprecate._ignored = true | |||
| deprecate._namespace = namespace | |||
| deprecate._traced = false | |||
| deprecate._warned = Object.create(null) | |||
| deprecate.function = wrapfunction | |||
| deprecate.property = wrapproperty | |||
| return deprecate | |||
| } | |||
| /** | |||
| * Return a wrapped function in a deprecation message. | |||
| * | |||
| * This is a no-op version of the wrapper, which does nothing but call | |||
| * validation. | |||
| */ | |||
| function wrapfunction (fn, message) { | |||
| if (typeof fn !== 'function') { | |||
| throw new TypeError('argument fn must be a function') | |||
| } | |||
| return fn | |||
| } | |||
| /** | |||
| * Wrap property in a deprecation message. | |||
| * | |||
| * This is a no-op version of the wrapper, which does nothing but call | |||
| * validation. | |||
| */ | |||
| function wrapproperty (obj, prop, message) { | |||
| if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) { | |||
| throw new TypeError('argument obj must be object') | |||
| } | |||
| var descriptor = Object.getOwnPropertyDescriptor(obj, prop) | |||
| if (!descriptor) { | |||
| throw new TypeError('must call property on owner object') | |||
| } | |||
| if (!descriptor.configurable) { | |||
| throw new TypeError('property must be configurable') | |||
| } | |||
| } | |||
| @@ -0,0 +1,103 @@ | |||
| /*! | |||
| * depd | |||
| * Copyright(c) 2014 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| */ | |||
| module.exports = callSiteToString | |||
| /** | |||
| * Format a CallSite file location to a string. | |||
| */ | |||
| function callSiteFileLocation (callSite) { | |||
| var fileName | |||
| var fileLocation = '' | |||
| if (callSite.isNative()) { | |||
| fileLocation = 'native' | |||
| } else if (callSite.isEval()) { | |||
| fileName = callSite.getScriptNameOrSourceURL() | |||
| if (!fileName) { | |||
| fileLocation = callSite.getEvalOrigin() | |||
| } | |||
| } else { | |||
| fileName = callSite.getFileName() | |||
| } | |||
| if (fileName) { | |||
| fileLocation += fileName | |||
| var lineNumber = callSite.getLineNumber() | |||
| if (lineNumber != null) { | |||
| fileLocation += ':' + lineNumber | |||
| var columnNumber = callSite.getColumnNumber() | |||
| if (columnNumber) { | |||
| fileLocation += ':' + columnNumber | |||
| } | |||
| } | |||
| } | |||
| return fileLocation || 'unknown source' | |||
| } | |||
| /** | |||
| * Format a CallSite to a string. | |||
| */ | |||
| function callSiteToString (callSite) { | |||
| var addSuffix = true | |||
| var fileLocation = callSiteFileLocation(callSite) | |||
| var functionName = callSite.getFunctionName() | |||
| var isConstructor = callSite.isConstructor() | |||
| var isMethodCall = !(callSite.isToplevel() || isConstructor) | |||
| var line = '' | |||
| if (isMethodCall) { | |||
| var methodName = callSite.getMethodName() | |||
| var typeName = getConstructorName(callSite) | |||
| if (functionName) { | |||
| if (typeName && functionName.indexOf(typeName) !== 0) { | |||
| line += typeName + '.' | |||
| } | |||
| line += functionName | |||
| if (methodName && functionName.lastIndexOf('.' + methodName) !== functionName.length - methodName.length - 1) { | |||
| line += ' [as ' + methodName + ']' | |||
| } | |||
| } else { | |||
| line += typeName + '.' + (methodName || '<anonymous>') | |||
| } | |||
| } else if (isConstructor) { | |||
| line += 'new ' + (functionName || '<anonymous>') | |||
| } else if (functionName) { | |||
| line += functionName | |||
| } else { | |||
| addSuffix = false | |||
| line += fileLocation | |||
| } | |||
| if (addSuffix) { | |||
| line += ' (' + fileLocation + ')' | |||
| } | |||
| return line | |||
| } | |||
| /** | |||
| * Get constructor name of reviver. | |||
| */ | |||
| function getConstructorName (obj) { | |||
| var receiver = obj.receiver | |||
| return (receiver.constructor && receiver.constructor.name) || null | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| /*! | |||
| * depd | |||
| * Copyright(c) 2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = eventListenerCount | |||
| /** | |||
| * Get the count of listeners on an event emitter of a specific type. | |||
| */ | |||
| function eventListenerCount (emitter, type) { | |||
| return emitter.listeners(type).length | |||
| } | |||
| @@ -0,0 +1,79 @@ | |||
| /*! | |||
| * depd | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var EventEmitter = require('events').EventEmitter | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| lazyProperty(module.exports, 'callSiteToString', function callSiteToString () { | |||
| var limit = Error.stackTraceLimit | |||
| var obj = {} | |||
| var prep = Error.prepareStackTrace | |||
| function prepareObjectStackTrace (obj, stack) { | |||
| return stack | |||
| } | |||
| Error.prepareStackTrace = prepareObjectStackTrace | |||
| Error.stackTraceLimit = 2 | |||
| // capture the stack | |||
| Error.captureStackTrace(obj) | |||
| // slice the stack | |||
| var stack = obj.stack.slice() | |||
| Error.prepareStackTrace = prep | |||
| Error.stackTraceLimit = limit | |||
| return stack[0].toString ? toString : require('./callsite-tostring') | |||
| }) | |||
| lazyProperty(module.exports, 'eventListenerCount', function eventListenerCount () { | |||
| return EventEmitter.listenerCount || require('./event-listener-count') | |||
| }) | |||
| /** | |||
| * Define a lazy property. | |||
| */ | |||
| function lazyProperty (obj, prop, getter) { | |||
| function get () { | |||
| var val = getter() | |||
| Object.defineProperty(obj, prop, { | |||
| configurable: true, | |||
| enumerable: true, | |||
| value: val | |||
| }) | |||
| return val | |||
| } | |||
| Object.defineProperty(obj, prop, { | |||
| configurable: true, | |||
| enumerable: true, | |||
| get: get | |||
| }) | |||
| } | |||
| /** | |||
| * Call toString() on the obj | |||
| */ | |||
| function toString (obj) { | |||
| return obj.toString() | |||
| } | |||
| @@ -0,0 +1,107 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "depd@~1.1.2", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "depd@>=1.1.2 <1.2.0", | |||
| "_id": "depd@1.1.2", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/depd", | |||
| "_nodeVersion": "6.11.1", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/depd-1.1.2.tgz_1515736023686_0.5012104702182114" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "3.10.10", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "depd", | |||
| "raw": "depd@~1.1.2", | |||
| "rawSpec": "~1.1.2", | |||
| "scope": null, | |||
| "spec": ">=1.1.2 <1.2.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/body-parser", | |||
| "/express", | |||
| "/http-errors", | |||
| "/send" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | |||
| "_shasum": "9bcd52e14c097763e749b274c4346ed2e560b5a9", | |||
| "_shrinkwrap": null, | |||
| "_spec": "depd@~1.1.2", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "author": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "Douglas Christopher Wilson" | |||
| }, | |||
| "browser": "lib/browser/index.js", | |||
| "bugs": { | |||
| "url": "https://github.com/dougwilson/nodejs-depd/issues" | |||
| }, | |||
| "dependencies": {}, | |||
| "description": "Deprecate all the things", | |||
| "devDependencies": { | |||
| "beautify-benchmark": "0.2.4", | |||
| "benchmark": "2.1.4", | |||
| "eslint": "3.19.0", | |||
| "eslint-config-standard": "7.1.0", | |||
| "eslint-plugin-markdown": "1.0.0-beta.7", | |||
| "eslint-plugin-promise": "3.6.0", | |||
| "eslint-plugin-standard": "3.0.1", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "~1.21.5" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "9bcd52e14c097763e749b274c4346ed2e560b5a9", | |||
| "tarball": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "files": [ | |||
| "History.md", | |||
| "LICENSE", | |||
| "Readme.md", | |||
| "index.js", | |||
| "lib/" | |||
| ], | |||
| "gitHead": "9a789740084d4f07a3a611432435ae4671f722ff", | |||
| "homepage": "https://github.com/dougwilson/nodejs-depd#readme", | |||
| "keywords": [ | |||
| "deprecate", | |||
| "deprecated" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "depd", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/dougwilson/nodejs-depd.git" | |||
| }, | |||
| "scripts": { | |||
| "bench": "node benchmark/index.js", | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --reporter spec --bail test/", | |||
| "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --no-exit test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot test/" | |||
| }, | |||
| "version": "1.1.2" | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2014 Jonathan Ong me@jongleberry.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. | |||
| @@ -0,0 +1,60 @@ | |||
| # Destroy | |||
| [![NPM version][npm-image]][npm-url] | |||
| [![Build status][travis-image]][travis-url] | |||
| [![Test coverage][coveralls-image]][coveralls-url] | |||
| [![License][license-image]][license-url] | |||
| [![Downloads][downloads-image]][downloads-url] | |||
| [![Gittip][gittip-image]][gittip-url] | |||
| Destroy a stream. | |||
| This module is meant to ensure a stream gets destroyed, handling different APIs | |||
| and Node.js bugs. | |||
| ## API | |||
| ```js | |||
| var destroy = require('destroy') | |||
| ``` | |||
| ### destroy(stream) | |||
| Destroy the given stream. In most cases, this is identical to a simple | |||
| `stream.destroy()` call. The rules are as follows for a given stream: | |||
| 1. If the `stream` is an instance of `ReadStream`, then call `stream.destroy()` | |||
| and add a listener to the `open` event to call `stream.close()` if it is | |||
| fired. This is for a Node.js bug that will leak a file descriptor if | |||
| `.destroy()` is called before `open`. | |||
| 2. If the `stream` is not an instance of `Stream`, then nothing happens. | |||
| 3. If the `stream` has a `.destroy()` method, then call it. | |||
| The function returns the `stream` passed in as the argument. | |||
| ## Example | |||
| ```js | |||
| var destroy = require('destroy') | |||
| var fs = require('fs') | |||
| var stream = fs.createReadStream('package.json') | |||
| // ... and later | |||
| destroy(stream) | |||
| ``` | |||
| [npm-image]: https://img.shields.io/npm/v/destroy.svg?style=flat-square | |||
| [npm-url]: https://npmjs.org/package/destroy | |||
| [github-tag]: http://img.shields.io/github/tag/stream-utils/destroy.svg?style=flat-square | |||
| [github-url]: https://github.com/stream-utils/destroy/tags | |||
| [travis-image]: https://img.shields.io/travis/stream-utils/destroy.svg?style=flat-square | |||
| [travis-url]: https://travis-ci.org/stream-utils/destroy | |||
| [coveralls-image]: https://img.shields.io/coveralls/stream-utils/destroy.svg?style=flat-square | |||
| [coveralls-url]: https://coveralls.io/r/stream-utils/destroy?branch=master | |||
| [license-image]: http://img.shields.io/npm/l/destroy.svg?style=flat-square | |||
| [license-url]: LICENSE.md | |||
| [downloads-image]: http://img.shields.io/npm/dm/destroy.svg?style=flat-square | |||
| [downloads-url]: https://npmjs.org/package/destroy | |||
| [gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square | |||
| [gittip-url]: https://www.gittip.com/jonathanong/ | |||
| @@ -0,0 +1,75 @@ | |||
| /*! | |||
| * destroy | |||
| * Copyright(c) 2014 Jonathan Ong | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var ReadStream = require('fs').ReadStream | |||
| var Stream = require('stream') | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = destroy | |||
| /** | |||
| * Destroy a stream. | |||
| * | |||
| * @param {object} stream | |||
| * @public | |||
| */ | |||
| function destroy(stream) { | |||
| if (stream instanceof ReadStream) { | |||
| return destroyReadStream(stream) | |||
| } | |||
| if (!(stream instanceof Stream)) { | |||
| return stream | |||
| } | |||
| if (typeof stream.destroy === 'function') { | |||
| stream.destroy() | |||
| } | |||
| return stream | |||
| } | |||
| /** | |||
| * Destroy a ReadStream. | |||
| * | |||
| * @param {object} stream | |||
| * @private | |||
| */ | |||
| function destroyReadStream(stream) { | |||
| stream.destroy() | |||
| if (typeof stream.close === 'function') { | |||
| // node.js core bug work-around | |||
| stream.on('open', onOpenClose) | |||
| } | |||
| return stream | |||
| } | |||
| /** | |||
| * On open handler to close stream. | |||
| * @private | |||
| */ | |||
| function onOpenClose() { | |||
| if (typeof this.fd === 'number') { | |||
| // actually close down the fd | |||
| this.close() | |||
| } | |||
| } | |||
| @@ -0,0 +1,98 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "destroy@~1.0.4", | |||
| "/var/www/noelle.codes/node/node_modules/send" | |||
| ] | |||
| ], | |||
| "_from": "destroy@>=1.0.4 <1.1.0", | |||
| "_id": "destroy@1.0.4", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/destroy", | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "1.4.28", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "destroy", | |||
| "raw": "destroy@~1.0.4", | |||
| "rawSpec": "~1.0.4", | |||
| "scope": null, | |||
| "spec": ">=1.0.4 <1.1.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/send" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", | |||
| "_shasum": "978857442c44749e4206613e37946205826abd80", | |||
| "_shrinkwrap": null, | |||
| "_spec": "destroy@~1.0.4", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/send", | |||
| "author": { | |||
| "email": "me@jongleberry.com", | |||
| "name": "Jonathan Ong", | |||
| "url": "http://jongleberry.com" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/stream-utils/destroy/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "destroy a stream if possible", | |||
| "devDependencies": { | |||
| "istanbul": "0.4.2", | |||
| "mocha": "2.3.4" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "978857442c44749e4206613e37946205826abd80", | |||
| "tarball": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" | |||
| }, | |||
| "files": [ | |||
| "LICENSE", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "86edea01456f5fa1027f6a47250c34c713cbcc3b", | |||
| "homepage": "https://github.com/stream-utils/destroy", | |||
| "keywords": [ | |||
| "cleanup", | |||
| "destroy", | |||
| "fd", | |||
| "leak", | |||
| "stream", | |||
| "streams" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "jongleberry", | |||
| "email": "jonathanrichardong@gmail.com" | |||
| }, | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "destroy", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/stream-utils/destroy.git" | |||
| }, | |||
| "scripts": { | |||
| "test": "mocha --reporter spec", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter dot" | |||
| }, | |||
| "version": "1.0.4" | |||
| } | |||
| @@ -0,0 +1,22 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2014 Jonathan Ong me@jongleberry.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. | |||
| @@ -0,0 +1,80 @@ | |||
| # EE First | |||
| [![NPM version][npm-image]][npm-url] | |||
| [![Build status][travis-image]][travis-url] | |||
| [![Test coverage][coveralls-image]][coveralls-url] | |||
| [![License][license-image]][license-url] | |||
| [![Downloads][downloads-image]][downloads-url] | |||
| [![Gittip][gittip-image]][gittip-url] | |||
| Get the first event in a set of event emitters and event pairs, | |||
| then clean up after itself. | |||
| ## Install | |||
| ```sh | |||
| $ npm install ee-first | |||
| ``` | |||
| ## API | |||
| ```js | |||
| var first = require('ee-first') | |||
| ``` | |||
| ### first(arr, listener) | |||
| Invoke `listener` on the first event from the list specified in `arr`. `arr` is | |||
| an array of arrays, with each array in the format `[ee, ...event]`. `listener` | |||
| will be called only once, the first time any of the given events are emitted. If | |||
| `error` is one of the listened events, then if that fires first, the `listener` | |||
| will be given the `err` argument. | |||
| The `listener` is invoked as `listener(err, ee, event, args)`, where `err` is the | |||
| first argument emitted from an `error` event, if applicable; `ee` is the event | |||
| emitter that fired; `event` is the string event name that fired; and `args` is an | |||
| array of the arguments that were emitted on the event. | |||
| ```js | |||
| var ee1 = new EventEmitter() | |||
| var ee2 = new EventEmitter() | |||
| first([ | |||
| [ee1, 'close', 'end', 'error'], | |||
| [ee2, 'error'] | |||
| ], function (err, ee, event, args) { | |||
| // listener invoked | |||
| }) | |||
| ``` | |||
| #### .cancel() | |||
| The group of listeners can be cancelled before being invoked and have all the event | |||
| listeners removed from the underlying event emitters. | |||
| ```js | |||
| var thunk = first([ | |||
| [ee1, 'close', 'end', 'error'], | |||
| [ee2, 'error'] | |||
| ], function (err, ee, event, args) { | |||
| // listener invoked | |||
| }) | |||
| // cancel and clean up | |||
| thunk.cancel() | |||
| ``` | |||
| [npm-image]: https://img.shields.io/npm/v/ee-first.svg?style=flat-square | |||
| [npm-url]: https://npmjs.org/package/ee-first | |||
| [github-tag]: http://img.shields.io/github/tag/jonathanong/ee-first.svg?style=flat-square | |||
| [github-url]: https://github.com/jonathanong/ee-first/tags | |||
| [travis-image]: https://img.shields.io/travis/jonathanong/ee-first.svg?style=flat-square | |||
| [travis-url]: https://travis-ci.org/jonathanong/ee-first | |||
| [coveralls-image]: https://img.shields.io/coveralls/jonathanong/ee-first.svg?style=flat-square | |||
| [coveralls-url]: https://coveralls.io/r/jonathanong/ee-first?branch=master | |||
| [license-image]: http://img.shields.io/npm/l/ee-first.svg?style=flat-square | |||
| [license-url]: LICENSE.md | |||
| [downloads-image]: http://img.shields.io/npm/dm/ee-first.svg?style=flat-square | |||
| [downloads-url]: https://npmjs.org/package/ee-first | |||
| [gittip-image]: https://img.shields.io/gittip/jonathanong.svg?style=flat-square | |||
| [gittip-url]: https://www.gittip.com/jonathanong/ | |||
| @@ -0,0 +1,95 @@ | |||
| /*! | |||
| * ee-first | |||
| * Copyright(c) 2014 Jonathan Ong | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = first | |||
| /** | |||
| * Get the first event in a set of event emitters and event pairs. | |||
| * | |||
| * @param {array} stuff | |||
| * @param {function} done | |||
| * @public | |||
| */ | |||
| function first(stuff, done) { | |||
| if (!Array.isArray(stuff)) | |||
| throw new TypeError('arg must be an array of [ee, events...] arrays') | |||
| var cleanups = [] | |||
| for (var i = 0; i < stuff.length; i++) { | |||
| var arr = stuff[i] | |||
| if (!Array.isArray(arr) || arr.length < 2) | |||
| throw new TypeError('each array member must be [ee, events...]') | |||
| var ee = arr[0] | |||
| for (var j = 1; j < arr.length; j++) { | |||
| var event = arr[j] | |||
| var fn = listener(event, callback) | |||
| // listen to the event | |||
| ee.on(event, fn) | |||
| // push this listener to the list of cleanups | |||
| cleanups.push({ | |||
| ee: ee, | |||
| event: event, | |||
| fn: fn, | |||
| }) | |||
| } | |||
| } | |||
| function callback() { | |||
| cleanup() | |||
| done.apply(null, arguments) | |||
| } | |||
| function cleanup() { | |||
| var x | |||
| for (var i = 0; i < cleanups.length; i++) { | |||
| x = cleanups[i] | |||
| x.ee.removeListener(x.event, x.fn) | |||
| } | |||
| } | |||
| function thunk(fn) { | |||
| done = fn | |||
| } | |||
| thunk.cancel = cleanup | |||
| return thunk | |||
| } | |||
| /** | |||
| * Create the event listener. | |||
| * @private | |||
| */ | |||
| function listener(event, done) { | |||
| return function onevent(arg1) { | |||
| var args = new Array(arguments.length) | |||
| var ee = this | |||
| var err = event === 'error' | |||
| ? arg1 | |||
| : null | |||
| // copy args to prevent arguments escaping scope | |||
| for (var i = 0; i < args.length; i++) { | |||
| args[i] = arguments[i] | |||
| } | |||
| done(err, ee, event, args) | |||
| } | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "ee-first@1.1.1", | |||
| "/var/www/noelle.codes/node/node_modules/on-finished" | |||
| ] | |||
| ], | |||
| "_from": "ee-first@1.1.1", | |||
| "_id": "ee-first@1.1.1", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/ee-first", | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "1.4.28", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "ee-first", | |||
| "raw": "ee-first@1.1.1", | |||
| "rawSpec": "1.1.1", | |||
| "scope": null, | |||
| "spec": "1.1.1", | |||
| "type": "version" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/on-finished" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | |||
| "_shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", | |||
| "_shrinkwrap": null, | |||
| "_spec": "ee-first@1.1.1", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/on-finished", | |||
| "author": { | |||
| "email": "me@jongleberry.com", | |||
| "name": "Jonathan Ong", | |||
| "url": "http://jongleberry.com" | |||
| }, | |||
| "bugs": { | |||
| "url": "https://github.com/jonathanong/ee-first/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "return the first event in a set of ee/event pairs", | |||
| "devDependencies": { | |||
| "istanbul": "0.3.9", | |||
| "mocha": "2.2.5" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "590c61156b0ae2f4f0255732a158b266bc56b21d", | |||
| "tarball": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" | |||
| }, | |||
| "files": [ | |||
| "LICENSE", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "512e0ce4cc3643f603708f965a97b61b1a9c0441", | |||
| "homepage": "https://github.com/jonathanong/ee-first", | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "jongleberry", | |||
| "email": "jonathanrichardong@gmail.com" | |||
| }, | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "ee-first", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jonathanong/ee-first.git" | |||
| }, | |||
| "scripts": { | |||
| "test": "mocha --reporter spec --bail --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | |||
| }, | |||
| "version": "1.1.1" | |||
| } | |||
| @@ -0,0 +1,14 @@ | |||
| 1.0.2 / 2018-01-21 | |||
| ================== | |||
| * Fix encoding `%` as last character | |||
| 1.0.1 / 2016-06-09 | |||
| ================== | |||
| * Fix encoding unpaired surrogates at start/end of string | |||
| 1.0.0 / 2016-06-08 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,22 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2016 Douglas Christopher Wilson | |||
| 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. | |||
| @@ -0,0 +1,128 @@ | |||
| # encodeurl | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Encode a URL to a percent-encoded form, excluding already-encoded sequences | |||
| ## Installation | |||
| This is a [Node.js](https://nodejs.org/en/) module available through the | |||
| [npm registry](https://www.npmjs.com/). Installation is done using the | |||
| [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | |||
| ```sh | |||
| $ npm install encodeurl | |||
| ``` | |||
| ## API | |||
| ```js | |||
| var encodeUrl = require('encodeurl') | |||
| ``` | |||
| ### encodeUrl(url) | |||
| Encode a URL to a percent-encoded form, excluding already-encoded sequences. | |||
| This function will take an already-encoded URL and encode all the non-URL | |||
| code points (as UTF-8 byte sequences). This function will not encode the | |||
| "%" character unless it is not part of a valid sequence (`%20` will be | |||
| left as-is, but `%foo` will be encoded as `%25foo`). | |||
| This encode is meant to be "safe" and does not throw errors. It will try as | |||
| hard as it can to properly encode the given URL, including replacing any raw, | |||
| unpaired surrogate pairs with the Unicode replacement character prior to | |||
| encoding. | |||
| This function is _similar_ to the intrinsic function `encodeURI`, except it | |||
| will not encode the `%` character if that is part of a valid sequence, will | |||
| not encode `[` and `]` (for IPv6 hostnames) and will replace raw, unpaired | |||
| surrogate pairs with the Unicode replacement character (instead of throwing). | |||
| ## Examples | |||
| ### Encode a URL containing user-controled data | |||
| ```js | |||
| var encodeUrl = require('encodeurl') | |||
| var escapeHtml = require('escape-html') | |||
| http.createServer(function onRequest (req, res) { | |||
| // get encoded form of inbound url | |||
| var url = encodeUrl(req.url) | |||
| // create html message | |||
| var body = '<p>Location ' + escapeHtml(url) + ' not found</p>' | |||
| // send a 404 | |||
| res.statusCode = 404 | |||
| res.setHeader('Content-Type', 'text/html; charset=UTF-8') | |||
| res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) | |||
| res.end(body, 'utf-8') | |||
| }) | |||
| ``` | |||
| ### Encode a URL for use in a header field | |||
| ```js | |||
| var encodeUrl = require('encodeurl') | |||
| var escapeHtml = require('escape-html') | |||
| var url = require('url') | |||
| http.createServer(function onRequest (req, res) { | |||
| // parse inbound url | |||
| var href = url.parse(req) | |||
| // set new host for redirect | |||
| href.host = 'localhost' | |||
| href.protocol = 'https:' | |||
| href.slashes = true | |||
| // create location header | |||
| var location = encodeUrl(url.format(href)) | |||
| // create html message | |||
| var body = '<p>Redirecting to new site: ' + escapeHtml(location) + '</p>' | |||
| // send a 301 | |||
| res.statusCode = 301 | |||
| res.setHeader('Content-Type', 'text/html; charset=UTF-8') | |||
| res.setHeader('Content-Length', String(Buffer.byteLength(body, 'utf-8'))) | |||
| res.setHeader('Location', location) | |||
| res.end(body, 'utf-8') | |||
| }) | |||
| ``` | |||
| ## Testing | |||
| ```sh | |||
| $ npm test | |||
| $ npm run lint | |||
| ``` | |||
| ## References | |||
| - [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax][rfc-3986] | |||
| - [WHATWG URL Living Standard][whatwg-url] | |||
| [rfc-3986]: https://tools.ietf.org/html/rfc3986 | |||
| [whatwg-url]: https://url.spec.whatwg.org/ | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/encodeurl.svg | |||
| [npm-url]: https://npmjs.org/package/encodeurl | |||
| [node-version-image]: https://img.shields.io/node/v/encodeurl.svg | |||
| [node-version-url]: https://nodejs.org/en/download | |||
| [travis-image]: https://img.shields.io/travis/pillarjs/encodeurl.svg | |||
| [travis-url]: https://travis-ci.org/pillarjs/encodeurl | |||
| [coveralls-image]: https://img.shields.io/coveralls/pillarjs/encodeurl.svg | |||
| [coveralls-url]: https://coveralls.io/r/pillarjs/encodeurl?branch=master | |||
| [downloads-image]: https://img.shields.io/npm/dm/encodeurl.svg | |||
| [downloads-url]: https://npmjs.org/package/encodeurl | |||
| @@ -0,0 +1,60 @@ | |||
| /*! | |||
| * encodeurl | |||
| * Copyright(c) 2016 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = encodeUrl | |||
| /** | |||
| * RegExp to match non-URL code points, *after* encoding (i.e. not including "%") | |||
| * and including invalid escape sequences. | |||
| * @private | |||
| */ | |||
| var ENCODE_CHARS_REGEXP = /(?:[^\x21\x25\x26-\x3B\x3D\x3F-\x5B\x5D\x5F\x61-\x7A\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]|$))+/g | |||
| /** | |||
| * RegExp to match unmatched surrogate pair. | |||
| * @private | |||
| */ | |||
| var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g | |||
| /** | |||
| * String to replace unmatched surrogate pair with. | |||
| * @private | |||
| */ | |||
| var UNMATCHED_SURROGATE_PAIR_REPLACE = '$1\uFFFD$2' | |||
| /** | |||
| * Encode a URL to a percent-encoded form, excluding already-encoded sequences. | |||
| * | |||
| * This function will take an already-encoded URL and encode all the non-URL | |||
| * code points. This function will not encode the "%" character unless it is | |||
| * not part of a valid sequence (`%20` will be left as-is, but `%foo` will | |||
| * be encoded as `%25foo`). | |||
| * | |||
| * This encode is meant to be "safe" and does not throw errors. It will try as | |||
| * hard as it can to properly encode the given URL, including replacing any raw, | |||
| * unpaired surrogate pairs with the Unicode replacement character prior to | |||
| * encoding. | |||
| * | |||
| * @param {string} url | |||
| * @return {string} | |||
| * @public | |||
| */ | |||
| function encodeUrl (url) { | |||
| return String(url) | |||
| .replace(UNMATCHED_SURROGATE_PAIR_REGEXP, UNMATCHED_SURROGATE_PAIR_REPLACE) | |||
| .replace(ENCODE_CHARS_REGEXP, encodeURI) | |||
| } | |||
| @@ -0,0 +1,106 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "encodeurl@~1.0.2", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "encodeurl@>=1.0.2 <1.1.0", | |||
| "_id": "encodeurl@1.0.2", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/encodeurl", | |||
| "_nodeVersion": "6.11.1", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/encodeurl-1.0.2.tgz_1516591169672_0.5424360500182956" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "3.10.10", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "encodeurl", | |||
| "raw": "encodeurl@~1.0.2", | |||
| "rawSpec": "~1.0.2", | |||
| "scope": null, | |||
| "spec": ">=1.0.2 <1.1.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express", | |||
| "/finalhandler", | |||
| "/send", | |||
| "/serve-static" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | |||
| "_shasum": "ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59", | |||
| "_shrinkwrap": null, | |||
| "_spec": "encodeurl@~1.0.2", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "bugs": { | |||
| "url": "https://github.com/pillarjs/encodeurl/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "Encode a URL to a percent-encoded form, excluding already-encoded sequences", | |||
| "devDependencies": { | |||
| "eslint": "3.19.0", | |||
| "eslint-config-standard": "10.2.1", | |||
| "eslint-plugin-import": "2.8.0", | |||
| "eslint-plugin-node": "5.2.1", | |||
| "eslint-plugin-promise": "3.6.0", | |||
| "eslint-plugin-standard": "3.0.1", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "2.5.3" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59", | |||
| "tarball": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.8" | |||
| }, | |||
| "files": [ | |||
| "HISTORY.md", | |||
| "LICENSE", | |||
| "README.md", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "1a7301e330bf20fd7c8c173102315e45cd1f5d1e", | |||
| "homepage": "https://github.com/pillarjs/encodeurl#readme", | |||
| "keywords": [ | |||
| "encode", | |||
| "encodeurl", | |||
| "url" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "encodeurl", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/pillarjs/encodeurl.git" | |||
| }, | |||
| "scripts": { | |||
| "lint": "eslint .", | |||
| "test": "mocha --reporter spec --bail --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | |||
| }, | |||
| "version": "1.0.2" | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2012-2013 TJ Holowaychuk | |||
| Copyright (c) 2015 Andreas Lubbe | |||
| Copyright (c) 2015 Tiancheng "Timothy" Gu | |||
| 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. | |||
| @@ -0,0 +1,43 @@ | |||
| # escape-html | |||
| Escape string for use in HTML | |||
| ## Example | |||
| ```js | |||
| var escape = require('escape-html'); | |||
| var html = escape('foo & bar'); | |||
| // -> foo & bar | |||
| ``` | |||
| ## Benchmark | |||
| ``` | |||
| $ npm run-script bench | |||
| > escape-html@1.0.3 bench nodejs-escape-html | |||
| > node benchmark/index.js | |||
| http_parser@1.0 | |||
| node@0.10.33 | |||
| v8@3.14.5.9 | |||
| ares@1.9.0-DEV | |||
| uv@0.10.29 | |||
| zlib@1.2.3 | |||
| modules@11 | |||
| openssl@1.0.1j | |||
| 1 test completed. | |||
| 2 tests completed. | |||
| 3 tests completed. | |||
| no special characters x 19,435,271 ops/sec ±0.85% (187 runs sampled) | |||
| single special character x 6,132,421 ops/sec ±0.67% (194 runs sampled) | |||
| many special characters x 3,175,826 ops/sec ±0.65% (193 runs sampled) | |||
| ``` | |||
| ## License | |||
| MIT | |||
| @@ -0,0 +1,78 @@ | |||
| /*! | |||
| * escape-html | |||
| * Copyright(c) 2012-2013 TJ Holowaychuk | |||
| * Copyright(c) 2015 Andreas Lubbe | |||
| * Copyright(c) 2015 Tiancheng "Timothy" Gu | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict'; | |||
| /** | |||
| * Module variables. | |||
| * @private | |||
| */ | |||
| var matchHtmlRegExp = /["'&<>]/; | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = escapeHtml; | |||
| /** | |||
| * Escape special characters in the given string of html. | |||
| * | |||
| * @param {string} string The string to escape for inserting into HTML | |||
| * @return {string} | |||
| * @public | |||
| */ | |||
| function escapeHtml(string) { | |||
| var str = '' + string; | |||
| var match = matchHtmlRegExp.exec(str); | |||
| if (!match) { | |||
| return str; | |||
| } | |||
| var escape; | |||
| var html = ''; | |||
| var index = 0; | |||
| var lastIndex = 0; | |||
| for (index = match.index; index < str.length; index++) { | |||
| switch (str.charCodeAt(index)) { | |||
| case 34: // " | |||
| escape = '"'; | |||
| break; | |||
| case 38: // & | |||
| escape = '&'; | |||
| break; | |||
| case 39: // ' | |||
| escape = '''; | |||
| break; | |||
| case 60: // < | |||
| escape = '<'; | |||
| break; | |||
| case 62: // > | |||
| escape = '>'; | |||
| break; | |||
| default: | |||
| continue; | |||
| } | |||
| if (lastIndex !== index) { | |||
| html += str.substring(lastIndex, index); | |||
| } | |||
| lastIndex = index + 1; | |||
| html += escape; | |||
| } | |||
| return lastIndex !== index | |||
| ? html + str.substring(lastIndex, index) | |||
| : html; | |||
| } | |||
| @@ -0,0 +1,86 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "escape-html@~1.0.3", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "escape-html@>=1.0.3 <1.1.0", | |||
| "_id": "escape-html@1.0.3", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/escape-html", | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "1.4.28", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "escape-html", | |||
| "raw": "escape-html@~1.0.3", | |||
| "rawSpec": "~1.0.3", | |||
| "scope": null, | |||
| "spec": ">=1.0.3 <1.1.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express", | |||
| "/finalhandler", | |||
| "/send", | |||
| "/serve-static" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | |||
| "_shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", | |||
| "_shrinkwrap": null, | |||
| "_spec": "escape-html@~1.0.3", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "bugs": { | |||
| "url": "https://github.com/component/escape-html/issues" | |||
| }, | |||
| "dependencies": {}, | |||
| "description": "Escape string for use in HTML", | |||
| "devDependencies": { | |||
| "beautify-benchmark": "0.2.4", | |||
| "benchmark": "1.0.0" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "0258eae4d3d0c0974de1c169188ef0051d1d1988", | |||
| "tarball": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" | |||
| }, | |||
| "files": [ | |||
| "LICENSE", | |||
| "Readme.md", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "7ac2ea3977fcac3d4c5be8d2a037812820c65f28", | |||
| "homepage": "https://github.com/component/escape-html", | |||
| "keywords": [ | |||
| "escape", | |||
| "html", | |||
| "utility" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "tjholowaychuk", | |||
| "email": "tj@vision-media.ca" | |||
| }, | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "escape-html", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/component/escape-html.git" | |||
| }, | |||
| "scripts": { | |||
| "bench": "node benchmark/index.js" | |||
| }, | |||
| "version": "1.0.3" | |||
| } | |||
| @@ -0,0 +1,83 @@ | |||
| 1.8.1 / 2017-09-12 | |||
| ================== | |||
| * perf: replace regular expression with substring | |||
| 1.8.0 / 2017-02-18 | |||
| ================== | |||
| * Use SHA1 instead of MD5 for ETag hashing | |||
| - Improves performance for larger entities | |||
| - Works with FIPS 140-2 OpenSSL configuration | |||
| 1.7.0 / 2015-06-08 | |||
| ================== | |||
| * Always include entity length in ETags for hash length extensions | |||
| * Generate non-Stats ETags using MD5 only (no longer CRC32) | |||
| * Improve stat performance by removing hashing | |||
| * Remove base64 padding in ETags to shorten | |||
| * Use MD5 instead of MD4 in weak ETags over 1KB | |||
| 1.6.0 / 2015-05-10 | |||
| ================== | |||
| * Improve support for JXcore | |||
| * Remove requirement of `atime` in the stats object | |||
| * Support "fake" stats objects in environments without `fs` | |||
| 1.5.1 / 2014-11-19 | |||
| ================== | |||
| * deps: crc@3.2.1 | |||
| - Minor fixes | |||
| 1.5.0 / 2014-10-14 | |||
| ================== | |||
| * Improve string performance | |||
| * Slightly improve speed for weak ETags over 1KB | |||
| 1.4.0 / 2014-09-21 | |||
| ================== | |||
| * Support "fake" stats objects | |||
| * Support Node.js 0.6 | |||
| 1.3.1 / 2014-09-14 | |||
| ================== | |||
| * Use the (new and improved) `crc` for crc32 | |||
| 1.3.0 / 2014-08-29 | |||
| ================== | |||
| * Default strings to strong ETags | |||
| * Improve speed for weak ETags over 1KB | |||
| 1.2.1 / 2014-08-29 | |||
| ================== | |||
| * Use the (much faster) `buffer-crc32` for crc32 | |||
| 1.2.0 / 2014-08-24 | |||
| ================== | |||
| * Add support for file stat objects | |||
| 1.1.0 / 2014-08-24 | |||
| ================== | |||
| * Add fast-path for empty entity | |||
| * Add weak ETag generation | |||
| * Shrink size of generated ETags | |||
| 1.0.1 / 2014-08-24 | |||
| ================== | |||
| * Fix behavior of string containing Unicode | |||
| 1.0.0 / 2014-05-18 | |||
| ================== | |||
| * Initial release | |||
| @@ -0,0 +1,22 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2014-2016 Douglas Christopher Wilson | |||
| 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. | |||
| @@ -0,0 +1,159 @@ | |||
| # etag | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Node.js Version][node-version-image]][node-version-url] | |||
| [![Build Status][travis-image]][travis-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| Create simple HTTP ETags | |||
| This module generates HTTP ETags (as defined in RFC 7232) for use in | |||
| HTTP responses. | |||
| ## Installation | |||
| This is a [Node.js](https://nodejs.org/en/) module available through the | |||
| [npm registry](https://www.npmjs.com/). Installation is done using the | |||
| [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | |||
| ```sh | |||
| $ npm install etag | |||
| ``` | |||
| ## API | |||
| <!-- eslint-disable no-unused-vars --> | |||
| ```js | |||
| var etag = require('etag') | |||
| ``` | |||
| ### etag(entity, [options]) | |||
| Generate a strong ETag for the given entity. This should be the complete | |||
| body of the entity. Strings, `Buffer`s, and `fs.Stats` are accepted. By | |||
| default, a strong ETag is generated except for `fs.Stats`, which will | |||
| generate a weak ETag (this can be overwritten by `options.weak`). | |||
| <!-- eslint-disable no-undef --> | |||
| ```js | |||
| res.setHeader('ETag', etag(body)) | |||
| ``` | |||
| #### Options | |||
| `etag` accepts these properties in the options object. | |||
| ##### weak | |||
| Specifies if the generated ETag will include the weak validator mark (that | |||
| is, the leading `W/`). The actual entity tag is the same. The default value | |||
| is `false`, unless the `entity` is `fs.Stats`, in which case it is `true`. | |||
| ## Testing | |||
| ```sh | |||
| $ npm test | |||
| ``` | |||
| ## Benchmark | |||
| ```bash | |||
| $ npm run-script bench | |||
| > etag@1.8.1 bench nodejs-etag | |||
| > node benchmark/index.js | |||
| http_parser@2.7.0 | |||
| node@6.11.1 | |||
| v8@5.1.281.103 | |||
| uv@1.11.0 | |||
| zlib@1.2.11 | |||
| ares@1.10.1-DEV | |||
| icu@58.2 | |||
| modules@48 | |||
| openssl@1.0.2k | |||
| > node benchmark/body0-100b.js | |||
| 100B body | |||
| 4 tests completed. | |||
| buffer - strong x 258,647 ops/sec ±1.07% (180 runs sampled) | |||
| buffer - weak x 263,812 ops/sec ±0.61% (184 runs sampled) | |||
| string - strong x 259,955 ops/sec ±1.19% (185 runs sampled) | |||
| string - weak x 264,356 ops/sec ±1.09% (184 runs sampled) | |||
| > node benchmark/body1-1kb.js | |||
| 1KB body | |||
| 4 tests completed. | |||
| buffer - strong x 189,018 ops/sec ±1.12% (182 runs sampled) | |||
| buffer - weak x 190,586 ops/sec ±0.81% (186 runs sampled) | |||
| string - strong x 144,272 ops/sec ±0.96% (188 runs sampled) | |||
| string - weak x 145,380 ops/sec ±1.43% (187 runs sampled) | |||
| > node benchmark/body2-5kb.js | |||
| 5KB body | |||
| 4 tests completed. | |||
| buffer - strong x 92,435 ops/sec ±0.42% (188 runs sampled) | |||
| buffer - weak x 92,373 ops/sec ±0.58% (189 runs sampled) | |||
| string - strong x 48,850 ops/sec ±0.56% (186 runs sampled) | |||
| string - weak x 49,380 ops/sec ±0.56% (190 runs sampled) | |||
| > node benchmark/body3-10kb.js | |||
| 10KB body | |||
| 4 tests completed. | |||
| buffer - strong x 55,989 ops/sec ±0.93% (188 runs sampled) | |||
| buffer - weak x 56,148 ops/sec ±0.55% (190 runs sampled) | |||
| string - strong x 27,345 ops/sec ±0.43% (188 runs sampled) | |||
| string - weak x 27,496 ops/sec ±0.45% (190 runs sampled) | |||
| > node benchmark/body4-100kb.js | |||
| 100KB body | |||
| 4 tests completed. | |||
| buffer - strong x 7,083 ops/sec ±0.22% (190 runs sampled) | |||
| buffer - weak x 7,115 ops/sec ±0.26% (191 runs sampled) | |||
| string - strong x 3,068 ops/sec ±0.34% (190 runs sampled) | |||
| string - weak x 3,096 ops/sec ±0.35% (190 runs sampled) | |||
| > node benchmark/stats.js | |||
| stat | |||
| 4 tests completed. | |||
| real - strong x 871,642 ops/sec ±0.34% (189 runs sampled) | |||
| real - weak x 867,613 ops/sec ±0.39% (190 runs sampled) | |||
| fake - strong x 401,051 ops/sec ±0.40% (189 runs sampled) | |||
| fake - weak x 400,100 ops/sec ±0.47% (188 runs sampled) | |||
| ``` | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/etag.svg | |||
| [npm-url]: https://npmjs.org/package/etag | |||
| [node-version-image]: https://img.shields.io/node/v/etag.svg | |||
| [node-version-url]: https://nodejs.org/en/download/ | |||
| [travis-image]: https://img.shields.io/travis/jshttp/etag/master.svg | |||
| [travis-url]: https://travis-ci.org/jshttp/etag | |||
| [coveralls-image]: https://img.shields.io/coveralls/jshttp/etag/master.svg | |||
| [coveralls-url]: https://coveralls.io/r/jshttp/etag?branch=master | |||
| [downloads-image]: https://img.shields.io/npm/dm/etag.svg | |||
| [downloads-url]: https://npmjs.org/package/etag | |||
| @@ -0,0 +1,131 @@ | |||
| /*! | |||
| * etag | |||
| * Copyright(c) 2014-2016 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict' | |||
| /** | |||
| * Module exports. | |||
| * @public | |||
| */ | |||
| module.exports = etag | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var crypto = require('crypto') | |||
| var Stats = require('fs').Stats | |||
| /** | |||
| * Module variables. | |||
| * @private | |||
| */ | |||
| var toString = Object.prototype.toString | |||
| /** | |||
| * Generate an entity tag. | |||
| * | |||
| * @param {Buffer|string} entity | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function entitytag (entity) { | |||
| if (entity.length === 0) { | |||
| // fast-path empty | |||
| return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"' | |||
| } | |||
| // compute hash of entity | |||
| var hash = crypto | |||
| .createHash('sha1') | |||
| .update(entity, 'utf8') | |||
| .digest('base64') | |||
| .substring(0, 27) | |||
| // compute length of entity | |||
| var len = typeof entity === 'string' | |||
| ? Buffer.byteLength(entity, 'utf8') | |||
| : entity.length | |||
| return '"' + len.toString(16) + '-' + hash + '"' | |||
| } | |||
| /** | |||
| * Create a simple ETag. | |||
| * | |||
| * @param {string|Buffer|Stats} entity | |||
| * @param {object} [options] | |||
| * @param {boolean} [options.weak] | |||
| * @return {String} | |||
| * @public | |||
| */ | |||
| function etag (entity, options) { | |||
| if (entity == null) { | |||
| throw new TypeError('argument entity is required') | |||
| } | |||
| // support fs.Stats object | |||
| var isStats = isstats(entity) | |||
| var weak = options && typeof options.weak === 'boolean' | |||
| ? options.weak | |||
| : isStats | |||
| // validate argument | |||
| if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) { | |||
| throw new TypeError('argument entity must be string, Buffer, or fs.Stats') | |||
| } | |||
| // generate entity tag | |||
| var tag = isStats | |||
| ? stattag(entity) | |||
| : entitytag(entity) | |||
| return weak | |||
| ? 'W/' + tag | |||
| : tag | |||
| } | |||
| /** | |||
| * Determine if object is a Stats object. | |||
| * | |||
| * @param {object} obj | |||
| * @return {boolean} | |||
| * @api private | |||
| */ | |||
| function isstats (obj) { | |||
| // genuine fs.Stats | |||
| if (typeof Stats === 'function' && obj instanceof Stats) { | |||
| return true | |||
| } | |||
| // quack quack | |||
| return obj && typeof obj === 'object' && | |||
| 'ctime' in obj && toString.call(obj.ctime) === '[object Date]' && | |||
| 'mtime' in obj && toString.call(obj.mtime) === '[object Date]' && | |||
| 'ino' in obj && typeof obj.ino === 'number' && | |||
| 'size' in obj && typeof obj.size === 'number' | |||
| } | |||
| /** | |||
| * Generate a tag for a stat. | |||
| * | |||
| * @param {object} stat | |||
| * @return {string} | |||
| * @private | |||
| */ | |||
| function stattag (stat) { | |||
| var mtime = stat.mtime.getTime().toString(16) | |||
| var size = stat.size.toString(16) | |||
| return '"' + size + '-' + mtime + '"' | |||
| } | |||
| @@ -0,0 +1,114 @@ | |||
| { | |||
| "_args": [ | |||
| [ | |||
| "etag@~1.8.1", | |||
| "/var/www/noelle.codes/node/node_modules/express" | |||
| ] | |||
| ], | |||
| "_from": "etag@>=1.8.1 <1.9.0", | |||
| "_id": "etag@1.8.1", | |||
| "_inCache": true, | |||
| "_installable": true, | |||
| "_location": "/etag", | |||
| "_nodeVersion": "6.11.1", | |||
| "_npmOperationalInternal": { | |||
| "host": "s3://npm-registry-packages", | |||
| "tmp": "tmp/etag-1.8.1.tgz_1505270623443_0.24458415526896715" | |||
| }, | |||
| "_npmUser": { | |||
| "email": "doug@somethingdoug.com", | |||
| "name": "dougwilson" | |||
| }, | |||
| "_npmVersion": "3.10.10", | |||
| "_phantomChildren": {}, | |||
| "_requested": { | |||
| "name": "etag", | |||
| "raw": "etag@~1.8.1", | |||
| "rawSpec": "~1.8.1", | |||
| "scope": null, | |||
| "spec": ">=1.8.1 <1.9.0", | |||
| "type": "range" | |||
| }, | |||
| "_requiredBy": [ | |||
| "/express", | |||
| "/send" | |||
| ], | |||
| "_resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | |||
| "_shasum": "41ae2eeb65efa62268aebfea83ac7d79299b0887", | |||
| "_shrinkwrap": null, | |||
| "_spec": "etag@~1.8.1", | |||
| "_where": "/var/www/noelle.codes/node/node_modules/express", | |||
| "bugs": { | |||
| "url": "https://github.com/jshttp/etag/issues" | |||
| }, | |||
| "contributors": [ | |||
| { | |||
| "name": "Douglas Christopher Wilson", | |||
| "email": "doug@somethingdoug.com" | |||
| }, | |||
| { | |||
| "name": "David Björklund", | |||
| "email": "david.bjorklund@gmail.com" | |||
| } | |||
| ], | |||
| "dependencies": {}, | |||
| "description": "Create simple HTTP ETags", | |||
| "devDependencies": { | |||
| "beautify-benchmark": "0.2.4", | |||
| "benchmark": "2.1.4", | |||
| "eslint": "3.19.0", | |||
| "eslint-config-standard": "10.2.1", | |||
| "eslint-plugin-import": "2.7.0", | |||
| "eslint-plugin-markdown": "1.0.0-beta.6", | |||
| "eslint-plugin-node": "5.1.1", | |||
| "eslint-plugin-promise": "3.5.0", | |||
| "eslint-plugin-standard": "3.0.1", | |||
| "istanbul": "0.4.5", | |||
| "mocha": "1.21.5", | |||
| "safe-buffer": "5.1.1", | |||
| "seedrandom": "2.4.3" | |||
| }, | |||
| "directories": {}, | |||
| "dist": { | |||
| "shasum": "41ae2eeb65efa62268aebfea83ac7d79299b0887", | |||
| "tarball": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" | |||
| }, | |||
| "engines": { | |||
| "node": ">= 0.6" | |||
| }, | |||
| "files": [ | |||
| "HISTORY.md", | |||
| "LICENSE", | |||
| "README.md", | |||
| "index.js" | |||
| ], | |||
| "gitHead": "9b1e3e41df31cda4080833c187120b91a7ce8327", | |||
| "homepage": "https://github.com/jshttp/etag#readme", | |||
| "keywords": [ | |||
| "etag", | |||
| "http", | |||
| "res" | |||
| ], | |||
| "license": "MIT", | |||
| "maintainers": [ | |||
| { | |||
| "name": "dougwilson", | |||
| "email": "doug@somethingdoug.com" | |||
| } | |||
| ], | |||
| "name": "etag", | |||
| "optionalDependencies": {}, | |||
| "readme": "ERROR: No README data found!", | |||
| "repository": { | |||
| "type": "git", | |||
| "url": "git+https://github.com/jshttp/etag.git" | |||
| }, | |||
| "scripts": { | |||
| "bench": "node benchmark/index.js", | |||
| "lint": "eslint --plugin markdown --ext js,md .", | |||
| "test": "mocha --reporter spec --bail --check-leaks test/", | |||
| "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", | |||
| "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" | |||
| }, | |||
| "version": "1.8.1" | |||
| } | |||
| @@ -0,0 +1,24 @@ | |||
| (The MIT License) | |||
| Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca> | |||
| Copyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com> | |||
| Copyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.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. | |||
| @@ -0,0 +1,155 @@ | |||
| [](http://expressjs.com/) | |||
| Fast, unopinionated, minimalist web framework for [node](http://nodejs.org). | |||
| [![NPM Version][npm-image]][npm-url] | |||
| [![NPM Downloads][downloads-image]][downloads-url] | |||
| [![Linux Build][travis-image]][travis-url] | |||
| [![Windows Build][appveyor-image]][appveyor-url] | |||
| [![Test Coverage][coveralls-image]][coveralls-url] | |||
| ```js | |||
| const express = require('express') | |||
| const app = express() | |||
| app.get('/', function (req, res) { | |||
| res.send('Hello World') | |||
| }) | |||
| app.listen(3000) | |||
| ``` | |||
| ## Installation | |||
| This is a [Node.js](https://nodejs.org/en/) module available through the | |||
| [npm registry](https://www.npmjs.com/). | |||
| Before installing, [download and install Node.js](https://nodejs.org/en/download/). | |||
| Node.js 0.10 or higher is required. | |||
| Installation is done using the | |||
| [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): | |||
| ```bash | |||
| $ npm install express | |||
| ``` | |||
| Follow [our installing guide](http://expressjs.com/en/starter/installing.html) | |||
| for more information. | |||
| ## Features | |||
| * Robust routing | |||
| * Focus on high performance | |||
| * Super-high test coverage | |||
| * HTTP helpers (redirection, caching, etc) | |||
| * View system supporting 14+ template engines | |||
| * Content negotiation | |||
| * Executable for generating applications quickly | |||
| ## Docs & Community | |||
| * [Website and Documentation](http://expressjs.com/) - [[website repo](https://github.com/expressjs/expressjs.com)] | |||
| * [#express](https://webchat.freenode.net/?channels=express) on freenode IRC | |||
| * [GitHub Organization](https://github.com/expressjs) for Official Middleware & Modules | |||
| * Visit the [Wiki](https://github.com/expressjs/express/wiki) | |||
| * [Google Group](https://groups.google.com/group/express-js) for discussion | |||
| * [Gitter](https://gitter.im/expressjs/express) for support and discussion | |||
| **PROTIP** Be sure to read [Migrating from 3.x to 4.x](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x) as well as [New features in 4.x](https://github.com/expressjs/express/wiki/New-features-in-4.x). | |||
| ### Security Issues | |||
| If you discover a security vulnerability in Express, please see [Security Policies and Procedures](Security.md). | |||
| ## Quick Start | |||
| The quickest way to get started with express is to utilize the executable [`express(1)`](https://github.com/expressjs/generator) to generate an application as shown below: | |||
| Install the executable. The executable's major version will match Express's: | |||
| ```bash | |||
| $ npm install -g express-generator@4 | |||
| ``` | |||
| Create the app: | |||
| ```bash | |||
| $ express /tmp/foo && cd /tmp/foo | |||
| ``` | |||
| Install dependencies: | |||
| ```bash | |||
| $ npm install | |||
| ``` | |||
| Start the server: | |||
| ```bash | |||
| $ npm start | |||
| ``` | |||
| View the website at: http://localhost:3000 | |||
| ## Philosophy | |||
| The Express philosophy is to provide small, robust tooling for HTTP servers, making | |||
| it a great solution for single page applications, web sites, hybrids, or public | |||
| HTTP APIs. | |||
| Express does not force you to use any specific ORM or template engine. With support for over | |||
| 14 template engines via [Consolidate.js](https://github.com/tj/consolidate.js), | |||
| you can quickly craft your perfect framework. | |||
| ## Examples | |||
| To view the examples, clone the Express repo and install the dependencies: | |||
| ```bash | |||
| $ git clone git://github.com/expressjs/express.git --depth 1 | |||
| $ cd express | |||
| $ npm install | |||
| ``` | |||
| Then run whichever example you want: | |||
| ```bash | |||
| $ node examples/content-negotiation | |||
| ``` | |||
| ## Tests | |||
| To run the test suite, first install the dependencies, then run `npm test`: | |||
| ```bash | |||
| $ npm install | |||
| $ npm test | |||
| ``` | |||
| ## Contributing | |||
| [Contributing Guide](Contributing.md) | |||
| ## People | |||
| The original author of Express is [TJ Holowaychuk](https://github.com/tj) | |||
| The current lead maintainer is [Douglas Christopher Wilson](https://github.com/dougwilson) | |||
| [List of all contributors](https://github.com/expressjs/express/graphs/contributors) | |||
| ## License | |||
| [MIT](LICENSE) | |||
| [npm-image]: https://img.shields.io/npm/v/express.svg | |||
| [npm-url]: https://npmjs.org/package/express | |||
| [downloads-image]: https://img.shields.io/npm/dm/express.svg | |||
| [downloads-url]: https://npmjs.org/package/express | |||
| [travis-image]: https://img.shields.io/travis/expressjs/express/master.svg?label=linux | |||
| [travis-url]: https://travis-ci.org/expressjs/express | |||
| [appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/express/master.svg?label=windows | |||
| [appveyor-url]: https://ci.appveyor.com/project/dougwilson/express | |||
| [coveralls-image]: https://img.shields.io/coveralls/expressjs/express/master.svg | |||
| [coveralls-url]: https://coveralls.io/r/expressjs/express?branch=master | |||
| @@ -0,0 +1,11 @@ | |||
| /*! | |||
| * express | |||
| * Copyright(c) 2009-2013 TJ Holowaychuk | |||
| * Copyright(c) 2013 Roman Shtylman | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict'; | |||
| module.exports = require('./lib/express'); | |||
| @@ -0,0 +1,644 @@ | |||
| /*! | |||
| * express | |||
| * Copyright(c) 2009-2013 TJ Holowaychuk | |||
| * Copyright(c) 2013 Roman Shtylman | |||
| * Copyright(c) 2014-2015 Douglas Christopher Wilson | |||
| * MIT Licensed | |||
| */ | |||
| 'use strict'; | |||
| /** | |||
| * Module dependencies. | |||
| * @private | |||
| */ | |||
| var finalhandler = require('finalhandler'); | |||
| var Router = require('./router'); | |||
| var methods = require('methods'); | |||
| var middleware = require('./middleware/init'); | |||
| var query = require('./middleware/query'); | |||
| var debug = require('debug')('express:application'); | |||
| var View = require('./view'); | |||
| var http = require('http'); | |||
| var compileETag = require('./utils').compileETag; | |||
| var compileQueryParser = require('./utils').compileQueryParser; | |||
| var compileTrust = require('./utils').compileTrust; | |||
| var deprecate = require('depd')('express'); | |||
| var flatten = require('array-flatten'); | |||
| var merge = require('utils-merge'); | |||
| var resolve = require('path').resolve; | |||
| var setPrototypeOf = require('setprototypeof') | |||
| var slice = Array.prototype.slice; | |||
| /** | |||
| * Application prototype. | |||
| */ | |||
| var app = exports = module.exports = {}; | |||
| /** | |||
| * Variable for trust proxy inheritance back-compat | |||
| * @private | |||
| */ | |||
| var trustProxyDefaultSymbol = '@@symbol:trust_proxy_default'; | |||
| /** | |||
| * Initialize the server. | |||
| * | |||
| * - setup default configuration | |||
| * - setup default middleware | |||
| * - setup route reflection methods | |||
| * | |||
| * @private | |||
| */ | |||
| app.init = function init() { | |||
| this.cache = {}; | |||
| this.engines = {}; | |||
| this.settings = {}; | |||
| this.defaultConfiguration(); | |||
| }; | |||
| /** | |||
| * Initialize application configuration. | |||
| * @private | |||
| */ | |||
| app.defaultConfiguration = function defaultConfiguration() { | |||
| var env = process.env.NODE_ENV || 'development'; | |||
| // default settings | |||
| this.enable('x-powered-by'); | |||
| this.set('etag', 'weak'); | |||
| this.set('env', env); | |||
| this.set('query parser', 'extended'); | |||
| this.set('subdomain offset', 2); | |||
| this.set('trust proxy', false); | |||
| // trust proxy inherit back-compat | |||
| Object.defineProperty(this.settings, trustProxyDefaultSymbol, { | |||
| configurable: true, | |||
| value: true | |||
| }); | |||
| debug('booting in %s mode', env); | |||
| this.on('mount', function onmount(parent) { | |||
| // inherit trust proxy | |||
| if (this.settings[trustProxyDefaultSymbol] === true | |||
| && typeof parent.settings['trust proxy fn'] === 'function') { | |||
| delete this.settings['trust proxy']; | |||
| delete this.settings['trust proxy fn']; | |||
| } | |||
| // inherit protos | |||
| setPrototypeOf(this.request, parent.request) | |||
| setPrototypeOf(this.response, parent.response) | |||
| setPrototypeOf(this.engines, parent.engines) | |||
| setPrototypeOf(this.settings, parent.settings) | |||
| }); | |||
| // setup locals | |||
| this.locals = Object.create(null); | |||
| // top-most app is mounted at / | |||
| this.mountpath = '/'; | |||
| // default locals | |||
| this.locals.settings = this.settings; | |||
| // default configuration | |||
| this.set('view', View); | |||
| this.set('views', resolve('views')); | |||
| this.set('jsonp callback name', 'callback'); | |||
| if (env === 'production') { | |||
| this.enable('view cache'); | |||
| } | |||
| Object.defineProperty(this, 'router', { | |||
| get: function() { | |||
| throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.'); | |||
| } | |||
| }); | |||
| }; | |||
| /** | |||
| * lazily adds the base router if it has not yet been added. | |||
| * | |||
| * We cannot add the base router in the defaultConfiguration because | |||
| * it reads app settings which might be set after that has run. | |||
| * | |||
| * @private | |||
| */ | |||
| app.lazyrouter = function lazyrouter() { | |||
| if (!this._router) { | |||
| this._router = new Router({ | |||
| caseSensitive: this.enabled('case sensitive routing'), | |||
| strict: this.enabled('strict routing') | |||
| }); | |||
| this._router.use(query(this.get('query parser fn'))); | |||
| this._router.use(middleware.init(this)); | |||
| } | |||
| }; | |||
| /** | |||
| * Dispatch a req, res pair into the application. Starts pipeline processing. | |||
| * | |||
| * If no callback is provided, then default error handlers will respond | |||
| * in the event of an error bubbling through the stack. | |||
| * | |||
| * @private | |||
| */ | |||
| app.handle = function handle(req, res, callback) { | |||
| var router = this._router; | |||
| // final handler | |||
| var done = callback || finalhandler(req, res, { | |||
| env: this.get('env'), | |||
| onerror: logerror.bind(this) | |||
| }); | |||
| // no routes | |||
| if (!router) { | |||
| debug('no routes defined on app'); | |||
| done(); | |||
| return; | |||
| } | |||
| router.handle(req, res, done); | |||
| }; | |||
| /** | |||
| * Proxy `Router#use()` to add middleware to the app router. | |||
| * See Router#use() documentation for details. | |||
| * | |||
| * If the _fn_ parameter is an express app, then it will be | |||
| * mounted at the _route_ specified. | |||
| * | |||
| * @public | |||
| */ | |||
| app.use = function use(fn) { | |||
| var offset = 0; | |||
| var path = '/'; | |||
| // default path to '/' | |||
| // disambiguate app.use([fn]) | |||
| if (typeof fn !== 'function') { | |||
| var arg = fn; | |||
| while (Array.isArray(arg) && arg.length !== 0) { | |||
| arg = arg[0]; | |||
| } | |||
| // first arg is the path | |||
| if (typeof arg !== 'function') { | |||
| offset = 1; | |||
| path = fn; | |||
| } | |||
| } | |||
| var fns = flatten(slice.call(arguments, offset)); | |||
| if (fns.length === 0) { | |||
| throw new TypeError('app.use() requires a middleware function') | |||
| } | |||
| // setup router | |||
| this.lazyrouter(); | |||
| var router = this._router; | |||
| fns.forEach(function (fn) { | |||
| // non-express app | |||
| if (!fn || !fn.handle || !fn.set) { | |||
| return router.use(path, fn); | |||
| } | |||
| debug('.use app under %s', path); | |||
| fn.mountpath = path; | |||
| fn.parent = this; | |||
| // restore .app property on req and res | |||
| router.use(path, function mounted_app(req, res, next) { | |||
| var orig = req.app; | |||
| fn.handle(req, res, function (err) { | |||
| setPrototypeOf(req, orig.request) | |||
| setPrototypeOf(res, orig.response) | |||
| next(err); | |||
| }); | |||
| }); | |||
| // mounted an app | |||
| fn.emit('mount', this); | |||
| }, this); | |||
| return this; | |||
| }; | |||
| /** | |||
| * Proxy to the app `Router#route()` | |||
| * Returns a new `Route` instance for the _path_. | |||
| * | |||
| * Routes are isolated middleware stacks for specific paths. | |||
| * See the Route api docs for details. | |||
| * | |||
| * @public | |||
| */ | |||
| app.route = function route(path) { | |||
| this.lazyrouter(); | |||
| return this._router.route(path); | |||
| }; | |||
| /** | |||
| * Register the given template engine callback `fn` | |||
| * as `ext`. | |||
| * | |||
| * By default will `require()` the engine based on the | |||
| * file extension. For example if you try to render | |||
| * a "foo.ejs" file Express will invoke the following internally: | |||
| * | |||
| * app.engine('ejs', require('ejs').__express); | |||
| * | |||
| * For engines that do not provide `.__express` out of the box, | |||
| * or if you wish to "map" a different extension to the template engine | |||
| * you may use this method. For example mapping the EJS template engine to | |||
| * ".html" files: | |||
| * | |||
| * app.engine('html', require('ejs').renderFile); | |||
| * | |||
| * In this case EJS provides a `.renderFile()` method with | |||
| * the same signature that Express expects: `(path, options, callback)`, | |||
| * though note that it aliases this method as `ejs.__express` internally | |||
| * so if you're using ".ejs" extensions you dont need to do anything. | |||
| * | |||
| * Some template engines do not follow this convention, the | |||
| * [Consolidate.js](https://github.com/tj/consolidate.js) | |||
| * library was created to map all of node's popular template | |||
| * engines to follow this convention, thus allowing them to | |||
| * work seamlessly within Express. | |||
| * | |||
| * @param {String} ext | |||
| * @param {Function} fn | |||
| * @return {app} for chaining | |||
| * @public | |||
| */ | |||
| app.engine = function engine(ext, fn) { | |||
| if (typeof fn !== 'function') { | |||
| throw new Error('callback function required'); | |||
| } | |||
| // get file extension | |||
| var extension = ext[0] !== '.' | |||
| ? '.' + ext | |||
| : ext; | |||
| // store engine | |||
| this.engines[extension] = fn; | |||
| return this; | |||
| }; | |||
| /** | |||
| * Proxy to `Router#param()` with one added api feature. The _name_ parameter | |||
| * can be an array of names. | |||
| * | |||
| * See the Router#param() docs for more details. | |||
| * | |||
| * @param {String|Array} name | |||
| * @param {Function} fn | |||
| * @return {app} for chaining | |||
| * @public | |||
| */ | |||
| app.param = function param(name, fn) { | |||
| this.lazyrouter(); | |||
| if (Array.isArray(name)) { | |||
| for (var i = 0; i < name.length; i++) { | |||
| this.param(name[i], fn); | |||
| } | |||
| return this; | |||
| } | |||
| this._router.param(name, fn); | |||
| return this; | |||
| }; | |||
| /** | |||
| * Assign `setting` to `val`, or return `setting`'s value. | |||
| * | |||
| * app.set('foo', 'bar'); | |||
| * app.set('foo'); | |||
| * // => "bar" | |||
| * | |||
| * Mounted servers inherit their parent server's settings. | |||
| * | |||
| * @param {String} setting | |||
| * @param {*} [val] | |||
| * @return {Server} for chaining | |||
| * @public | |||
| */ | |||
| app.set = function set(setting, val) { | |||
| if (arguments.length === 1) { | |||
| // app.get(setting) | |||
| return this.settings[setting]; | |||
| } | |||
| debug('set "%s" to %o', setting, val); | |||
| // set value | |||
| this.settings[setting] = val; | |||
| // trigger matched settings | |||
| switch (setting) { | |||
| case 'etag': | |||
| this.set('etag fn', compileETag(val)); | |||
| break; | |||
| case 'query parser': | |||
| this.set('query parser fn', compileQueryParser(val)); | |||
| break; | |||
| case 'trust proxy': | |||
| this.set('trust proxy fn', compileTrust(val)); | |||
| // trust proxy inherit back-compat | |||
| Object.defineProperty(this.settings, trustProxyDefaultSymbol, { | |||
| configurable: true, | |||
| value: false | |||
| }); | |||
| break; | |||
| } | |||
| return this; | |||
| }; | |||
| /** | |||
| * Return the app's absolute pathname | |||
| * based on the parent(s) that have | |||
| * mounted it. | |||
| * | |||
| * For example if the application was | |||
| * mounted as "/admin", which itself | |||
| * was mounted as "/blog" then the | |||
| * return value would be "/blog/admin". | |||
| * | |||
| * @return {String} | |||
| * @private | |||
| */ | |||
| app.path = function path() { | |||
| return this.parent | |||
| ? this.parent.path() + this.mountpath | |||
| : ''; | |||
| }; | |||
| /** | |||
| * Check if `setting` is enabled (truthy). | |||
| * | |||
| * app.enabled('foo') | |||
| * // => false | |||
| * | |||
| * app.enable('foo') | |||
| * app.enabled('foo') | |||
| * // => true | |||
| * | |||
| * @param {String} setting | |||
| * @return {Boolean} | |||
| * @public | |||
| */ | |||
| app.enabled = function enabled(setting) { | |||
| return Boolean(this.set(setting)); | |||
| }; | |||
| /** | |||
| * Check if `setting` is disabled. | |||
| * | |||
| * app.disabled('foo') | |||
| * // => true | |||
| * | |||
| * app.enable('foo') | |||
| * app.disabled('foo') | |||
| * // => false | |||
| * | |||
| * @param {String} setting | |||
| * @return {Boolean} | |||
| * @public | |||
| */ | |||
| app.disabled = function disabled(setting) { | |||
| return !this.set(setting); | |||
| }; | |||
| /** | |||
| * Enable `setting`. | |||
| * | |||
| * @param {String} setting | |||
| * @return {app} for chaining | |||
| * @public | |||
| */ | |||
| app.enable = function enable(setting) { | |||
| return this.set(setting, true); | |||
| }; | |||
| /** | |||
| * Disable `setting`. | |||
| * | |||
| * @param {String} setting | |||
| * @return {app} for chaining | |||
| * @public | |||
| */ | |||
| app.disable = function disable(setting) { | |||
| return this.set(setting, false); | |||
| }; | |||
| /** | |||
| * Delegate `.VERB(...)` calls to `router.VERB(...)`. | |||
| */ | |||
| methods.forEach(function(method){ | |||
| app[method] = function(path){ | |||
| if (method === 'get' && arguments.length === 1) { | |||
| // app.get(setting) | |||
| return this.set(path); | |||
| } | |||
| this.lazyrouter(); | |||
| var route = this._router.route(path); | |||
| route[method].apply(route, slice.call(arguments, 1)); | |||
| return this; | |||
| }; | |||
| }); | |||
| /** | |||
| * Special-cased "all" method, applying the given route `path`, | |||
| * middleware, and callback to _every_ HTTP method. | |||
| * | |||
| * @param {String} path | |||
| * @param {Function} ... | |||
| * @return {app} for chaining | |||
| * @public | |||
| */ | |||
| app.all = function all(path) { | |||
| this.lazyrouter(); | |||
| var route = this._router.route(path); | |||
| var args = slice.call(arguments, 1); | |||
| for (var i = 0; i < methods.length; i++) { | |||
| route[methods[i]].apply(route, args); | |||
| } | |||
| return this; | |||
| }; | |||
| // del -> delete alias | |||
| app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead'); | |||
| /** | |||
| * Render the given view `name` name with `options` | |||
| * and a callback accepting an error and the | |||
| * rendered template string. | |||
| * | |||
| * Example: | |||
| * | |||
| * app.render('email', { name: 'Tobi' }, function(err, html){ | |||
| * // ... | |||
| * }) | |||
| * | |||
| * @param {String} name | |||
| * @param {Object|Function} options or fn | |||
| * @param {Function} callback | |||
| * @public | |||
| */ | |||
| app.render = function render(name, options, callback) { | |||
| var cache = this.cache; | |||
| var done = callback; | |||
| var engines = this.engines; | |||
| var opts = options; | |||
| var renderOptions = {}; | |||
| var view; | |||
| // support callback function as second arg | |||
| if (typeof options === 'function') { | |||
| done = options; | |||
| opts = {}; | |||
| } | |||
| // merge app.locals | |||
| merge(renderOptions, this.locals); | |||
| // merge options._locals | |||
| if (opts._locals) { | |||
| merge(renderOptions, opts._locals); | |||
| } | |||
| // merge options | |||
| merge(renderOptions, opts); | |||
| // set .cache unless explicitly provided | |||
| if (renderOptions.cache == null) { | |||
| renderOptions.cache = this.enabled('view cache'); | |||
| } | |||
| // primed cache | |||
| if (renderOptions.cache) { | |||
| view = cache[name]; | |||
| } | |||
| // view | |||
| if (!view) { | |||
| var View = this.get('view'); | |||
| view = new View(name, { | |||
| defaultEngine: this.get('view engine'), | |||
| root: this.get('views'), | |||
| engines: engines | |||
| }); | |||
| if (!view.path) { | |||
| var dirs = Array.isArray(view.root) && view.root.length > 1 | |||
| ? 'directories "' + view.root.slice(0, -1).join('", "') + '" or "' + view.root[view.root.length - 1] + '"' | |||
| : 'directory "' + view.root + '"' | |||
| var err = new Error('Failed to lookup view "' + name + '" in views ' + dirs); | |||
| err.view = view; | |||
| return done(err); | |||
| } | |||
| // prime the cache | |||
| if (renderOptions.cache) { | |||
| cache[name] = view; | |||
| } | |||
| } | |||
| // render | |||
| tryRender(view, renderOptions, done); | |||
| }; | |||
| /** | |||
| * Listen for connections. | |||
| * | |||
| * A node `http.Server` is returned, with this | |||
| * application (which is a `Function`) as its | |||
| * callback. If you wish to create both an HTTP | |||
| * and HTTPS server you may do so with the "http" | |||
| * and "https" modules as shown here: | |||
| * | |||
| * var http = require('http') | |||
| * , https = require('https') | |||
| * , express = require('express') | |||
| * , app = express(); | |||
| * | |||
| * http.createServer(app).listen(80); | |||
| * https.createServer({ ... }, app).listen(443); | |||
| * | |||
| * @return {http.Server} | |||
| * @public | |||
| */ | |||
| app.listen = function listen() { | |||
| var server = http.createServer(this); | |||
| return server.listen.apply(server, arguments); | |||
| }; | |||
| /** | |||
| * Log error using console.error. | |||
| * | |||
| * @param {Error} err | |||
| * @private | |||
| */ | |||
| function logerror(err) { | |||
| /* istanbul ignore next */ | |||
| if (this.get('env') !== 'test') console.error(err.stack || err.toString()); | |||
| } | |||
| /** | |||
| * Try rendering a view. | |||
| * @private | |||
| */ | |||
| function tryRender(view, options, callback) { | |||
| try { | |||
| view.render(options, callback); | |||
| } catch (err) { | |||
| callback(err); | |||
| } | |||
| } | |||