backup everything to local gitea
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
@@ -1,15 +0,0 @@
|
||||
FROM node:20
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
|
||||
COPY --chown=node:node . .
|
||||
|
||||
RUN npm ci
|
||||
|
||||
ENV DEBUG=express:*
|
||||
|
||||
|
||||
USER node
|
||||
|
||||
CMD npm start
|
||||
@@ -1,19 +0,0 @@
|
||||
# Express application
|
||||
|
||||
Install dependencies with `npm install`
|
||||
|
||||
Run with `npm start`
|
||||
|
||||
Or in development mode with `npm run dev`
|
||||
|
||||
# Visit counter
|
||||
|
||||
When running the server, visit http://localhost:3000 to see visit counter, or give environment variable `PORT` to change the port.
|
||||
|
||||
# MongoDB
|
||||
|
||||
The application has /todos crud which requires a MongoDB. Pass connection url with env `MONGO_URL`
|
||||
|
||||
# Redis
|
||||
|
||||
Pass connection url with env `REDIS_URL`
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var app = require('../app');
|
||||
var debug = require('debug')('todo-express-backend:server');
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
services:
|
||||
app: # The name of the service, can be anything
|
||||
image: todo-backend # Declares which image to use
|
||||
build: . # Declares where to build if image is not found
|
||||
ports: # Declares the ports to publish
|
||||
- 3000:3000
|
||||
@@ -1,10 +0,0 @@
|
||||
const mongoose = require('mongoose')
|
||||
const Todo = require('./models/Todo')
|
||||
const { MONGO_URL } = require('../util/config')
|
||||
|
||||
if (MONGO_URL && !mongoose.connection.readyState) mongoose.connect(MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||
|
||||
|
||||
module.exports = {
|
||||
Todo
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const todoSchema = new mongoose.Schema({
|
||||
text: String,
|
||||
done: Boolean
|
||||
})
|
||||
|
||||
module.exports = mongoose.model('Todo', todoSchema)
|
||||
@@ -1,15 +0,0 @@
|
||||
db.createUser({
|
||||
user: 'the_username',
|
||||
pwd: 'the_password',
|
||||
roles: [
|
||||
{
|
||||
role: 'dbOwner',
|
||||
db: 'the_database',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
db.createCollection('todos');
|
||||
|
||||
db.todos.insert({ text: 'Write code', done: true });
|
||||
db.todos.insert({ text: 'Learn about containers', done: false });
|
||||
@@ -1,2 +0,0 @@
|
||||
WiredTiger
|
||||
WiredTiger 11.2.0: (November 10, 2022)
|
||||
@@ -1 +0,0 @@
|
||||
WiredTiger lock file
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../is-ci/bin.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../mime/cli.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../nodemon/bin/nodemon.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../touch/bin/nodetouch.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../nopt/bin/nopt.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../rc/cli.js
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../semver/bin/semver
|
||||
Generated
Vendored
-29
@@ -4,21 +4,6 @@
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "todo-express-backend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"debug": "~2.6.9",
|
||||
"express": "~4.16.1",
|
||||
"mongoose": "^5.13.2",
|
||||
"morgan": "~1.9.1",
|
||||
"redis": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
|
||||
@@ -708,20 +693,6 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
Generated
Vendored
Executable
+1
@@ -0,0 +1 @@
|
||||
repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
|
||||
Generated
Vendored
Executable
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"no-empty": [1, { "allowEmptyCatch": true }]
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
||||
Generated
Vendored
Executable
+9
@@ -0,0 +1,9 @@
|
||||
support
|
||||
test
|
||||
examples
|
||||
example
|
||||
*.sock
|
||||
dist
|
||||
yarn.lock
|
||||
coverage
|
||||
bower.json
|
||||
Generated
Vendored
Executable
+14
@@ -0,0 +1,14 @@
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "6"
|
||||
- "5"
|
||||
- "4"
|
||||
|
||||
install:
|
||||
- make node_modules
|
||||
|
||||
script:
|
||||
- make lint
|
||||
- make test
|
||||
- make coveralls
|
||||
Generated
Vendored
Executable
+362
@@ -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
|
||||
Generated
Vendored
Executable
+19
@@ -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.
|
||||
|
||||
Generated
Vendored
Executable
+50
@@ -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
|
||||
Generated
Vendored
Executable
+312
@@ -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.
|
||||
Generated
Vendored
Executable
+19
@@ -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"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+70
@@ -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
|
||||
})
|
||||
}
|
||||
Generated
Vendored
Executable
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./src/node');
|
||||
Generated
Vendored
Executable
+152
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
var s = 1000;
|
||||
var m = s * 60;
|
||||
var h = m * 60;
|
||||
var d = h * 24;
|
||||
var y = d * 365.25;
|
||||
|
||||
/**
|
||||
* Parse or format the given `val`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `long` verbose formatting [false]
|
||||
*
|
||||
* @param {String|Number} val
|
||||
* @param {Object} [options]
|
||||
* @throws {Error} throw an error if val is not a non-empty string or a number
|
||||
* @return {String|Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports = function(val, options) {
|
||||
options = options || {};
|
||||
var type = typeof val;
|
||||
if (type === 'string' && val.length > 0) {
|
||||
return parse(val);
|
||||
} else if (type === 'number' && isNaN(val) === false) {
|
||||
return options.long ? fmtLong(val) : fmtShort(val);
|
||||
}
|
||||
throw new Error(
|
||||
'val is not a non-empty string or a valid number. val=' +
|
||||
JSON.stringify(val)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the given `str` and return milliseconds.
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse(str) {
|
||||
str = String(str);
|
||||
if (str.length > 100) {
|
||||
return;
|
||||
}
|
||||
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
|
||||
str
|
||||
);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
var n = parseFloat(match[1]);
|
||||
var type = (match[2] || 'ms').toLowerCase();
|
||||
switch (type) {
|
||||
case 'years':
|
||||
case 'year':
|
||||
case 'yrs':
|
||||
case 'yr':
|
||||
case 'y':
|
||||
return n * y;
|
||||
case 'days':
|
||||
case 'day':
|
||||
case 'd':
|
||||
return n * d;
|
||||
case 'hours':
|
||||
case 'hour':
|
||||
case 'hrs':
|
||||
case 'hr':
|
||||
case 'h':
|
||||
return n * h;
|
||||
case 'minutes':
|
||||
case 'minute':
|
||||
case 'mins':
|
||||
case 'min':
|
||||
case 'm':
|
||||
return n * m;
|
||||
case 'seconds':
|
||||
case 'second':
|
||||
case 'secs':
|
||||
case 'sec':
|
||||
case 's':
|
||||
return n * s;
|
||||
case 'milliseconds':
|
||||
case 'millisecond':
|
||||
case 'msecs':
|
||||
case 'msec':
|
||||
case 'ms':
|
||||
return n;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Short format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtShort(ms) {
|
||||
if (ms >= d) {
|
||||
return Math.round(ms / d) + 'd';
|
||||
}
|
||||
if (ms >= h) {
|
||||
return Math.round(ms / h) + 'h';
|
||||
}
|
||||
if (ms >= m) {
|
||||
return Math.round(ms / m) + 'm';
|
||||
}
|
||||
if (ms >= s) {
|
||||
return Math.round(ms / s) + 's';
|
||||
}
|
||||
return ms + 'ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Long format for `ms`.
|
||||
*
|
||||
* @param {Number} ms
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function fmtLong(ms) {
|
||||
return plural(ms, d, 'day') ||
|
||||
plural(ms, h, 'hour') ||
|
||||
plural(ms, m, 'minute') ||
|
||||
plural(ms, s, 'second') ||
|
||||
ms + ' ms';
|
||||
}
|
||||
|
||||
/**
|
||||
* Pluralization helper.
|
||||
*/
|
||||
|
||||
function plural(ms, n, name) {
|
||||
if (ms < n) {
|
||||
return;
|
||||
}
|
||||
if (ms < n * 1.5) {
|
||||
return Math.floor(ms / n) + ' ' + name;
|
||||
}
|
||||
return Math.ceil(ms / n) + ' ' + name + 's';
|
||||
}
|
||||
Generated
Vendored
Executable
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Zeit, Inc.
|
||||
|
||||
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.
|
||||
Generated
Vendored
Executable
+37
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "ms",
|
||||
"version": "2.0.0",
|
||||
"description": "Tiny milisecond conversion utility",
|
||||
"repository": "zeit/ms",
|
||||
"main": "./index",
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"lint": "eslint lib/* bin/*",
|
||||
"test": "mocha tests.js"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"npm run lint",
|
||||
"prettier --single-quote --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"eslint": "3.19.0",
|
||||
"expect.js": "0.3.1",
|
||||
"husky": "0.13.3",
|
||||
"lint-staged": "3.4.1",
|
||||
"mocha": "3.4.1"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+51
@@ -0,0 +1,51 @@
|
||||
# ms
|
||||
|
||||
[](https://travis-ci.org/zeit/ms)
|
||||
[](https://zeit.chat/)
|
||||
|
||||
Use this package to easily convert various time formats to milliseconds.
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
ms('2 days') // 172800000
|
||||
ms('1d') // 86400000
|
||||
ms('10h') // 36000000
|
||||
ms('2.5 hrs') // 9000000
|
||||
ms('2h') // 7200000
|
||||
ms('1m') // 60000
|
||||
ms('5s') // 5000
|
||||
ms('1y') // 31557600000
|
||||
ms('100') // 100
|
||||
```
|
||||
|
||||
### Convert from milliseconds
|
||||
|
||||
```js
|
||||
ms(60000) // "1m"
|
||||
ms(2 * 60000) // "2m"
|
||||
ms(ms('10 hours')) // "10h"
|
||||
```
|
||||
|
||||
### Time format written-out
|
||||
|
||||
```js
|
||||
ms(60000, { long: true }) // "1 minute"
|
||||
ms(2 * 60000, { long: true }) // "2 minutes"
|
||||
ms(ms('10 hours'), { long: true }) // "10 hours"
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Works both in [node](https://nodejs.org) and in the browser.
|
||||
- If a number is supplied to `ms`, a string with a unit is returned.
|
||||
- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
|
||||
- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
|
||||
|
||||
## Caught a bug?
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
|
||||
2. Link the package to the global module directory: `npm link`
|
||||
3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
|
||||
|
||||
As always, you can run the tests using: `npm test`
|
||||
Generated
Vendored
Executable
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "debug",
|
||||
"version": "2.6.9",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/visionmedia/debug.git"
|
||||
},
|
||||
"description": "small debugging utility",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"log",
|
||||
"debugger"
|
||||
],
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
|
||||
"Andrew Rhyne <rhyneandrew@gmail.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"main": "./src/index.js",
|
||||
"browser": "./src/browser.js",
|
||||
"component": {
|
||||
"scripts": {
|
||||
"debug/index.js": "browser.js",
|
||||
"debug/debug.js": "debug.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+185
@@ -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) {}
|
||||
}
|
||||
Generated
Vendored
Executable
+202
@@ -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;
|
||||
}
|
||||
Generated
Vendored
Executable
+10
@@ -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');
|
||||
}
|
||||
Generated
Vendored
Executable
+15
@@ -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;
|
||||
}
|
||||
Generated
Vendored
Executable
+248
@@ -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());
|
||||
Generated
Vendored
Executable
+3421
File diff suppressed because it is too large
Load Diff
Generated
Vendored
Executable
+24
@@ -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.
|
||||
Generated
Vendored
Executable
+153
@@ -0,0 +1,153 @@
|
||||
[](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
|
||||
var express = require('express')
|
||||
var 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
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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
|
||||
[gratipay-image-visionmedia]: https://img.shields.io/gratipay/visionmedia.svg
|
||||
[gratipay-url-visionmedia]: https://gratipay.com/visionmedia/
|
||||
[gratipay-image-dougwilson]: https://img.shields.io/gratipay/dougwilson.svg
|
||||
[gratipay-url-dougwilson]: https://gratipay.com/dougwilson/
|
||||
Generated
Vendored
Executable
+11
@@ -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');
|
||||
Generated
Vendored
Executable
+644
@@ -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);
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+114
@@ -0,0 +1,114 @@
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var bodyParser = require('body-parser')
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var mixin = require('merge-descriptors');
|
||||
var proto = require('./application');
|
||||
var Route = require('./router/route');
|
||||
var Router = require('./router');
|
||||
var req = require('./request');
|
||||
var res = require('./response');
|
||||
|
||||
/**
|
||||
* Expose `createApplication()`.
|
||||
*/
|
||||
|
||||
exports = module.exports = createApplication;
|
||||
|
||||
/**
|
||||
* Create an express application.
|
||||
*
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function createApplication() {
|
||||
var app = function(req, res, next) {
|
||||
app.handle(req, res, next);
|
||||
};
|
||||
|
||||
mixin(app, EventEmitter.prototype, false);
|
||||
mixin(app, proto, false);
|
||||
|
||||
// expose the prototype that will get set on requests
|
||||
app.request = Object.create(req, {
|
||||
app: { configurable: true, enumerable: true, writable: true, value: app }
|
||||
})
|
||||
|
||||
// expose the prototype that will get set on responses
|
||||
app.response = Object.create(res, {
|
||||
app: { configurable: true, enumerable: true, writable: true, value: app }
|
||||
})
|
||||
|
||||
app.init();
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the prototypes.
|
||||
*/
|
||||
|
||||
exports.application = proto;
|
||||
exports.request = req;
|
||||
exports.response = res;
|
||||
|
||||
/**
|
||||
* Expose constructors.
|
||||
*/
|
||||
|
||||
exports.Route = Route;
|
||||
exports.Router = Router;
|
||||
|
||||
/**
|
||||
* Expose middleware
|
||||
*/
|
||||
|
||||
exports.json = bodyParser.json
|
||||
exports.query = require('./middleware/query');
|
||||
exports.static = require('serve-static');
|
||||
exports.urlencoded = bodyParser.urlencoded
|
||||
|
||||
/**
|
||||
* Replace removed middleware with an appropriate error message.
|
||||
*/
|
||||
|
||||
var removedMiddlewares = [
|
||||
'bodyParser',
|
||||
'compress',
|
||||
'cookieSession',
|
||||
'session',
|
||||
'logger',
|
||||
'cookieParser',
|
||||
'favicon',
|
||||
'responseTime',
|
||||
'errorHandler',
|
||||
'timeout',
|
||||
'methodOverride',
|
||||
'vhost',
|
||||
'csrf',
|
||||
'directory',
|
||||
'limit',
|
||||
'multipart',
|
||||
'staticCache'
|
||||
]
|
||||
|
||||
removedMiddlewares.forEach(function (name) {
|
||||
Object.defineProperty(exports, name, {
|
||||
get: function () {
|
||||
throw new Error('Most middleware (like ' + name + ') is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.');
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
});
|
||||
Generated
Vendored
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/*!
|
||||
* 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 setPrototypeOf = require('setprototypeof')
|
||||
|
||||
/**
|
||||
* Initialization middleware, exposing the
|
||||
* request and response to each other, as well
|
||||
* as defaulting the X-Powered-By header field.
|
||||
*
|
||||
* @param {Function} app
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.init = function(app){
|
||||
return function expressInit(req, res, next){
|
||||
if (app.enabled('x-powered-by')) res.setHeader('X-Powered-By', 'Express');
|
||||
req.res = res;
|
||||
res.req = req;
|
||||
req.next = next;
|
||||
|
||||
setPrototypeOf(req, app.request)
|
||||
setPrototypeOf(res, app.response)
|
||||
|
||||
res.locals = res.locals || Object.create(null);
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
Generated
Vendored
Executable
+47
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var merge = require('utils-merge')
|
||||
var parseUrl = require('parseurl');
|
||||
var qs = require('qs');
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
module.exports = function query(options) {
|
||||
var opts = merge({}, options)
|
||||
var queryparse = qs.parse;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
queryparse = options;
|
||||
opts = undefined;
|
||||
}
|
||||
|
||||
if (opts !== undefined && opts.allowPrototypes === undefined) {
|
||||
// back-compat for qs module
|
||||
opts.allowPrototypes = true;
|
||||
}
|
||||
|
||||
return function query(req, res, next){
|
||||
if (!req.query) {
|
||||
var val = parseUrl(req).query;
|
||||
req.query = queryparse(val, opts);
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
Generated
Vendored
Executable
+521
@@ -0,0 +1,521 @@
|
||||
/*!
|
||||
* 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 accepts = require('accepts');
|
||||
var deprecate = require('depd')('express');
|
||||
var isIP = require('net').isIP;
|
||||
var typeis = require('type-is');
|
||||
var http = require('http');
|
||||
var fresh = require('fresh');
|
||||
var parseRange = require('range-parser');
|
||||
var parse = require('parseurl');
|
||||
var proxyaddr = require('proxy-addr');
|
||||
|
||||
/**
|
||||
* Request prototype.
|
||||
* @public
|
||||
*/
|
||||
|
||||
var req = Object.create(http.IncomingMessage.prototype)
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = req
|
||||
|
||||
/**
|
||||
* Return request header.
|
||||
*
|
||||
* The `Referrer` header field is special-cased,
|
||||
* both `Referrer` and `Referer` are interchangeable.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* req.get('Content-Type');
|
||||
* // => "text/plain"
|
||||
*
|
||||
* req.get('content-type');
|
||||
* // => "text/plain"
|
||||
*
|
||||
* req.get('Something');
|
||||
* // => undefined
|
||||
*
|
||||
* Aliased as `req.header()`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.get =
|
||||
req.header = function header(name) {
|
||||
if (!name) {
|
||||
throw new TypeError('name argument is required to req.get');
|
||||
}
|
||||
|
||||
if (typeof name !== 'string') {
|
||||
throw new TypeError('name must be a string to req.get');
|
||||
}
|
||||
|
||||
var lc = name.toLowerCase();
|
||||
|
||||
switch (lc) {
|
||||
case 'referer':
|
||||
case 'referrer':
|
||||
return this.headers.referrer
|
||||
|| this.headers.referer;
|
||||
default:
|
||||
return this.headers[lc];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* To do: update docs.
|
||||
*
|
||||
* 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", an extension name
|
||||
* such as "json", a comma-delimited list such as "json, html, text/plain",
|
||||
* an argument list such as `"json", "html", "text/plain"`,
|
||||
* 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
|
||||
* req.accepts('html');
|
||||
* // => "html"
|
||||
*
|
||||
* // Accept: text/*, application/json
|
||||
* req.accepts('html');
|
||||
* // => "html"
|
||||
* req.accepts('text/html');
|
||||
* // => "text/html"
|
||||
* req.accepts('json, text');
|
||||
* // => "json"
|
||||
* req.accepts('application/json');
|
||||
* // => "application/json"
|
||||
*
|
||||
* // Accept: text/*, application/json
|
||||
* req.accepts('image/png');
|
||||
* req.accepts('png');
|
||||
* // => undefined
|
||||
*
|
||||
* // Accept: text/*;q=.5, application/json
|
||||
* req.accepts(['html', 'json']);
|
||||
* req.accepts('html', 'json');
|
||||
* req.accepts('html, json');
|
||||
* // => "json"
|
||||
*
|
||||
* @param {String|Array} type(s)
|
||||
* @return {String|Array|Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.accepts = function(){
|
||||
var accept = accepts(this);
|
||||
return accept.types.apply(accept, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the given `encoding`s are accepted.
|
||||
*
|
||||
* @param {String} ...encoding
|
||||
* @return {String|Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.acceptsEncodings = function(){
|
||||
var accept = accepts(this);
|
||||
return accept.encodings.apply(accept, arguments);
|
||||
};
|
||||
|
||||
req.acceptsEncoding = deprecate.function(req.acceptsEncodings,
|
||||
'req.acceptsEncoding: Use acceptsEncodings instead');
|
||||
|
||||
/**
|
||||
* Check if the given `charset`s are acceptable,
|
||||
* otherwise you should respond with 406 "Not Acceptable".
|
||||
*
|
||||
* @param {String} ...charset
|
||||
* @return {String|Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.acceptsCharsets = function(){
|
||||
var accept = accepts(this);
|
||||
return accept.charsets.apply(accept, arguments);
|
||||
};
|
||||
|
||||
req.acceptsCharset = deprecate.function(req.acceptsCharsets,
|
||||
'req.acceptsCharset: Use acceptsCharsets instead');
|
||||
|
||||
/**
|
||||
* Check if the given `lang`s are acceptable,
|
||||
* otherwise you should respond with 406 "Not Acceptable".
|
||||
*
|
||||
* @param {String} ...lang
|
||||
* @return {String|Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.acceptsLanguages = function(){
|
||||
var accept = accepts(this);
|
||||
return accept.languages.apply(accept, arguments);
|
||||
};
|
||||
|
||||
req.acceptsLanguage = deprecate.function(req.acceptsLanguages,
|
||||
'req.acceptsLanguage: Use acceptsLanguages instead');
|
||||
|
||||
/**
|
||||
* Parse Range header field, capping to the given `size`.
|
||||
*
|
||||
* Unspecified ranges such as "0-" require knowledge of your resource length. In
|
||||
* the case of a byte range this is of course the total number of bytes. If the
|
||||
* Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
|
||||
* and `-2` when syntactically invalid.
|
||||
*
|
||||
* When ranges are returned, the array has a "type" property which is the type of
|
||||
* range that is required (most commonly, "bytes"). Each array element is an object
|
||||
* with a "start" and "end" property for the portion of the range.
|
||||
*
|
||||
* The "combine" option can be set to `true` and overlapping & adjacent ranges
|
||||
* will be combined into a single range.
|
||||
*
|
||||
* NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
|
||||
* should respond with 4 users when available, not 3.
|
||||
*
|
||||
* @param {number} size
|
||||
* @param {object} [options]
|
||||
* @param {boolean} [options.combine=false]
|
||||
* @return {number|array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.range = function range(size, options) {
|
||||
var range = this.get('Range');
|
||||
if (!range) return;
|
||||
return parseRange(size, range, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the value of param `name` when present or `defaultValue`.
|
||||
*
|
||||
* - Checks route placeholders, ex: _/user/:id_
|
||||
* - Checks body params, ex: id=12, {"id":12}
|
||||
* - Checks query string params, ex: ?id=12
|
||||
*
|
||||
* To utilize request bodies, `req.body`
|
||||
* should be an object. This can be done by using
|
||||
* the `bodyParser()` middleware.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Mixed} [defaultValue]
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.param = function param(name, defaultValue) {
|
||||
var params = this.params || {};
|
||||
var body = this.body || {};
|
||||
var query = this.query || {};
|
||||
|
||||
var args = arguments.length === 1
|
||||
? 'name'
|
||||
: 'name, default';
|
||||
deprecate('req.param(' + args + '): Use req.params, req.body, or req.query instead');
|
||||
|
||||
if (null != params[name] && params.hasOwnProperty(name)) return params[name];
|
||||
if (null != body[name]) return body[name];
|
||||
if (null != query[name]) return query[name];
|
||||
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the incoming request contains the "Content-Type"
|
||||
* header field, and it contains the give mime `type`.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* // With Content-Type: text/html; charset=utf-8
|
||||
* req.is('html');
|
||||
* req.is('text/html');
|
||||
* req.is('text/*');
|
||||
* // => true
|
||||
*
|
||||
* // When Content-Type is application/json
|
||||
* req.is('json');
|
||||
* req.is('application/json');
|
||||
* req.is('application/*');
|
||||
* // => true
|
||||
*
|
||||
* req.is('html');
|
||||
* // => false
|
||||
*
|
||||
* @param {String|Array} types...
|
||||
* @return {String|false|null}
|
||||
* @public
|
||||
*/
|
||||
|
||||
req.is = function is(types) {
|
||||
var arr = types;
|
||||
|
||||
// support flattened arguments
|
||||
if (!Array.isArray(types)) {
|
||||
arr = new Array(arguments.length);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
arr[i] = arguments[i];
|
||||
}
|
||||
}
|
||||
|
||||
return typeis(this, arr);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the protocol string "http" or "https"
|
||||
* when requested with TLS. When the "trust proxy"
|
||||
* setting trusts the socket address, the
|
||||
* "X-Forwarded-Proto" header field will be trusted
|
||||
* and used if present.
|
||||
*
|
||||
* If you're running behind a reverse proxy that
|
||||
* supplies https for you this may be enabled.
|
||||
*
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'protocol', function protocol(){
|
||||
var proto = this.connection.encrypted
|
||||
? 'https'
|
||||
: 'http';
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
|
||||
if (!trust(this.connection.remoteAddress, 0)) {
|
||||
return proto;
|
||||
}
|
||||
|
||||
// Note: X-Forwarded-Proto is normally only ever a
|
||||
// single value, but this is to be safe.
|
||||
var header = this.get('X-Forwarded-Proto') || proto
|
||||
var index = header.indexOf(',')
|
||||
|
||||
return index !== -1
|
||||
? header.substring(0, index).trim()
|
||||
: header.trim()
|
||||
});
|
||||
|
||||
/**
|
||||
* Short-hand for:
|
||||
*
|
||||
* req.protocol === 'https'
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'secure', function secure(){
|
||||
return this.protocol === 'https';
|
||||
});
|
||||
|
||||
/**
|
||||
* Return the remote address from the trusted proxy.
|
||||
*
|
||||
* The is the remote address on the socket unless
|
||||
* "trust proxy" is set.
|
||||
*
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'ip', function ip(){
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
return proxyaddr(this, trust);
|
||||
});
|
||||
|
||||
/**
|
||||
* When "trust proxy" is set, trusted proxy addresses + client.
|
||||
*
|
||||
* For example if the value were "client, proxy1, proxy2"
|
||||
* you would receive the array `["client", "proxy1", "proxy2"]`
|
||||
* where "proxy2" is the furthest down-stream and "proxy1" and
|
||||
* "proxy2" were trusted.
|
||||
*
|
||||
* @return {Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'ips', function ips() {
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
var addrs = proxyaddr.all(this, trust);
|
||||
|
||||
// reverse the order (to farthest -> closest)
|
||||
// and remove socket address
|
||||
addrs.reverse().pop()
|
||||
|
||||
return addrs
|
||||
});
|
||||
|
||||
/**
|
||||
* Return subdomains as an array.
|
||||
*
|
||||
* Subdomains are the dot-separated parts of the host before the main domain of
|
||||
* the app. By default, the domain of the app is assumed to be the last two
|
||||
* parts of the host. This can be changed by setting "subdomain offset".
|
||||
*
|
||||
* For example, if the domain is "tobi.ferrets.example.com":
|
||||
* If "subdomain offset" is not set, req.subdomains is `["ferrets", "tobi"]`.
|
||||
* If "subdomain offset" is 3, req.subdomains is `["tobi"]`.
|
||||
*
|
||||
* @return {Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'subdomains', function subdomains() {
|
||||
var hostname = this.hostname;
|
||||
|
||||
if (!hostname) return [];
|
||||
|
||||
var offset = this.app.get('subdomain offset');
|
||||
var subdomains = !isIP(hostname)
|
||||
? hostname.split('.').reverse()
|
||||
: [hostname];
|
||||
|
||||
return subdomains.slice(offset);
|
||||
});
|
||||
|
||||
/**
|
||||
* Short-hand for `url.parse(req.url).pathname`.
|
||||
*
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'path', function path() {
|
||||
return parse(this).pathname;
|
||||
});
|
||||
|
||||
/**
|
||||
* Parse the "Host" header field to a hostname.
|
||||
*
|
||||
* When the "trust proxy" setting trusts the socket
|
||||
* address, the "X-Forwarded-Host" header field will
|
||||
* be trusted.
|
||||
*
|
||||
* @return {String}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'hostname', function hostname(){
|
||||
var trust = this.app.get('trust proxy fn');
|
||||
var host = this.get('X-Forwarded-Host');
|
||||
|
||||
if (!host || !trust(this.connection.remoteAddress, 0)) {
|
||||
host = this.get('Host');
|
||||
}
|
||||
|
||||
if (!host) return;
|
||||
|
||||
// IPv6 literal support
|
||||
var offset = host[0] === '['
|
||||
? host.indexOf(']') + 1
|
||||
: 0;
|
||||
var index = host.indexOf(':', offset);
|
||||
|
||||
return index !== -1
|
||||
? host.substring(0, index)
|
||||
: host;
|
||||
});
|
||||
|
||||
// TODO: change req.host to return host in next major
|
||||
|
||||
defineGetter(req, 'host', deprecate.function(function host(){
|
||||
return this.hostname;
|
||||
}, 'req.host: Use req.hostname instead'));
|
||||
|
||||
/**
|
||||
* Check if the request is fresh, aka
|
||||
* Last-Modified and/or the ETag
|
||||
* still match.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'fresh', function(){
|
||||
var method = this.method;
|
||||
var res = this.res
|
||||
var status = res.statusCode
|
||||
|
||||
// GET or HEAD for weak freshness validation only
|
||||
if ('GET' !== method && 'HEAD' !== method) return false;
|
||||
|
||||
// 2xx or 304 as per rfc2616 14.26
|
||||
if ((status >= 200 && status < 300) || 304 === status) {
|
||||
return fresh(this.headers, {
|
||||
'etag': res.get('ETag'),
|
||||
'last-modified': res.get('Last-Modified')
|
||||
})
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Check if the request is stale, aka
|
||||
* "Last-Modified" and / or the "ETag" for the
|
||||
* resource has changed.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'stale', function stale(){
|
||||
return !this.fresh;
|
||||
});
|
||||
|
||||
/**
|
||||
* Check if the request was an _XMLHttpRequest_.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @public
|
||||
*/
|
||||
|
||||
defineGetter(req, 'xhr', function xhr(){
|
||||
var val = this.get('X-Requested-With') || '';
|
||||
return val.toLowerCase() === 'xmlhttprequest';
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper function for creating a getter on an object.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} name
|
||||
* @param {Function} getter
|
||||
* @private
|
||||
*/
|
||||
function defineGetter(obj, name, getter) {
|
||||
Object.defineProperty(obj, name, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: getter
|
||||
});
|
||||
}
|
||||
Generated
Vendored
Executable
+1137
File diff suppressed because it is too large
Load Diff
Generated
Vendored
Executable
+662
@@ -0,0 +1,662 @@
|
||||
/*!
|
||||
* 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 Route = require('./route');
|
||||
var Layer = require('./layer');
|
||||
var methods = require('methods');
|
||||
var mixin = require('utils-merge');
|
||||
var debug = require('debug')('express:router');
|
||||
var deprecate = require('depd')('express');
|
||||
var flatten = require('array-flatten');
|
||||
var parseUrl = require('parseurl');
|
||||
var setPrototypeOf = require('setprototypeof')
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var objectRegExp = /^\[object (\S+)\]$/;
|
||||
var slice = Array.prototype.slice;
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
* Initialize a new `Router` with the given `options`.
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* @return {Router} which is an callable function
|
||||
* @public
|
||||
*/
|
||||
|
||||
var proto = module.exports = function(options) {
|
||||
var opts = options || {};
|
||||
|
||||
function router(req, res, next) {
|
||||
router.handle(req, res, next);
|
||||
}
|
||||
|
||||
// mixin Router class functions
|
||||
setPrototypeOf(router, proto)
|
||||
|
||||
router.params = {};
|
||||
router._params = [];
|
||||
router.caseSensitive = opts.caseSensitive;
|
||||
router.mergeParams = opts.mergeParams;
|
||||
router.strict = opts.strict;
|
||||
router.stack = [];
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
/**
|
||||
* Map the given param placeholder `name`(s) to the given callback.
|
||||
*
|
||||
* Parameter mapping is used to provide pre-conditions to routes
|
||||
* which use normalized placeholders. For example a _:user_id_ parameter
|
||||
* could automatically load a user's information from the database without
|
||||
* any additional code,
|
||||
*
|
||||
* The callback uses the same signature as middleware, the only difference
|
||||
* being that the value of the placeholder is passed, in this case the _id_
|
||||
* of the user. Once the `next()` function is invoked, just like middleware
|
||||
* it will continue on to execute the route, or subsequent parameter functions.
|
||||
*
|
||||
* Just like in middleware, you must either respond to the request or call next
|
||||
* to avoid stalling the request.
|
||||
*
|
||||
* app.param('user_id', function(req, res, next, id){
|
||||
* User.find(id, function(err, user){
|
||||
* if (err) {
|
||||
* return next(err);
|
||||
* } else if (!user) {
|
||||
* return next(new Error('failed to load user'));
|
||||
* }
|
||||
* req.user = user;
|
||||
* next();
|
||||
* });
|
||||
* });
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Function} fn
|
||||
* @return {app} for chaining
|
||||
* @public
|
||||
*/
|
||||
|
||||
proto.param = function param(name, fn) {
|
||||
// param logic
|
||||
if (typeof name === 'function') {
|
||||
deprecate('router.param(fn): Refactor to use path params');
|
||||
this._params.push(name);
|
||||
return;
|
||||
}
|
||||
|
||||
// apply param functions
|
||||
var params = this._params;
|
||||
var len = params.length;
|
||||
var ret;
|
||||
|
||||
if (name[0] === ':') {
|
||||
deprecate('router.param(' + JSON.stringify(name) + ', fn): Use router.param(' + JSON.stringify(name.substr(1)) + ', fn) instead');
|
||||
name = name.substr(1);
|
||||
}
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
if (ret = params[i](name, fn)) {
|
||||
fn = ret;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure we end up with a
|
||||
// middleware function
|
||||
if ('function' !== typeof fn) {
|
||||
throw new Error('invalid param() call for ' + name + ', got ' + fn);
|
||||
}
|
||||
|
||||
(this.params[name] = this.params[name] || []).push(fn);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch a req, res into the router.
|
||||
* @private
|
||||
*/
|
||||
|
||||
proto.handle = function handle(req, res, out) {
|
||||
var self = this;
|
||||
|
||||
debug('dispatching %s %s', req.method, req.url);
|
||||
|
||||
var idx = 0;
|
||||
var protohost = getProtohost(req.url) || ''
|
||||
var removed = '';
|
||||
var slashAdded = false;
|
||||
var paramcalled = {};
|
||||
|
||||
// store options for OPTIONS request
|
||||
// only used if OPTIONS request
|
||||
var options = [];
|
||||
|
||||
// middleware and routes
|
||||
var stack = self.stack;
|
||||
|
||||
// manage inter-router variables
|
||||
var parentParams = req.params;
|
||||
var parentUrl = req.baseUrl || '';
|
||||
var done = restore(out, req, 'baseUrl', 'next', 'params');
|
||||
|
||||
// setup next layer
|
||||
req.next = next;
|
||||
|
||||
// for options requests, respond with a default if nothing else responds
|
||||
if (req.method === 'OPTIONS') {
|
||||
done = wrap(done, function(old, err) {
|
||||
if (err || options.length === 0) return old(err);
|
||||
sendOptionsResponse(res, options, old);
|
||||
});
|
||||
}
|
||||
|
||||
// setup basic req values
|
||||
req.baseUrl = parentUrl;
|
||||
req.originalUrl = req.originalUrl || req.url;
|
||||
|
||||
next();
|
||||
|
||||
function next(err) {
|
||||
var layerError = err === 'route'
|
||||
? null
|
||||
: err;
|
||||
|
||||
// remove added slash
|
||||
if (slashAdded) {
|
||||
req.url = req.url.substr(1);
|
||||
slashAdded = false;
|
||||
}
|
||||
|
||||
// restore altered req.url
|
||||
if (removed.length !== 0) {
|
||||
req.baseUrl = parentUrl;
|
||||
req.url = protohost + removed + req.url.substr(protohost.length);
|
||||
removed = '';
|
||||
}
|
||||
|
||||
// signal to exit router
|
||||
if (layerError === 'router') {
|
||||
setImmediate(done, null)
|
||||
return
|
||||
}
|
||||
|
||||
// no more matching layers
|
||||
if (idx >= stack.length) {
|
||||
setImmediate(done, layerError);
|
||||
return;
|
||||
}
|
||||
|
||||
// get pathname of request
|
||||
var path = getPathname(req);
|
||||
|
||||
if (path == null) {
|
||||
return done(layerError);
|
||||
}
|
||||
|
||||
// find next matching layer
|
||||
var layer;
|
||||
var match;
|
||||
var route;
|
||||
|
||||
while (match !== true && idx < stack.length) {
|
||||
layer = stack[idx++];
|
||||
match = matchLayer(layer, path);
|
||||
route = layer.route;
|
||||
|
||||
if (typeof match !== 'boolean') {
|
||||
// hold on to layerError
|
||||
layerError = layerError || match;
|
||||
}
|
||||
|
||||
if (match !== true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!route) {
|
||||
// process non-route handlers normally
|
||||
continue;
|
||||
}
|
||||
|
||||
if (layerError) {
|
||||
// routes do not match with a pending error
|
||||
match = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
var method = req.method;
|
||||
var has_method = route._handles_method(method);
|
||||
|
||||
// build up automatic options response
|
||||
if (!has_method && method === 'OPTIONS') {
|
||||
appendMethods(options, route._options());
|
||||
}
|
||||
|
||||
// don't even bother matching route
|
||||
if (!has_method && method !== 'HEAD') {
|
||||
match = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// no match
|
||||
if (match !== true) {
|
||||
return done(layerError);
|
||||
}
|
||||
|
||||
// store route for dispatch on change
|
||||
if (route) {
|
||||
req.route = route;
|
||||
}
|
||||
|
||||
// Capture one-time layer values
|
||||
req.params = self.mergeParams
|
||||
? mergeParams(layer.params, parentParams)
|
||||
: layer.params;
|
||||
var layerPath = layer.path;
|
||||
|
||||
// this should be done for the layer
|
||||
self.process_params(layer, paramcalled, req, res, function (err) {
|
||||
if (err) {
|
||||
return next(layerError || err);
|
||||
}
|
||||
|
||||
if (route) {
|
||||
return layer.handle_request(req, res, next);
|
||||
}
|
||||
|
||||
trim_prefix(layer, layerError, layerPath, path);
|
||||
});
|
||||
}
|
||||
|
||||
function trim_prefix(layer, layerError, layerPath, path) {
|
||||
if (layerPath.length !== 0) {
|
||||
// Validate path breaks on a path separator
|
||||
var c = path[layerPath.length]
|
||||
if (c && c !== '/' && c !== '.') return next(layerError)
|
||||
|
||||
// Trim off the part of the url that matches the route
|
||||
// middleware (.use stuff) needs to have the path stripped
|
||||
debug('trim prefix (%s) from url %s', layerPath, req.url);
|
||||
removed = layerPath;
|
||||
req.url = protohost + req.url.substr(protohost.length + removed.length);
|
||||
|
||||
// Ensure leading slash
|
||||
if (!protohost && req.url[0] !== '/') {
|
||||
req.url = '/' + req.url;
|
||||
slashAdded = true;
|
||||
}
|
||||
|
||||
// Setup base URL (no trailing slash)
|
||||
req.baseUrl = parentUrl + (removed[removed.length - 1] === '/'
|
||||
? removed.substring(0, removed.length - 1)
|
||||
: removed);
|
||||
}
|
||||
|
||||
debug('%s %s : %s', layer.name, layerPath, req.originalUrl);
|
||||
|
||||
if (layerError) {
|
||||
layer.handle_error(layerError, req, res, next);
|
||||
} else {
|
||||
layer.handle_request(req, res, next);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Process any parameters for the layer.
|
||||
* @private
|
||||
*/
|
||||
|
||||
proto.process_params = function process_params(layer, called, req, res, done) {
|
||||
var params = this.params;
|
||||
|
||||
// captured parameters from the layer, keys and values
|
||||
var keys = layer.keys;
|
||||
|
||||
// fast track
|
||||
if (!keys || keys.length === 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var name;
|
||||
var paramIndex = 0;
|
||||
var key;
|
||||
var paramVal;
|
||||
var paramCallbacks;
|
||||
var paramCalled;
|
||||
|
||||
// process params in order
|
||||
// param callbacks can be async
|
||||
function param(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
if (i >= keys.length ) {
|
||||
return done();
|
||||
}
|
||||
|
||||
paramIndex = 0;
|
||||
key = keys[i++];
|
||||
name = key.name;
|
||||
paramVal = req.params[name];
|
||||
paramCallbacks = params[name];
|
||||
paramCalled = called[name];
|
||||
|
||||
if (paramVal === undefined || !paramCallbacks) {
|
||||
return param();
|
||||
}
|
||||
|
||||
// param previously called with same value or error occurred
|
||||
if (paramCalled && (paramCalled.match === paramVal
|
||||
|| (paramCalled.error && paramCalled.error !== 'route'))) {
|
||||
// restore value
|
||||
req.params[name] = paramCalled.value;
|
||||
|
||||
// next param
|
||||
return param(paramCalled.error);
|
||||
}
|
||||
|
||||
called[name] = paramCalled = {
|
||||
error: null,
|
||||
match: paramVal,
|
||||
value: paramVal
|
||||
};
|
||||
|
||||
paramCallback();
|
||||
}
|
||||
|
||||
// single param callbacks
|
||||
function paramCallback(err) {
|
||||
var fn = paramCallbacks[paramIndex++];
|
||||
|
||||
// store updated value
|
||||
paramCalled.value = req.params[key.name];
|
||||
|
||||
if (err) {
|
||||
// store error
|
||||
paramCalled.error = err;
|
||||
param(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fn) return param();
|
||||
|
||||
try {
|
||||
fn(req, res, paramCallback, paramVal, key.name);
|
||||
} catch (e) {
|
||||
paramCallback(e);
|
||||
}
|
||||
}
|
||||
|
||||
param();
|
||||
};
|
||||
|
||||
/**
|
||||
* Use the given middleware function, with optional path, defaulting to "/".
|
||||
*
|
||||
* Use (like `.all`) will run for any http METHOD, but it will not add
|
||||
* handlers for those methods so OPTIONS requests will not consider `.use`
|
||||
* functions even if they could respond.
|
||||
*
|
||||
* The other difference is that _route_ path is stripped and not visible
|
||||
* to the handler function. The main effect of this feature is that mounted
|
||||
* handlers can operate without any code changes regardless of the "prefix"
|
||||
* pathname.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
proto.use = function use(fn) {
|
||||
var offset = 0;
|
||||
var path = '/';
|
||||
|
||||
// default path to '/'
|
||||
// disambiguate router.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 callbacks = flatten(slice.call(arguments, offset));
|
||||
|
||||
if (callbacks.length === 0) {
|
||||
throw new TypeError('Router.use() requires a middleware function')
|
||||
}
|
||||
|
||||
for (var i = 0; i < callbacks.length; i++) {
|
||||
var fn = callbacks[i];
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
|
||||
}
|
||||
|
||||
// add the middleware
|
||||
debug('use %o %s', path, fn.name || '<anonymous>')
|
||||
|
||||
var layer = new Layer(path, {
|
||||
sensitive: this.caseSensitive,
|
||||
strict: false,
|
||||
end: false
|
||||
}, fn);
|
||||
|
||||
layer.route = undefined;
|
||||
|
||||
this.stack.push(layer);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new Route for the given path.
|
||||
*
|
||||
* Each route contains a separate middleware stack and VERB handlers.
|
||||
*
|
||||
* See the Route api documentation for details on adding handlers
|
||||
* and middleware to routes.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Route}
|
||||
* @public
|
||||
*/
|
||||
|
||||
proto.route = function route(path) {
|
||||
var route = new Route(path);
|
||||
|
||||
var layer = new Layer(path, {
|
||||
sensitive: this.caseSensitive,
|
||||
strict: this.strict,
|
||||
end: true
|
||||
}, route.dispatch.bind(route));
|
||||
|
||||
layer.route = route;
|
||||
|
||||
this.stack.push(layer);
|
||||
return route;
|
||||
};
|
||||
|
||||
// create Router#VERB functions
|
||||
methods.concat('all').forEach(function(method){
|
||||
proto[method] = function(path){
|
||||
var route = this.route(path)
|
||||
route[method].apply(route, slice.call(arguments, 1));
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
||||
// append methods to a list of methods
|
||||
function appendMethods(list, addition) {
|
||||
for (var i = 0; i < addition.length; i++) {
|
||||
var method = addition[i];
|
||||
if (list.indexOf(method) === -1) {
|
||||
list.push(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get pathname of request
|
||||
function getPathname(req) {
|
||||
try {
|
||||
return parseUrl(req).pathname;
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Get get protocol + host for a URL
|
||||
function getProtohost(url) {
|
||||
if (typeof url !== 'string' || url.length === 0 || url[0] === '/') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
var searchIndex = url.indexOf('?')
|
||||
var pathLength = searchIndex !== -1
|
||||
? searchIndex
|
||||
: url.length
|
||||
var fqdnIndex = url.substr(0, pathLength).indexOf('://')
|
||||
|
||||
return fqdnIndex !== -1
|
||||
? url.substr(0, url.indexOf('/', 3 + fqdnIndex))
|
||||
: undefined
|
||||
}
|
||||
|
||||
// get type for error message
|
||||
function gettype(obj) {
|
||||
var type = typeof obj;
|
||||
|
||||
if (type !== 'object') {
|
||||
return type;
|
||||
}
|
||||
|
||||
// inspect [[Class]] for objects
|
||||
return toString.call(obj)
|
||||
.replace(objectRegExp, '$1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Match path to a layer.
|
||||
*
|
||||
* @param {Layer} layer
|
||||
* @param {string} path
|
||||
* @private
|
||||
*/
|
||||
|
||||
function matchLayer(layer, path) {
|
||||
try {
|
||||
return layer.match(path);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// merge params with parent params
|
||||
function mergeParams(params, parent) {
|
||||
if (typeof parent !== 'object' || !parent) {
|
||||
return params;
|
||||
}
|
||||
|
||||
// make copy of parent for base
|
||||
var obj = mixin({}, parent);
|
||||
|
||||
// simple non-numeric merging
|
||||
if (!(0 in params) || !(0 in parent)) {
|
||||
return mixin(obj, params);
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var o = 0;
|
||||
|
||||
// determine numeric gaps
|
||||
while (i in params) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (o in parent) {
|
||||
o++;
|
||||
}
|
||||
|
||||
// offset numeric indices in params before merge
|
||||
for (i--; i >= 0; i--) {
|
||||
params[i + o] = params[i];
|
||||
|
||||
// create holes for the merge when necessary
|
||||
if (i < o) {
|
||||
delete params[i];
|
||||
}
|
||||
}
|
||||
|
||||
return mixin(obj, params);
|
||||
}
|
||||
|
||||
// restore obj props after function
|
||||
function restore(fn, obj) {
|
||||
var props = new Array(arguments.length - 2);
|
||||
var vals = new Array(arguments.length - 2);
|
||||
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
props[i] = arguments[i + 2];
|
||||
vals[i] = obj[props[i]];
|
||||
}
|
||||
|
||||
return function () {
|
||||
// restore vals
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
obj[props[i]] = vals[i];
|
||||
}
|
||||
|
||||
return fn.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// send an OPTIONS response
|
||||
function sendOptionsResponse(res, options, next) {
|
||||
try {
|
||||
var body = options.join(',');
|
||||
res.set('Allow', body);
|
||||
res.send(body);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
|
||||
// wrap a function
|
||||
function wrap(old, fn) {
|
||||
return function proxy() {
|
||||
var args = new Array(arguments.length + 1);
|
||||
|
||||
args[0] = old;
|
||||
for (var i = 0, len = arguments.length; i < len; i++) {
|
||||
args[i + 1] = arguments[i];
|
||||
}
|
||||
|
||||
fn.apply(this, args);
|
||||
};
|
||||
}
|
||||
Generated
Vendored
Executable
+181
@@ -0,0 +1,181 @@
|
||||
/*!
|
||||
* 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 pathRegexp = require('path-to-regexp');
|
||||
var debug = require('debug')('express:router:layer');
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Layer;
|
||||
|
||||
function Layer(path, options, fn) {
|
||||
if (!(this instanceof Layer)) {
|
||||
return new Layer(path, options, fn);
|
||||
}
|
||||
|
||||
debug('new %o', path)
|
||||
var opts = options || {};
|
||||
|
||||
this.handle = fn;
|
||||
this.name = fn.name || '<anonymous>';
|
||||
this.params = undefined;
|
||||
this.path = undefined;
|
||||
this.regexp = pathRegexp(path, this.keys = [], opts);
|
||||
|
||||
// set fast path flags
|
||||
this.regexp.fast_star = path === '*'
|
||||
this.regexp.fast_slash = path === '/' && opts.end === false
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the error for the layer.
|
||||
*
|
||||
* @param {Error} error
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {function} next
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Layer.prototype.handle_error = function handle_error(error, req, res, next) {
|
||||
var fn = this.handle;
|
||||
|
||||
if (fn.length !== 4) {
|
||||
// not a standard error handler
|
||||
return next(error);
|
||||
}
|
||||
|
||||
try {
|
||||
fn(error, req, res, next);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle the request for the layer.
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {function} next
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Layer.prototype.handle_request = function handle(req, res, next) {
|
||||
var fn = this.handle;
|
||||
|
||||
if (fn.length > 3) {
|
||||
// not a standard request handler
|
||||
return next();
|
||||
}
|
||||
|
||||
try {
|
||||
fn(req, res, next);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this route matches `path`, if so
|
||||
* populate `.params`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Layer.prototype.match = function match(path) {
|
||||
var match
|
||||
|
||||
if (path != null) {
|
||||
// fast path non-ending match for / (any path matches)
|
||||
if (this.regexp.fast_slash) {
|
||||
this.params = {}
|
||||
this.path = ''
|
||||
return true
|
||||
}
|
||||
|
||||
// fast path for * (everything matched in a param)
|
||||
if (this.regexp.fast_star) {
|
||||
this.params = {'0': decode_param(path)}
|
||||
this.path = path
|
||||
return true
|
||||
}
|
||||
|
||||
// match the path
|
||||
match = this.regexp.exec(path)
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
this.params = undefined;
|
||||
this.path = undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
// store values
|
||||
this.params = {};
|
||||
this.path = match[0]
|
||||
|
||||
var keys = this.keys;
|
||||
var params = this.params;
|
||||
|
||||
for (var i = 1; i < match.length; i++) {
|
||||
var key = keys[i - 1];
|
||||
var prop = key.name;
|
||||
var val = decode_param(match[i])
|
||||
|
||||
if (val !== undefined || !(hasOwnProperty.call(params, prop))) {
|
||||
params[prop] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode param value.
|
||||
*
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function decode_param(val) {
|
||||
if (typeof val !== 'string' || val.length === 0) {
|
||||
return val;
|
||||
}
|
||||
|
||||
try {
|
||||
return decodeURIComponent(val);
|
||||
} catch (err) {
|
||||
if (err instanceof URIError) {
|
||||
err.message = 'Failed to decode param \'' + val + '\'';
|
||||
err.status = err.statusCode = 400;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+216
@@ -0,0 +1,216 @@
|
||||
/*!
|
||||
* 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 debug = require('debug')('express:router:route');
|
||||
var flatten = require('array-flatten');
|
||||
var Layer = require('./layer');
|
||||
var methods = require('methods');
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = Route;
|
||||
|
||||
/**
|
||||
* Initialize `Route` with the given `path`,
|
||||
*
|
||||
* @param {String} path
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Route(path) {
|
||||
this.path = path;
|
||||
this.stack = [];
|
||||
|
||||
debug('new %o', path)
|
||||
|
||||
// route handlers for various http methods
|
||||
this.methods = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route handles a given method.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Route.prototype._handles_method = function _handles_method(method) {
|
||||
if (this.methods._all) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var name = method.toLowerCase();
|
||||
|
||||
if (name === 'head' && !this.methods['head']) {
|
||||
name = 'get';
|
||||
}
|
||||
|
||||
return Boolean(this.methods[name]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Array} supported HTTP methods
|
||||
* @private
|
||||
*/
|
||||
|
||||
Route.prototype._options = function _options() {
|
||||
var methods = Object.keys(this.methods);
|
||||
|
||||
// append automatic head
|
||||
if (this.methods.get && !this.methods.head) {
|
||||
methods.push('head');
|
||||
}
|
||||
|
||||
for (var i = 0; i < methods.length; i++) {
|
||||
// make upper case
|
||||
methods[i] = methods[i].toUpperCase();
|
||||
}
|
||||
|
||||
return methods;
|
||||
};
|
||||
|
||||
/**
|
||||
* dispatch req, res into this route
|
||||
* @private
|
||||
*/
|
||||
|
||||
Route.prototype.dispatch = function dispatch(req, res, done) {
|
||||
var idx = 0;
|
||||
var stack = this.stack;
|
||||
if (stack.length === 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
var method = req.method.toLowerCase();
|
||||
if (method === 'head' && !this.methods['head']) {
|
||||
method = 'get';
|
||||
}
|
||||
|
||||
req.route = this;
|
||||
|
||||
next();
|
||||
|
||||
function next(err) {
|
||||
// signal to exit route
|
||||
if (err && err === 'route') {
|
||||
return done();
|
||||
}
|
||||
|
||||
// signal to exit router
|
||||
if (err && err === 'router') {
|
||||
return done(err)
|
||||
}
|
||||
|
||||
var layer = stack[idx++];
|
||||
if (!layer) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
if (layer.method && layer.method !== method) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
layer.handle_error(err, req, res, next);
|
||||
} else {
|
||||
layer.handle_request(req, res, next);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a handler for all HTTP verbs to this route.
|
||||
*
|
||||
* Behaves just like middleware and can respond or call `next`
|
||||
* to continue processing.
|
||||
*
|
||||
* You can use multiple `.all` call to add multiple handlers.
|
||||
*
|
||||
* function check_something(req, res, next){
|
||||
* next();
|
||||
* };
|
||||
*
|
||||
* function validate_user(req, res, next){
|
||||
* next();
|
||||
* };
|
||||
*
|
||||
* route
|
||||
* .all(validate_user)
|
||||
* .all(check_something)
|
||||
* .get(function(req, res, next){
|
||||
* res.send('hello world');
|
||||
* });
|
||||
*
|
||||
* @param {function} handler
|
||||
* @return {Route} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Route.prototype.all = function all() {
|
||||
var handles = flatten(slice.call(arguments));
|
||||
|
||||
for (var i = 0; i < handles.length; i++) {
|
||||
var handle = handles[i];
|
||||
|
||||
if (typeof handle !== 'function') {
|
||||
var type = toString.call(handle);
|
||||
var msg = 'Route.all() requires a callback function but got a ' + type
|
||||
throw new TypeError(msg);
|
||||
}
|
||||
|
||||
var layer = Layer('/', {}, handle);
|
||||
layer.method = undefined;
|
||||
|
||||
this.methods._all = true;
|
||||
this.stack.push(layer);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
methods.forEach(function(method){
|
||||
Route.prototype[method] = function(){
|
||||
var handles = flatten(slice.call(arguments));
|
||||
|
||||
for (var i = 0; i < handles.length; i++) {
|
||||
var handle = handles[i];
|
||||
|
||||
if (typeof handle !== 'function') {
|
||||
var type = toString.call(handle);
|
||||
var msg = 'Route.' + method + '() requires a callback function but got a ' + type
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
debug('%s %o', method, this.path)
|
||||
|
||||
var layer = Layer('/', {}, handle);
|
||||
layer.method = method;
|
||||
|
||||
this.methods[method] = true;
|
||||
this.stack.push(layer);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
});
|
||||
Generated
Vendored
Executable
+306
@@ -0,0 +1,306 @@
|
||||
/*!
|
||||
* express
|
||||
* Copyright(c) 2009-2013 TJ Holowaychuk
|
||||
* Copyright(c) 2014-2015 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var Buffer = require('safe-buffer').Buffer
|
||||
var contentDisposition = require('content-disposition');
|
||||
var contentType = require('content-type');
|
||||
var deprecate = require('depd')('express');
|
||||
var flatten = require('array-flatten');
|
||||
var mime = require('send').mime;
|
||||
var etag = require('etag');
|
||||
var proxyaddr = require('proxy-addr');
|
||||
var qs = require('qs');
|
||||
var querystring = require('querystring');
|
||||
|
||||
/**
|
||||
* Return strong ETag for `body`.
|
||||
*
|
||||
* @param {String|Buffer} body
|
||||
* @param {String} [encoding]
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.etag = createETagGenerator({ weak: false })
|
||||
|
||||
/**
|
||||
* Return weak ETag for `body`.
|
||||
*
|
||||
* @param {String|Buffer} body
|
||||
* @param {String} [encoding]
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.wetag = createETagGenerator({ weak: true })
|
||||
|
||||
/**
|
||||
* Check if `path` looks absolute.
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.isAbsolute = function(path){
|
||||
if ('/' === path[0]) return true;
|
||||
if (':' === path[1] && ('\\' === path[2] || '/' === path[2])) return true; // Windows device path
|
||||
if ('\\\\' === path.substring(0, 2)) return true; // Microsoft Azure absolute path
|
||||
};
|
||||
|
||||
/**
|
||||
* Flatten the given `arr`.
|
||||
*
|
||||
* @param {Array} arr
|
||||
* @return {Array}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.flatten = deprecate.function(flatten,
|
||||
'utils.flatten: use array-flatten npm module instead');
|
||||
|
||||
/**
|
||||
* Normalize the given `type`, for example "html" becomes "text/html".
|
||||
*
|
||||
* @param {String} type
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.normalizeType = function(type){
|
||||
return ~type.indexOf('/')
|
||||
? acceptParams(type)
|
||||
: { value: mime.lookup(type), params: {} };
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize `types`, for example "html" becomes "text/html".
|
||||
*
|
||||
* @param {Array} types
|
||||
* @return {Array}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.normalizeTypes = function(types){
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < types.length; ++i) {
|
||||
ret.push(exports.normalizeType(types[i]));
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate Content-Disposition header appropriate for the filename.
|
||||
* non-ascii filenames are urlencoded and a filename* parameter is added
|
||||
*
|
||||
* @param {String} filename
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.contentDisposition = deprecate.function(contentDisposition,
|
||||
'utils.contentDisposition: use content-disposition npm module instead');
|
||||
|
||||
/**
|
||||
* Parse accept params `str` returning an
|
||||
* object with `.value`, `.quality` and `.params`.
|
||||
* also includes `.originalIndex` for stable sorting
|
||||
*
|
||||
* @param {String} str
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function acceptParams(str, index) {
|
||||
var parts = str.split(/ *; */);
|
||||
var ret = { value: parts[0], quality: 1, params: {}, originalIndex: index };
|
||||
|
||||
for (var i = 1; i < parts.length; ++i) {
|
||||
var pms = parts[i].split(/ *= */);
|
||||
if ('q' === pms[0]) {
|
||||
ret.quality = parseFloat(pms[1]);
|
||||
} else {
|
||||
ret.params[pms[0]] = pms[1];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile "etag" value to function.
|
||||
*
|
||||
* @param {Boolean|String|Function} val
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.compileETag = function(val) {
|
||||
var fn;
|
||||
|
||||
if (typeof val === 'function') {
|
||||
return val;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case true:
|
||||
fn = exports.wetag;
|
||||
break;
|
||||
case false:
|
||||
break;
|
||||
case 'strong':
|
||||
fn = exports.etag;
|
||||
break;
|
||||
case 'weak':
|
||||
fn = exports.wetag;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError('unknown value for etag function: ' + val);
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile "query parser" value to function.
|
||||
*
|
||||
* @param {String|Function} val
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.compileQueryParser = function compileQueryParser(val) {
|
||||
var fn;
|
||||
|
||||
if (typeof val === 'function') {
|
||||
return val;
|
||||
}
|
||||
|
||||
switch (val) {
|
||||
case true:
|
||||
fn = querystring.parse;
|
||||
break;
|
||||
case false:
|
||||
fn = newObject;
|
||||
break;
|
||||
case 'extended':
|
||||
fn = parseExtendedQueryString;
|
||||
break;
|
||||
case 'simple':
|
||||
fn = querystring.parse;
|
||||
break;
|
||||
default:
|
||||
throw new TypeError('unknown value for query parser function: ' + val);
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile "proxy trust" value to function.
|
||||
*
|
||||
* @param {Boolean|String|Number|Array|Function} val
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.compileTrust = function(val) {
|
||||
if (typeof val === 'function') return val;
|
||||
|
||||
if (val === true) {
|
||||
// Support plain true/false
|
||||
return function(){ return true };
|
||||
}
|
||||
|
||||
if (typeof val === 'number') {
|
||||
// Support trusting hop count
|
||||
return function(a, i){ return i < val };
|
||||
}
|
||||
|
||||
if (typeof val === 'string') {
|
||||
// Support comma-separated values
|
||||
val = val.split(/ *, */);
|
||||
}
|
||||
|
||||
return proxyaddr.compile(val || []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the charset in a given Content-Type string.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {String} charset
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.setCharset = function setCharset(type, charset) {
|
||||
if (!type || !charset) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// parse type
|
||||
var parsed = contentType.parse(type);
|
||||
|
||||
// set charset
|
||||
parsed.parameters.charset = charset;
|
||||
|
||||
// format type
|
||||
return contentType.format(parsed);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an ETag generator function, generating ETags with
|
||||
* the given options.
|
||||
*
|
||||
* @param {object} options
|
||||
* @return {function}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function createETagGenerator (options) {
|
||||
return function generateETag (body, encoding) {
|
||||
var buf = !Buffer.isBuffer(body)
|
||||
? Buffer.from(body, encoding)
|
||||
: body
|
||||
|
||||
return etag(buf, options)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an extended query string with qs.
|
||||
*
|
||||
* @return {Object}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function parseExtendedQueryString(str) {
|
||||
return qs.parse(str, {
|
||||
allowPrototypes: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return new empty object.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function newObject() {
|
||||
return {};
|
||||
}
|
||||
Generated
Vendored
Executable
+182
@@ -0,0 +1,182 @@
|
||||
/*!
|
||||
* 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 debug = require('debug')('express:view');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var dirname = path.dirname;
|
||||
var basename = path.basename;
|
||||
var extname = path.extname;
|
||||
var join = path.join;
|
||||
var resolve = path.resolve;
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
module.exports = View;
|
||||
|
||||
/**
|
||||
* Initialize a new `View` with the given `name`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `defaultEngine` the default template engine name
|
||||
* - `engines` template engine require() cache
|
||||
* - `root` root path for view lookup
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {object} options
|
||||
* @public
|
||||
*/
|
||||
|
||||
function View(name, options) {
|
||||
var opts = options || {};
|
||||
|
||||
this.defaultEngine = opts.defaultEngine;
|
||||
this.ext = extname(name);
|
||||
this.name = name;
|
||||
this.root = opts.root;
|
||||
|
||||
if (!this.ext && !this.defaultEngine) {
|
||||
throw new Error('No default engine was specified and no extension was provided.');
|
||||
}
|
||||
|
||||
var fileName = name;
|
||||
|
||||
if (!this.ext) {
|
||||
// get extension from default engine name
|
||||
this.ext = this.defaultEngine[0] !== '.'
|
||||
? '.' + this.defaultEngine
|
||||
: this.defaultEngine;
|
||||
|
||||
fileName += this.ext;
|
||||
}
|
||||
|
||||
if (!opts.engines[this.ext]) {
|
||||
// load engine
|
||||
var mod = this.ext.substr(1)
|
||||
debug('require "%s"', mod)
|
||||
|
||||
// default engine export
|
||||
var fn = require(mod).__express
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error('Module "' + mod + '" does not provide a view engine.')
|
||||
}
|
||||
|
||||
opts.engines[this.ext] = fn
|
||||
}
|
||||
|
||||
// store loaded engine
|
||||
this.engine = opts.engines[this.ext];
|
||||
|
||||
// lookup path
|
||||
this.path = this.lookup(fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup view by the given `name`
|
||||
*
|
||||
* @param {string} name
|
||||
* @private
|
||||
*/
|
||||
|
||||
View.prototype.lookup = function lookup(name) {
|
||||
var path;
|
||||
var roots = [].concat(this.root);
|
||||
|
||||
debug('lookup "%s"', name);
|
||||
|
||||
for (var i = 0; i < roots.length && !path; i++) {
|
||||
var root = roots[i];
|
||||
|
||||
// resolve the path
|
||||
var loc = resolve(root, name);
|
||||
var dir = dirname(loc);
|
||||
var file = basename(loc);
|
||||
|
||||
// resolve the file
|
||||
path = this.resolve(dir, file);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render with the given options.
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {function} callback
|
||||
* @private
|
||||
*/
|
||||
|
||||
View.prototype.render = function render(options, callback) {
|
||||
debug('render "%s"', this.path);
|
||||
this.engine(this.path, options, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve the file within the given directory.
|
||||
*
|
||||
* @param {string} dir
|
||||
* @param {string} file
|
||||
* @private
|
||||
*/
|
||||
|
||||
View.prototype.resolve = function resolve(dir, file) {
|
||||
var ext = this.ext;
|
||||
|
||||
// <path>.<ext>
|
||||
var path = join(dir, file);
|
||||
var stat = tryStat(path);
|
||||
|
||||
if (stat && stat.isFile()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
// <path>/index.<ext>
|
||||
path = join(dir, basename(file, ext), 'index' + ext);
|
||||
stat = tryStat(path);
|
||||
|
||||
if (stat && stat.isFile()) {
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a stat, maybe.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {fs.Stats}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function tryStat(path) {
|
||||
debug('stat "%s"', path);
|
||||
|
||||
try {
|
||||
return fs.statSync(path);
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+118
@@ -0,0 +1,118 @@
|
||||
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
|
||||
Generated
Vendored
Executable
+24
@@ -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.
|
||||
|
||||
Generated
Vendored
Executable
+220
@@ -0,0 +1,220 @@
|
||||
# cookie
|
||||
|
||||
[![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]
|
||||
|
||||
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-6266-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 `ecodeURIComponent`, 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-6266-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-6266-5.3] states that if both `expires` and
|
||||
`magAge` are set, then `maxAge` takes precedence, but it is possiblke 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-6266-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-6266-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-6266-5.3] states that if both `expires` and
|
||||
`magAge` are set, then `maxAge` takes precedence, but it is possiblke 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-6266-5.2.4]. By default, the path
|
||||
is considered the ["default path"][rfc-6266-5.1.4]. By default, no maximum age 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.
|
||||
|
||||
##### sameSite
|
||||
|
||||
Specifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute][draft-west-first-party-cookies-07].
|
||||
|
||||
- `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.
|
||||
- `'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
|
||||
https://tools.ietf.org/html/draft-west-first-party-cookies-07#section-4.1.1
|
||||
|
||||
**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-6266-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
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 6266: HTTP State Management Mechanism][rfc-6266]
|
||||
- [Same-site Cookies][draft-west-first-party-cookies-07]
|
||||
|
||||
[draft-west-first-party-cookies-07]: https://tools.ietf.org/html/draft-west-first-party-cookies-07
|
||||
[rfc-6266]: https://tools.ietf.org/html/rfc6266
|
||||
[rfc-6266-5.1.4]: https://tools.ietf.org/html/rfc6266#section-5.1.4
|
||||
[rfc-6266-5.2.1]: https://tools.ietf.org/html/rfc6266#section-5.2.1
|
||||
[rfc-6266-5.2.2]: https://tools.ietf.org/html/rfc6266#section-5.2.2
|
||||
[rfc-6266-5.2.3]: https://tools.ietf.org/html/rfc6266#section-5.2.3
|
||||
[rfc-6266-5.2.4]: https://tools.ietf.org/html/rfc6266#section-5.2.4
|
||||
[rfc-6266-5.3]: https://tools.ietf.org/html/rfc6266#section-5.3
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/cookie.svg
|
||||
[npm-url]: https://npmjs.org/package/cookie
|
||||
[node-version-image]: https://img.shields.io/node/v/cookie.svg
|
||||
[node-version-url]: https://nodejs.org/en/download
|
||||
[travis-image]: https://img.shields.io/travis/jshttp/cookie/master.svg
|
||||
[travis-url]: https://travis-ci.org/jshttp/cookie
|
||||
[coveralls-image]: https://img.shields.io/coveralls/jshttp/cookie/master.svg
|
||||
[coveralls-url]: https://coveralls.io/r/jshttp/cookie?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/cookie.svg
|
||||
[downloads-url]: https://npmjs.org/package/cookie
|
||||
Generated
Vendored
Executable
+195
@@ -0,0 +1,195 @@
|
||||
/*!
|
||||
* 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+33
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "cookie",
|
||||
"description": "HTTP server cookie parsing and serialization",
|
||||
"version": "0.3.1",
|
||||
"author": "Roman Shtylman <shtylman@gmail.com>",
|
||||
"contributors": [
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"cookie",
|
||||
"cookies"
|
||||
],
|
||||
"repository": "jshttp/cookie",
|
||||
"devDependencies": {
|
||||
"istanbul": "0.4.3",
|
||||
"mocha": "1.21.5"
|
||||
},
|
||||
"files": [
|
||||
"HISTORY.md",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
},
|
||||
"scripts": {
|
||||
"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/"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+98
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"name": "express",
|
||||
"description": "Fast, unopinionated, minimalist web framework",
|
||||
"version": "4.16.4",
|
||||
"author": "TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"contributors": [
|
||||
"Aaron Heckmann <aaron.heckmann+github@gmail.com>",
|
||||
"Ciaran Jessup <ciaranj@gmail.com>",
|
||||
"Douglas Christopher Wilson <doug@somethingdoug.com>",
|
||||
"Guillermo Rauch <rauchg@gmail.com>",
|
||||
"Jonathan Ong <me@jongleberry.com>",
|
||||
"Roman Shtylman <shtylman+expressjs@gmail.com>",
|
||||
"Young Jae Sim <hanul@hanul.me>"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": "expressjs/express",
|
||||
"homepage": "http://expressjs.com/",
|
||||
"keywords": [
|
||||
"express",
|
||||
"framework",
|
||||
"sinatra",
|
||||
"web",
|
||||
"rest",
|
||||
"restful",
|
||||
"router",
|
||||
"app",
|
||||
"api"
|
||||
],
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.5",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.18.3",
|
||||
"content-disposition": "0.5.2",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.3.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.1.1",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.2",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.4",
|
||||
"qs": "6.5.2",
|
||||
"range-parser": "~1.2.0",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.16.2",
|
||||
"serve-static": "1.13.2",
|
||||
"setprototypeof": "1.1.0",
|
||||
"statuses": "~1.4.0",
|
||||
"type-is": "~1.6.16",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"after": "0.8.2",
|
||||
"connect-redis": "3.4.0",
|
||||
"cookie-parser": "~1.4.3",
|
||||
"cookie-session": "1.3.2",
|
||||
"ejs": "2.6.1",
|
||||
"eslint": "2.13.1",
|
||||
"express-session": "1.15.6",
|
||||
"hbs": "4.0.1",
|
||||
"istanbul": "0.4.5",
|
||||
"marked": "0.5.1",
|
||||
"method-override": "3.0.0",
|
||||
"mocha": "5.2.0",
|
||||
"morgan": "1.9.1",
|
||||
"multiparty": "4.2.1",
|
||||
"pbkdf2-password": "1.2.1",
|
||||
"should": "13.2.3",
|
||||
"supertest": "3.3.0",
|
||||
"vhost": "~3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"History.md",
|
||||
"Readme.md",
|
||||
"index.js",
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "mocha --require test/support/env --reporter spec --bail --check-leaks test/ test/acceptance/",
|
||||
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --require test/support/env --reporter spec --check-leaks test/ test/acceptance/",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --require test/support/env --reporter dot --check-leaks test/ test/acceptance/",
|
||||
"test-tap": "mocha --require test/support/env --reporter tap --check-leaks test/ test/acceptance/"
|
||||
}
|
||||
}
|
||||
Generated
Vendored
Executable
+66
@@ -0,0 +1,66 @@
|
||||
/// <reference types="node"/>
|
||||
import * as fs from 'fs';
|
||||
|
||||
declare namespace makeDir {
|
||||
interface Options {
|
||||
/**
|
||||
Directory [permissions](https://x-team.com/blog/file-system-permissions-umask-node-js/).
|
||||
|
||||
@default 0o777
|
||||
*/
|
||||
readonly mode?: number;
|
||||
|
||||
/**
|
||||
Use a custom `fs` implementation. For example [`graceful-fs`](https://github.com/isaacs/node-graceful-fs).
|
||||
|
||||
Using a custom `fs` implementation will block the use of the native `recursive` option if `fs.mkdir` or `fs.mkdirSync` is not the native function.
|
||||
|
||||
@default require('fs')
|
||||
*/
|
||||
readonly fs?: typeof fs;
|
||||
}
|
||||
}
|
||||
|
||||
declare const makeDir: {
|
||||
/**
|
||||
Make a directory and its parents if needed - Think `mkdir -p`.
|
||||
|
||||
@param path - Directory to create.
|
||||
@returns The path to the created directory.
|
||||
|
||||
@example
|
||||
```
|
||||
import makeDir = require('make-dir');
|
||||
|
||||
(async () => {
|
||||
const path = await makeDir('unicorn/rainbow/cake');
|
||||
|
||||
console.log(path);
|
||||
//=> '/Users/sindresorhus/fun/unicorn/rainbow/cake'
|
||||
|
||||
// Multiple directories:
|
||||
const paths = await Promise.all([
|
||||
makeDir('unicorn/rainbow'),
|
||||
makeDir('foo/bar')
|
||||
]);
|
||||
|
||||
console.log(paths);
|
||||
// [
|
||||
// '/Users/sindresorhus/fun/unicorn/rainbow',
|
||||
// '/Users/sindresorhus/fun/foo/bar'
|
||||
// ]
|
||||
})();
|
||||
```
|
||||
*/
|
||||
(path: string, options?: makeDir.Options): Promise<string>;
|
||||
|
||||
/**
|
||||
Synchronously make a directory and its parents if needed - Think `mkdir -p`.
|
||||
|
||||
@param path - Directory to create.
|
||||
@returns The path to the created directory.
|
||||
*/
|
||||
sync(path: string, options?: makeDir.Options): string;
|
||||
};
|
||||
|
||||
export = makeDir;
|
||||
Generated
Vendored
Executable
+156
@@ -0,0 +1,156 @@
|
||||
'use strict';
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const {promisify} = require('util');
|
||||
const semver = require('semver');
|
||||
|
||||
const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0');
|
||||
|
||||
// https://github.com/nodejs/node/issues/8987
|
||||
// https://github.com/libuv/libuv/pull/1088
|
||||
const checkPath = pth => {
|
||||
if (process.platform === 'win32') {
|
||||
const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ''));
|
||||
|
||||
if (pathHasInvalidWinCharacters) {
|
||||
const error = new Error(`Path contains invalid characters: ${pth}`);
|
||||
error.code = 'EINVAL';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const processOptions = options => {
|
||||
// https://github.com/sindresorhus/make-dir/issues/18
|
||||
const defaults = {
|
||||
mode: 0o777,
|
||||
fs
|
||||
};
|
||||
|
||||
return {
|
||||
...defaults,
|
||||
...options
|
||||
};
|
||||
};
|
||||
|
||||
const permissionError = pth => {
|
||||
// This replicates the exception of `fs.mkdir` with native the
|
||||
// `recusive` option when run on an invalid drive under Windows.
|
||||
const error = new Error(`operation not permitted, mkdir '${pth}'`);
|
||||
error.code = 'EPERM';
|
||||
error.errno = -4048;
|
||||
error.path = pth;
|
||||
error.syscall = 'mkdir';
|
||||
return error;
|
||||
};
|
||||
|
||||
const makeDir = async (input, options) => {
|
||||
checkPath(input);
|
||||
options = processOptions(options);
|
||||
|
||||
const mkdir = promisify(options.fs.mkdir);
|
||||
const stat = promisify(options.fs.stat);
|
||||
|
||||
if (useNativeRecursiveOption && options.fs.mkdir === fs.mkdir) {
|
||||
const pth = path.resolve(input);
|
||||
|
||||
await mkdir(pth, {
|
||||
mode: options.mode,
|
||||
recursive: true
|
||||
});
|
||||
|
||||
return pth;
|
||||
}
|
||||
|
||||
const make = async pth => {
|
||||
try {
|
||||
await mkdir(pth, options.mode);
|
||||
|
||||
return pth;
|
||||
} catch (error) {
|
||||
if (error.code === 'EPERM') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (error.code === 'ENOENT') {
|
||||
if (path.dirname(pth) === pth) {
|
||||
throw permissionError(pth);
|
||||
}
|
||||
|
||||
if (error.message.includes('null bytes')) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
await make(path.dirname(pth));
|
||||
|
||||
return make(pth);
|
||||
}
|
||||
|
||||
try {
|
||||
const stats = await stat(pth);
|
||||
if (!stats.isDirectory()) {
|
||||
throw new Error('The path is not a directory');
|
||||
}
|
||||
} catch (_) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return pth;
|
||||
}
|
||||
};
|
||||
|
||||
return make(path.resolve(input));
|
||||
};
|
||||
|
||||
module.exports = makeDir;
|
||||
|
||||
module.exports.sync = (input, options) => {
|
||||
checkPath(input);
|
||||
options = processOptions(options);
|
||||
|
||||
if (useNativeRecursiveOption && options.fs.mkdirSync === fs.mkdirSync) {
|
||||
const pth = path.resolve(input);
|
||||
|
||||
fs.mkdirSync(pth, {
|
||||
mode: options.mode,
|
||||
recursive: true
|
||||
});
|
||||
|
||||
return pth;
|
||||
}
|
||||
|
||||
const make = pth => {
|
||||
try {
|
||||
options.fs.mkdirSync(pth, options.mode);
|
||||
} catch (error) {
|
||||
if (error.code === 'EPERM') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (error.code === 'ENOENT') {
|
||||
if (path.dirname(pth) === pth) {
|
||||
throw permissionError(pth);
|
||||
}
|
||||
|
||||
if (error.message.includes('null bytes')) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
make(path.dirname(pth));
|
||||
return make(pth);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!options.fs.statSync(pth).isDirectory()) {
|
||||
throw new Error('The path is not a directory');
|
||||
}
|
||||
} catch (_) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return pth;
|
||||
};
|
||||
|
||||
return make(path.resolve(input));
|
||||
};
|
||||
Generated
Vendored
Executable
+9
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.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.
|
||||
Generated
Vendored
Symlink
+1
@@ -0,0 +1 @@
|
||||
../semver/bin/semver.js
|
||||
Generated
Vendored
Executable
+70
@@ -0,0 +1,70 @@
|
||||
# changes log
|
||||
|
||||
## 6.2.0
|
||||
|
||||
* Coerce numbers to strings when passed to semver.coerce()
|
||||
* Add `rtl` option to coerce from right to left
|
||||
|
||||
## 6.1.3
|
||||
|
||||
* Handle X-ranges properly in includePrerelease mode
|
||||
|
||||
## 6.1.2
|
||||
|
||||
* Do not throw when testing invalid version strings
|
||||
|
||||
## 6.1.1
|
||||
|
||||
* Add options support for semver.coerce()
|
||||
* Handle undefined version passed to Range.test
|
||||
|
||||
## 6.1.0
|
||||
|
||||
* Add semver.compareBuild function
|
||||
* Support `*` in semver.intersects
|
||||
|
||||
## 6.0
|
||||
|
||||
* Fix `intersects` logic.
|
||||
|
||||
This is technically a bug fix, but since it is also a change to behavior
|
||||
that may require users updating their code, it is marked as a major
|
||||
version increment.
|
||||
|
||||
## 5.7
|
||||
|
||||
* Add `minVersion` method
|
||||
|
||||
## 5.6
|
||||
|
||||
* Move boolean `loose` param to an options object, with
|
||||
backwards-compatibility protection.
|
||||
* Add ability to opt out of special prerelease version handling with
|
||||
the `includePrerelease` option flag.
|
||||
|
||||
## 5.5
|
||||
|
||||
* Add version coercion capabilities
|
||||
|
||||
## 5.4
|
||||
|
||||
* Add intersection checking
|
||||
|
||||
## 5.3
|
||||
|
||||
* Add `minSatisfying` method
|
||||
|
||||
## 5.2
|
||||
|
||||
* Add `prerelease(v)` that returns prerelease components
|
||||
|
||||
## 5.1
|
||||
|
||||
* Add Backus-Naur for ranges
|
||||
* Remove excessively cute inspection methods
|
||||
|
||||
## 5.0
|
||||
|
||||
* Remove AMD/Browserified build artifacts
|
||||
* Fix ltr and gtr when using the `*` range
|
||||
* Fix for range `*` with a prerelease identifier
|
||||
Generated
Vendored
Executable
+15
@@ -0,0 +1,15 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
Generated
Vendored
Executable
+443
@@ -0,0 +1,443 @@
|
||||
semver(1) -- The semantic versioner for npm
|
||||
===========================================
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install semver
|
||||
````
|
||||
|
||||
## Usage
|
||||
|
||||
As a node module:
|
||||
|
||||
```js
|
||||
const semver = require('semver')
|
||||
|
||||
semver.valid('1.2.3') // '1.2.3'
|
||||
semver.valid('a.b.c') // null
|
||||
semver.clean(' =v1.2.3 ') // '1.2.3'
|
||||
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
|
||||
semver.gt('1.2.3', '9.8.7') // false
|
||||
semver.lt('1.2.3', '9.8.7') // true
|
||||
semver.minVersion('>=1.0.0') // '1.0.0'
|
||||
semver.valid(semver.coerce('v2')) // '2.0.0'
|
||||
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
|
||||
```
|
||||
|
||||
As a command-line utility:
|
||||
|
||||
```
|
||||
$ semver -h
|
||||
|
||||
A JavaScript implementation of the https://semver.org/ specification
|
||||
Copyright Isaac Z. Schlueter
|
||||
|
||||
Usage: semver [options] <version> [<version> [...]]
|
||||
Prints valid versions sorted by SemVer precedence
|
||||
|
||||
Options:
|
||||
-r --range <range>
|
||||
Print versions that match the specified range.
|
||||
|
||||
-i --increment [<level>]
|
||||
Increment a version by the specified level. Level can
|
||||
be one of: major, minor, patch, premajor, preminor,
|
||||
prepatch, or prerelease. Default level is 'patch'.
|
||||
Only one version may be specified.
|
||||
|
||||
--preid <identifier>
|
||||
Identifier to be used to prefix premajor, preminor,
|
||||
prepatch or prerelease version increments.
|
||||
|
||||
-l --loose
|
||||
Interpret versions and ranges loosely
|
||||
|
||||
-p --include-prerelease
|
||||
Always include prerelease versions in range matching
|
||||
|
||||
-c --coerce
|
||||
Coerce a string into SemVer if possible
|
||||
(does not imply --loose)
|
||||
|
||||
--rtl
|
||||
Coerce version strings right to left
|
||||
|
||||
--ltr
|
||||
Coerce version strings left to right (default)
|
||||
|
||||
Program exits successfully if any valid version satisfies
|
||||
all supplied ranges, and prints all satisfying versions.
|
||||
|
||||
If no satisfying versions are found, then exits failure.
|
||||
|
||||
Versions are printed in ascending order, so supplying
|
||||
multiple versions to the utility will just sort them.
|
||||
```
|
||||
|
||||
## Versions
|
||||
|
||||
A "version" is described by the `v2.0.0` specification found at
|
||||
<https://semver.org/>.
|
||||
|
||||
A leading `"="` or `"v"` character is stripped off and ignored.
|
||||
|
||||
## Ranges
|
||||
|
||||
A `version range` is a set of `comparators` which specify versions
|
||||
that satisfy the range.
|
||||
|
||||
A `comparator` is composed of an `operator` and a `version`. The set
|
||||
of primitive `operators` is:
|
||||
|
||||
* `<` Less than
|
||||
* `<=` Less than or equal to
|
||||
* `>` Greater than
|
||||
* `>=` Greater than or equal to
|
||||
* `=` Equal. If no operator is specified, then equality is assumed,
|
||||
so this operator is optional, but MAY be included.
|
||||
|
||||
For example, the comparator `>=1.2.7` would match the versions
|
||||
`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
|
||||
or `1.1.0`.
|
||||
|
||||
Comparators can be joined by whitespace to form a `comparator set`,
|
||||
which is satisfied by the **intersection** of all of the comparators
|
||||
it includes.
|
||||
|
||||
A range is composed of one or more comparator sets, joined by `||`. A
|
||||
version matches a range if and only if every comparator in at least
|
||||
one of the `||`-separated comparator sets is satisfied by the version.
|
||||
|
||||
For example, the range `>=1.2.7 <1.3.0` would match the versions
|
||||
`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`,
|
||||
or `1.1.0`.
|
||||
|
||||
The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`,
|
||||
`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`.
|
||||
|
||||
### Prerelease Tags
|
||||
|
||||
If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then
|
||||
it will only be allowed to satisfy comparator sets if at least one
|
||||
comparator with the same `[major, minor, patch]` tuple also has a
|
||||
prerelease tag.
|
||||
|
||||
For example, the range `>1.2.3-alpha.3` would be allowed to match the
|
||||
version `1.2.3-alpha.7`, but it would *not* be satisfied by
|
||||
`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
|
||||
than" `1.2.3-alpha.3` according to the SemVer sort rules. The version
|
||||
range only accepts prerelease tags on the `1.2.3` version. The
|
||||
version `3.4.5` *would* satisfy the range, because it does not have a
|
||||
prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
|
||||
|
||||
The purpose for this behavior is twofold. First, prerelease versions
|
||||
frequently are updated very quickly, and contain many breaking changes
|
||||
that are (by the author's design) not yet fit for public consumption.
|
||||
Therefore, by default, they are excluded from range matching
|
||||
semantics.
|
||||
|
||||
Second, a user who has opted into using a prerelease version has
|
||||
clearly indicated the intent to use *that specific* set of
|
||||
alpha/beta/rc versions. By including a prerelease tag in the range,
|
||||
the user is indicating that they are aware of the risk. However, it
|
||||
is still not appropriate to assume that they have opted into taking a
|
||||
similar risk on the *next* set of prerelease versions.
|
||||
|
||||
Note that this behavior can be suppressed (treating all prerelease
|
||||
versions as if they were normal versions, for the purpose of range
|
||||
matching) by setting the `includePrerelease` flag on the options
|
||||
object to any
|
||||
[functions](https://github.com/npm/node-semver#functions) that do
|
||||
range matching.
|
||||
|
||||
#### Prerelease Identifiers
|
||||
|
||||
The method `.inc` takes an additional `identifier` string argument that
|
||||
will append the value of the string as a prerelease identifier:
|
||||
|
||||
```javascript
|
||||
semver.inc('1.2.3', 'prerelease', 'beta')
|
||||
// '1.2.4-beta.0'
|
||||
```
|
||||
|
||||
command-line example:
|
||||
|
||||
```bash
|
||||
$ semver 1.2.3 -i prerelease --preid beta
|
||||
1.2.4-beta.0
|
||||
```
|
||||
|
||||
Which then can be used to increment further:
|
||||
|
||||
```bash
|
||||
$ semver 1.2.4-beta.0 -i prerelease
|
||||
1.2.4-beta.1
|
||||
```
|
||||
|
||||
### Advanced Range Syntax
|
||||
|
||||
Advanced range syntax desugars to primitive comparators in
|
||||
deterministic ways.
|
||||
|
||||
Advanced ranges may be combined in the same way as primitive
|
||||
comparators using white space or `||`.
|
||||
|
||||
#### Hyphen Ranges `X.Y.Z - A.B.C`
|
||||
|
||||
Specifies an inclusive set.
|
||||
|
||||
* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4`
|
||||
|
||||
If a partial version is provided as the first version in the inclusive
|
||||
range, then the missing pieces are replaced with zeroes.
|
||||
|
||||
* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4`
|
||||
|
||||
If a partial version is provided as the second version in the
|
||||
inclusive range, then all versions that start with the supplied parts
|
||||
of the tuple are accepted, but nothing that would be greater than the
|
||||
provided tuple parts.
|
||||
|
||||
* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0`
|
||||
* `1.2.3 - 2` := `>=1.2.3 <3.0.0`
|
||||
|
||||
#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
|
||||
|
||||
Any of `X`, `x`, or `*` may be used to "stand in" for one of the
|
||||
numeric values in the `[major, minor, patch]` tuple.
|
||||
|
||||
* `*` := `>=0.0.0` (Any version satisfies)
|
||||
* `1.x` := `>=1.0.0 <2.0.0` (Matching major version)
|
||||
* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions)
|
||||
|
||||
A partial version range is treated as an X-Range, so the special
|
||||
character is in fact optional.
|
||||
|
||||
* `""` (empty string) := `*` := `>=0.0.0`
|
||||
* `1` := `1.x.x` := `>=1.0.0 <2.0.0`
|
||||
* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0`
|
||||
|
||||
#### Tilde Ranges `~1.2.3` `~1.2` `~1`
|
||||
|
||||
Allows patch-level changes if a minor version is specified on the
|
||||
comparator. Allows minor-level changes if not.
|
||||
|
||||
* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0`
|
||||
* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`)
|
||||
* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`)
|
||||
* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0`
|
||||
* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`)
|
||||
* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`)
|
||||
* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in
|
||||
the `1.2.3` version will be allowed, if they are greater than or
|
||||
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
||||
`1.2.4-beta.2` would not, because it is a prerelease of a
|
||||
different `[major, minor, patch]` tuple.
|
||||
|
||||
#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4`
|
||||
|
||||
Allows changes that do not modify the left-most non-zero element in the
|
||||
`[major, minor, patch]` tuple. In other words, this allows patch and
|
||||
minor updates for versions `1.0.0` and above, patch updates for
|
||||
versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`.
|
||||
|
||||
Many authors treat a `0.x` version as if the `x` were the major
|
||||
"breaking-change" indicator.
|
||||
|
||||
Caret ranges are ideal when an author may make breaking changes
|
||||
between `0.2.4` and `0.3.0` releases, which is a common practice.
|
||||
However, it presumes that there will *not* be breaking changes between
|
||||
`0.2.4` and `0.2.5`. It allows for changes that are presumed to be
|
||||
additive (but non-breaking), according to commonly observed practices.
|
||||
|
||||
* `^1.2.3` := `>=1.2.3 <2.0.0`
|
||||
* `^0.2.3` := `>=0.2.3 <0.3.0`
|
||||
* `^0.0.3` := `>=0.0.3 <0.0.4`
|
||||
* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in
|
||||
the `1.2.3` version will be allowed, if they are greater than or
|
||||
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
||||
`1.2.4-beta.2` would not, because it is a prerelease of a
|
||||
different `[major, minor, patch]` tuple.
|
||||
* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the
|
||||
`0.0.3` version *only* will be allowed, if they are greater than or
|
||||
equal to `beta`. So, `0.0.3-pr.2` would be allowed.
|
||||
|
||||
When parsing caret ranges, a missing `patch` value desugars to the
|
||||
number `0`, but will allow flexibility within that value, even if the
|
||||
major and minor versions are both `0`.
|
||||
|
||||
* `^1.2.x` := `>=1.2.0 <2.0.0`
|
||||
* `^0.0.x` := `>=0.0.0 <0.1.0`
|
||||
* `^0.0` := `>=0.0.0 <0.1.0`
|
||||
|
||||
A missing `minor` and `patch` values will desugar to zero, but also
|
||||
allow flexibility within those values, even if the major version is
|
||||
zero.
|
||||
|
||||
* `^1.x` := `>=1.0.0 <2.0.0`
|
||||
* `^0.x` := `>=0.0.0 <1.0.0`
|
||||
|
||||
### Range Grammar
|
||||
|
||||
Putting all this together, here is a Backus-Naur grammar for ranges,
|
||||
for the benefit of parser authors:
|
||||
|
||||
```bnf
|
||||
range-set ::= range ( logical-or range ) *
|
||||
logical-or ::= ( ' ' ) * '||' ( ' ' ) *
|
||||
range ::= hyphen | simple ( ' ' simple ) * | ''
|
||||
hyphen ::= partial ' - ' partial
|
||||
simple ::= primitive | partial | tilde | caret
|
||||
primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
|
||||
partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )?
|
||||
xr ::= 'x' | 'X' | '*' | nr
|
||||
nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
|
||||
tilde ::= '~' partial
|
||||
caret ::= '^' partial
|
||||
qualifier ::= ( '-' pre )? ( '+' build )?
|
||||
pre ::= parts
|
||||
build ::= parts
|
||||
parts ::= part ( '.' part ) *
|
||||
part ::= nr | [-0-9A-Za-z]+
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
All methods and classes take a final `options` object argument. All
|
||||
options in this object are `false` by default. The options supported
|
||||
are:
|
||||
|
||||
- `loose` Be more forgiving about not-quite-valid semver strings.
|
||||
(Any resulting output will always be 100% strict compliant, of
|
||||
course.) For backwards compatibility reasons, if the `options`
|
||||
argument is a boolean value instead of an object, it is interpreted
|
||||
to be the `loose` param.
|
||||
- `includePrerelease` Set to suppress the [default
|
||||
behavior](https://github.com/npm/node-semver#prerelease-tags) of
|
||||
excluding prerelease tagged versions from ranges unless they are
|
||||
explicitly opted into.
|
||||
|
||||
Strict-mode Comparators and Ranges will be strict about the SemVer
|
||||
strings that they parse.
|
||||
|
||||
* `valid(v)`: Return the parsed version, or null if it's not valid.
|
||||
* `inc(v, release)`: Return the version incremented by the release
|
||||
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
|
||||
`prepatch`, or `prerelease`), or null if it's not valid
|
||||
* `premajor` in one call will bump the version up to the next major
|
||||
version and down to a prerelease of that major version.
|
||||
`preminor`, and `prepatch` work the same way.
|
||||
* If called from a non-prerelease version, the `prerelease` will work the
|
||||
same as `prepatch`. It increments the patch version, then makes a
|
||||
prerelease. If the input version is already a prerelease it simply
|
||||
increments it.
|
||||
* `prerelease(v)`: Returns an array of prerelease components, or null
|
||||
if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
|
||||
* `major(v)`: Return the major version number.
|
||||
* `minor(v)`: Return the minor version number.
|
||||
* `patch(v)`: Return the patch version number.
|
||||
* `intersects(r1, r2, loose)`: Return true if the two supplied ranges
|
||||
or comparators intersect.
|
||||
* `parse(v)`: Attempt to parse a string as a semantic version, returning either
|
||||
a `SemVer` object or `null`.
|
||||
|
||||
### Comparison
|
||||
|
||||
* `gt(v1, v2)`: `v1 > v2`
|
||||
* `gte(v1, v2)`: `v1 >= v2`
|
||||
* `lt(v1, v2)`: `v1 < v2`
|
||||
* `lte(v1, v2)`: `v1 <= v2`
|
||||
* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
|
||||
even if they're not the exact same string. You already know how to
|
||||
compare strings.
|
||||
* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
|
||||
* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
|
||||
the corresponding function above. `"==="` and `"!=="` do simple
|
||||
string comparison, but are included for completeness. Throws if an
|
||||
invalid comparison string is provided.
|
||||
* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
|
||||
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
|
||||
* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions
|
||||
in descending order when passed to `Array.sort()`.
|
||||
* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions
|
||||
are equal. Sorts in ascending order if passed to `Array.sort()`.
|
||||
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
|
||||
* `diff(v1, v2)`: Returns difference between two versions by the release type
|
||||
(`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
|
||||
or null if the versions are the same.
|
||||
|
||||
### Comparators
|
||||
|
||||
* `intersects(comparator)`: Return true if the comparators intersect
|
||||
|
||||
### Ranges
|
||||
|
||||
* `validRange(range)`: Return the valid range or null if it's not valid
|
||||
* `satisfies(version, range)`: Return true if the version satisfies the
|
||||
range.
|
||||
* `maxSatisfying(versions, range)`: Return the highest version in the list
|
||||
that satisfies the range, or `null` if none of them do.
|
||||
* `minSatisfying(versions, range)`: Return the lowest version in the list
|
||||
that satisfies the range, or `null` if none of them do.
|
||||
* `minVersion(range)`: Return the lowest version that can possibly match
|
||||
the given range.
|
||||
* `gtr(version, range)`: Return `true` if version is greater than all the
|
||||
versions possible in the range.
|
||||
* `ltr(version, range)`: Return `true` if version is less than all the
|
||||
versions possible in the range.
|
||||
* `outside(version, range, hilo)`: Return true if the version is outside
|
||||
the bounds of the range in either the high or low direction. The
|
||||
`hilo` argument must be either the string `'>'` or `'<'`. (This is
|
||||
the function called by `gtr` and `ltr`.)
|
||||
* `intersects(range)`: Return true if any of the ranges comparators intersect
|
||||
|
||||
Note that, since ranges may be non-contiguous, a version might not be
|
||||
greater than a range, less than a range, *or* satisfy a range! For
|
||||
example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
|
||||
until `2.0.0`, so the version `1.2.10` would not be greater than the
|
||||
range (because `2.0.1` satisfies, which is higher), nor less than the
|
||||
range (since `1.2.8` satisfies, which is lower), and it also does not
|
||||
satisfy the range.
|
||||
|
||||
If you want to know if a version satisfies or does not satisfy a
|
||||
range, use the `satisfies(version, range)` function.
|
||||
|
||||
### Coercion
|
||||
|
||||
* `coerce(version, options)`: Coerces a string to semver if possible
|
||||
|
||||
This aims to provide a very forgiving translation of a non-semver string to
|
||||
semver. It looks for the first digit in a string, and consumes all
|
||||
remaining characters which satisfy at least a partial semver (e.g., `1`,
|
||||
`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
|
||||
versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
|
||||
surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
|
||||
`3.4.0`). Only text which lacks digits will fail coercion (`version one`
|
||||
is not valid). The maximum length for any semver component considered for
|
||||
coercion is 16 characters; longer components will be ignored
|
||||
(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
|
||||
semver component is `Integer.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
|
||||
components are invalid (`9999999999999999.4.7.4` is likely invalid).
|
||||
|
||||
If the `options.rtl` flag is set, then `coerce` will return the right-most
|
||||
coercible tuple that does not share an ending index with a longer coercible
|
||||
tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not
|
||||
`4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of
|
||||
any other overlapping SemVer tuple.
|
||||
|
||||
### Clean
|
||||
|
||||
* `clean(version)`: Clean a string to be a valid semver if possible
|
||||
|
||||
This will return a cleaned and trimmed semver version. If the provided version is not valid a null will be returned. This does not work for ranges.
|
||||
|
||||
ex.
|
||||
* `s.clean(' = v 2.1.5foo')`: `null`
|
||||
* `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'`
|
||||
* `s.clean(' = v 2.1.5-foo')`: `null`
|
||||
* `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'`
|
||||
* `s.clean('=v2.1.5')`: `'2.1.5'`
|
||||
* `s.clean(' =v2.1.5')`: `2.1.5`
|
||||
* `s.clean(' 2.1.5 ')`: `'2.1.5'`
|
||||
* `s.clean('~1.0.0')`: `null`
|
||||
Generated
Vendored
Executable
+174
@@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env node
|
||||
// Standalone semver comparison program.
|
||||
// Exits successfully and prints matching version(s) if
|
||||
// any supplied version is valid and passes all tests.
|
||||
|
||||
var argv = process.argv.slice(2)
|
||||
|
||||
var versions = []
|
||||
|
||||
var range = []
|
||||
|
||||
var inc = null
|
||||
|
||||
var version = require('../package.json').version
|
||||
|
||||
var loose = false
|
||||
|
||||
var includePrerelease = false
|
||||
|
||||
var coerce = false
|
||||
|
||||
var rtl = false
|
||||
|
||||
var identifier
|
||||
|
||||
var semver = require('../semver')
|
||||
|
||||
var reverse = false
|
||||
|
||||
var options = {}
|
||||
|
||||
main()
|
||||
|
||||
function main () {
|
||||
if (!argv.length) return help()
|
||||
while (argv.length) {
|
||||
var a = argv.shift()
|
||||
var indexOfEqualSign = a.indexOf('=')
|
||||
if (indexOfEqualSign !== -1) {
|
||||
a = a.slice(0, indexOfEqualSign)
|
||||
argv.unshift(a.slice(indexOfEqualSign + 1))
|
||||
}
|
||||
switch (a) {
|
||||
case '-rv': case '-rev': case '--rev': case '--reverse':
|
||||
reverse = true
|
||||
break
|
||||
case '-l': case '--loose':
|
||||
loose = true
|
||||
break
|
||||
case '-p': case '--include-prerelease':
|
||||
includePrerelease = true
|
||||
break
|
||||
case '-v': case '--version':
|
||||
versions.push(argv.shift())
|
||||
break
|
||||
case '-i': case '--inc': case '--increment':
|
||||
switch (argv[0]) {
|
||||
case 'major': case 'minor': case 'patch': case 'prerelease':
|
||||
case 'premajor': case 'preminor': case 'prepatch':
|
||||
inc = argv.shift()
|
||||
break
|
||||
default:
|
||||
inc = 'patch'
|
||||
break
|
||||
}
|
||||
break
|
||||
case '--preid':
|
||||
identifier = argv.shift()
|
||||
break
|
||||
case '-r': case '--range':
|
||||
range.push(argv.shift())
|
||||
break
|
||||
case '-c': case '--coerce':
|
||||
coerce = true
|
||||
break
|
||||
case '--rtl':
|
||||
rtl = true
|
||||
break
|
||||
case '--ltr':
|
||||
rtl = false
|
||||
break
|
||||
case '-h': case '--help': case '-?':
|
||||
return help()
|
||||
default:
|
||||
versions.push(a)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl }
|
||||
|
||||
versions = versions.map(function (v) {
|
||||
return coerce ? (semver.coerce(v, options) || { version: v }).version : v
|
||||
}).filter(function (v) {
|
||||
return semver.valid(v)
|
||||
})
|
||||
if (!versions.length) return fail()
|
||||
if (inc && (versions.length !== 1 || range.length)) { return failInc() }
|
||||
|
||||
for (var i = 0, l = range.length; i < l; i++) {
|
||||
versions = versions.filter(function (v) {
|
||||
return semver.satisfies(v, range[i], options)
|
||||
})
|
||||
if (!versions.length) return fail()
|
||||
}
|
||||
return success(versions)
|
||||
}
|
||||
|
||||
function failInc () {
|
||||
console.error('--inc can only be used on a single version with no range')
|
||||
fail()
|
||||
}
|
||||
|
||||
function fail () { process.exit(1) }
|
||||
|
||||
function success () {
|
||||
var compare = reverse ? 'rcompare' : 'compare'
|
||||
versions.sort(function (a, b) {
|
||||
return semver[compare](a, b, options)
|
||||
}).map(function (v) {
|
||||
return semver.clean(v, options)
|
||||
}).map(function (v) {
|
||||
return inc ? semver.inc(v, inc, options, identifier) : v
|
||||
}).forEach(function (v, i, _) { console.log(v) })
|
||||
}
|
||||
|
||||
function help () {
|
||||
console.log(['SemVer ' + version,
|
||||
'',
|
||||
'A JavaScript implementation of the https://semver.org/ specification',
|
||||
'Copyright Isaac Z. Schlueter',
|
||||
'',
|
||||
'Usage: semver [options] <version> [<version> [...]]',
|
||||
'Prints valid versions sorted by SemVer precedence',
|
||||
'',
|
||||
'Options:',
|
||||
'-r --range <range>',
|
||||
' Print versions that match the specified range.',
|
||||
'',
|
||||
'-i --increment [<level>]',
|
||||
' Increment a version by the specified level. Level can',
|
||||
' be one of: major, minor, patch, premajor, preminor,',
|
||||
" prepatch, or prerelease. Default level is 'patch'.",
|
||||
' Only one version may be specified.',
|
||||
'',
|
||||
'--preid <identifier>',
|
||||
' Identifier to be used to prefix premajor, preminor,',
|
||||
' prepatch or prerelease version increments.',
|
||||
'',
|
||||
'-l --loose',
|
||||
' Interpret versions and ranges loosely',
|
||||
'',
|
||||
'-p --include-prerelease',
|
||||
' Always include prerelease versions in range matching',
|
||||
'',
|
||||
'-c --coerce',
|
||||
' Coerce a string into SemVer if possible',
|
||||
' (does not imply --loose)',
|
||||
'',
|
||||
'--rtl',
|
||||
' Coerce version strings right to left',
|
||||
'',
|
||||
'--ltr',
|
||||
' Coerce version strings left to right (default)',
|
||||
'',
|
||||
'Program exits successfully if any valid version satisfies',
|
||||
'all supplied ranges, and prints all satisfying versions.',
|
||||
'',
|
||||
'If no satisfying versions are found, then exits failure.',
|
||||
'',
|
||||
'Versions are printed in ascending order, so supplying',
|
||||
'multiple versions to the utility will just sort them.'
|
||||
].join('\n'))
|
||||
}
|
||||
Generated
Vendored
Executable
+28
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "semver",
|
||||
"version": "6.3.0",
|
||||
"description": "The semantic version parser used by npm.",
|
||||
"main": "semver.js",
|
||||
"scripts": {
|
||||
"test": "tap",
|
||||
"preversion": "npm test",
|
||||
"postversion": "npm publish",
|
||||
"postpublish": "git push origin --follow-tags"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^14.3.1"
|
||||
},
|
||||
"license": "ISC",
|
||||
"repository": "https://github.com/npm/node-semver",
|
||||
"bin": {
|
||||
"semver": "./bin/semver.js"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"range.bnf",
|
||||
"semver.js"
|
||||
],
|
||||
"tap": {
|
||||
"check-coverage": true
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user