Comparing version 2.14.1 to 3.0.0-alpha.0
'use strict'; | ||
'use strict' | ||
@@ -8,20 +8,31 @@ /** | ||
const isGeneratorFunction = require('is-generator-function'); | ||
const debug = require('debug')('koa:application'); | ||
const onFinished = require('on-finished'); | ||
const assert = require('assert'); | ||
const response = require('./response'); | ||
const compose = require('koa-compose'); | ||
const context = require('./context'); | ||
const request = require('./request'); | ||
const statuses = require('statuses'); | ||
const Emitter = require('events'); | ||
const util = require('util'); | ||
const Stream = require('stream'); | ||
const http = require('http'); | ||
const only = require('only'); | ||
const convert = require('koa-convert'); | ||
const deprecate = require('depd')('koa'); | ||
const { HttpError } = require('http-errors'); | ||
const debug = require('debug')('koa:application') | ||
const assert = require('assert') | ||
const onFinished = require('on-finished') | ||
const response = require('./response') | ||
const compose = require('koa-compose') | ||
const context = require('./context') | ||
const request = require('./request') | ||
const statuses = require('statuses') | ||
const Emitter = require('events') | ||
const util = require('util') | ||
const Stream = require('stream') | ||
const http = require('http') | ||
const only = require('only') | ||
const { HttpError } = require('http-errors') | ||
/** @typedef {typeof import ('./context') & { | ||
* app: Application | ||
* req: import('http').IncomingMessage | ||
* res: import('http').ServerResponse | ||
* request: KoaRequest | ||
* response: KoaResponse | ||
* state: any | ||
* originalUrl: string | ||
* }} Context */ | ||
/** @typedef {typeof import('./request')} KoaRequest */ | ||
/** @typedef {typeof import('./response')} KoaResponse */ | ||
/** | ||
@@ -51,25 +62,26 @@ * Expose `Application` class. | ||
constructor(options) { | ||
super(); | ||
options = options || {}; | ||
this.proxy = options.proxy || false; | ||
this.subdomainOffset = options.subdomainOffset || 2; | ||
this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For'; | ||
this.maxIpsCount = options.maxIpsCount || 0; | ||
this.env = options.env || process.env.NODE_ENV || 'development'; | ||
if (options.keys) this.keys = options.keys; | ||
this.middleware = []; | ||
this.context = Object.create(context); | ||
this.request = Object.create(request); | ||
this.response = Object.create(response); | ||
constructor (options) { | ||
super() | ||
options = options || {} | ||
this.proxy = options.proxy || false | ||
this.subdomainOffset = options.subdomainOffset || 2 | ||
this.proxyIpHeader = options.proxyIpHeader || 'X-Forwarded-For' | ||
this.maxIpsCount = options.maxIpsCount || 0 | ||
this.env = options.env || process.env.NODE_ENV || 'development' | ||
this.compose = options.compose || compose | ||
if (options.keys) this.keys = options.keys | ||
this.middleware = [] | ||
this.context = Object.create(context) | ||
this.request = Object.create(request) | ||
this.response = Object.create(response) | ||
// util.inspect.custom support for node 6+ | ||
/* istanbul ignore else */ | ||
if (util.inspect.custom) { | ||
this[util.inspect.custom] = this.inspect; | ||
this[util.inspect.custom] = this.inspect | ||
} | ||
if (options.asyncLocalStorage) { | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage'); | ||
this.ctxStorage = new AsyncLocalStorage(); | ||
this.use(this.createAsyncCtxStorageMiddleware()); | ||
const { AsyncLocalStorage } = require('async_hooks') | ||
assert(AsyncLocalStorage, 'Requires node 12.17.0 or higher to enable asyncLocalStorage') | ||
this.ctxStorage = new AsyncLocalStorage() | ||
this.use(this.createAsyncCtxStorageMiddleware()) | ||
} | ||
@@ -84,10 +96,10 @@ } | ||
* @param {Mixed} ... | ||
* @return {Server} | ||
* @return {import('http').Server} | ||
* @api public | ||
*/ | ||
listen(...args) { | ||
debug('listen'); | ||
const server = http.createServer(this.callback()); | ||
return server.listen(...args); | ||
listen (...args) { | ||
debug('listen') | ||
const server = http.createServer(this.callback()) | ||
return server.listen(...args) | ||
} | ||
@@ -103,3 +115,3 @@ | ||
toJSON() { | ||
toJSON () { | ||
return only(this, [ | ||
@@ -109,3 +121,3 @@ 'subdomainOffset', | ||
'env' | ||
]); | ||
]) | ||
} | ||
@@ -120,4 +132,4 @@ | ||
inspect() { | ||
return this.toJSON(); | ||
inspect () { | ||
return this.toJSON() | ||
} | ||
@@ -130,3 +142,3 @@ | ||
* | ||
* @param {Function} fn | ||
* @param {(context: Context) => Promise<any | void>} fn | ||
* @return {Application} self | ||
@@ -136,13 +148,7 @@ * @api public | ||
use(fn) { | ||
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!'); | ||
if (isGeneratorFunction(fn)) { | ||
deprecate('Support for generators will be removed in v3. ' + | ||
'See the documentation for examples of how to convert old middleware ' + | ||
'https://github.com/koajs/koa/blob/master/docs/migration.md'); | ||
fn = convert(fn); | ||
} | ||
debug('use %s', fn._name || fn.name || '-'); | ||
this.middleware.push(fn); | ||
return this; | ||
use (fn) { | ||
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!') | ||
debug('use %s', fn._name || fn.name || '-') | ||
this.middleware.push(fn) | ||
return this | ||
} | ||
@@ -158,20 +164,20 @@ | ||
callback() { | ||
const fn = compose(this.middleware); | ||
callback () { | ||
const fn = this.compose(this.middleware) | ||
if (!this.listenerCount('error')) this.on('error', this.onerror); | ||
if (!this.listenerCount('error')) this.on('error', this.onerror) | ||
const handleRequest = (req, res) => { | ||
const ctx = this.createContext(req, res); | ||
return this.handleRequest(ctx, fn); | ||
}; | ||
const ctx = this.createContext(req, res) | ||
return this.handleRequest(ctx, fn) | ||
} | ||
return handleRequest; | ||
return handleRequest | ||
} | ||
/** | ||
* return currnect contenxt from async local storage | ||
* return current context from async local storage | ||
*/ | ||
get currentContext() { | ||
if (this.ctxStorage) return this.ctxStorage.getStore(); | ||
get currentContext () { | ||
if (this.ctxStorage) return this.ctxStorage.getStore() | ||
} | ||
@@ -185,9 +191,9 @@ | ||
handleRequest(ctx, fnMiddleware) { | ||
const res = ctx.res; | ||
res.statusCode = 404; | ||
const onerror = err => ctx.onerror(err); | ||
const handleResponse = () => respond(ctx); | ||
onFinished(res, onerror); | ||
return fnMiddleware(ctx).then(handleResponse).catch(onerror); | ||
handleRequest (ctx, fnMiddleware) { | ||
const res = ctx.res | ||
res.statusCode = 404 | ||
const onerror = err => ctx.onerror(err) | ||
const handleResponse = () => respond(ctx) | ||
onFinished(res, onerror) | ||
return fnMiddleware(ctx).then(handleResponse).catch(onerror) | ||
} | ||
@@ -201,15 +207,18 @@ | ||
createContext(req, res) { | ||
const context = Object.create(this.context); | ||
const request = context.request = Object.create(this.request); | ||
const response = context.response = Object.create(this.response); | ||
context.app = request.app = response.app = this; | ||
context.req = request.req = response.req = req; | ||
context.res = request.res = response.res = res; | ||
request.ctx = response.ctx = context; | ||
request.response = response; | ||
response.request = request; | ||
context.originalUrl = request.originalUrl = req.url; | ||
context.state = {}; | ||
return context; | ||
createContext (req, res) { | ||
/** @type {Context} */ | ||
const context = Object.create(this.context) | ||
/** @type {KoaRequest} */ | ||
const request = context.request = Object.create(this.request) | ||
/** @type {KoaResponse} */ | ||
const response = context.response = Object.create(this.response) | ||
context.app = request.app = response.app = this | ||
context.req = request.req = response.req = req | ||
context.res = request.res = response.res = res | ||
request.ctx = response.ctx = context | ||
request.response = response | ||
response.request = request | ||
context.originalUrl = request.originalUrl = req.url | ||
context.state = {} | ||
return context | ||
} | ||
@@ -224,3 +233,3 @@ | ||
onerror(err) { | ||
onerror (err) { | ||
// When dealing with cross-globals a normal `instanceof` check doesn't work properly. | ||
@@ -231,10 +240,10 @@ // See https://github.com/koajs/koa/issues/1466 | ||
Object.prototype.toString.call(err) === '[object Error]' || | ||
err instanceof Error; | ||
if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err)); | ||
err instanceof Error | ||
if (!isNativeError) throw new TypeError(util.format('non-error thrown: %j', err)) | ||
if (404 === err.status || err.expose) return; | ||
if (this.silent) return; | ||
if (err.status === 404 || err.expose) return | ||
if (this.silent) return | ||
const msg = err.stack || err.toString(); | ||
console.error(`\n${msg.replace(/^/gm, ' ')}\n`); | ||
const msg = err.stack || err.toString() | ||
console.error(`\n${msg.replace(/^/gm, ' ')}\n`) | ||
} | ||
@@ -247,15 +256,15 @@ | ||
static get default() { | ||
return Application; | ||
static get default () { | ||
return Application | ||
} | ||
createAsyncCtxStorageMiddleware() { | ||
const app = this; | ||
return async function asyncCtxStorage(ctx, next) { | ||
await app.ctxStorage.run(ctx, async() => { | ||
return await next(); | ||
}); | ||
}; | ||
createAsyncCtxStorageMiddleware () { | ||
const app = this | ||
return async function asyncCtxStorage (ctx, next) { | ||
await app.ctxStorage.run(ctx, async () => { | ||
return await next() | ||
}) | ||
} | ||
} | ||
}; | ||
} | ||
@@ -266,11 +275,11 @@ /** | ||
function respond(ctx) { | ||
function respond (ctx) { | ||
// allow bypassing koa | ||
if (false === ctx.respond) return; | ||
if (ctx.respond === false) return | ||
if (!ctx.writable) return; | ||
if (!ctx.writable) return | ||
const res = ctx.res; | ||
let body = ctx.body; | ||
const code = ctx.status; | ||
const res = ctx.res | ||
let body = ctx.body | ||
const code = ctx.status | ||
@@ -280,44 +289,45 @@ // ignore body | ||
// strip headers | ||
ctx.body = null; | ||
return res.end(); | ||
ctx.body = null | ||
return res.end() | ||
} | ||
if ('HEAD' === ctx.method) { | ||
if (ctx.method === 'HEAD') { | ||
if (!res.headersSent && !ctx.response.has('Content-Length')) { | ||
const { length } = ctx.response; | ||
if (Number.isInteger(length)) ctx.length = length; | ||
const { length } = ctx.response | ||
if (Number.isInteger(length)) ctx.length = length | ||
} | ||
return res.end(); | ||
return res.end() | ||
} | ||
// status body | ||
if (null == body) { | ||
if (body == null) { | ||
if (ctx.response._explicitNullBody) { | ||
ctx.response.remove('Content-Type'); | ||
ctx.response.remove('Transfer-Encoding'); | ||
return res.end(); | ||
ctx.response.remove('Content-Type') | ||
ctx.response.remove('Transfer-Encoding') | ||
ctx.length = 0 | ||
return res.end() | ||
} | ||
if (ctx.req.httpVersionMajor >= 2) { | ||
body = String(code); | ||
body = String(code) | ||
} else { | ||
body = ctx.message || String(code); | ||
body = ctx.message || String(code) | ||
} | ||
if (!res.headersSent) { | ||
ctx.type = 'text'; | ||
ctx.length = Buffer.byteLength(body); | ||
ctx.type = 'text' | ||
ctx.length = Buffer.byteLength(body) | ||
} | ||
return res.end(body); | ||
return res.end(body) | ||
} | ||
// responses | ||
if (Buffer.isBuffer(body)) return res.end(body); | ||
if ('string' === typeof body) return res.end(body); | ||
if (body instanceof Stream) return body.pipe(res); | ||
if (Buffer.isBuffer(body)) return res.end(body) | ||
if (typeof body === 'string') return res.end(body) | ||
if (body instanceof Stream) return body.pipe(res) | ||
// body: json | ||
body = JSON.stringify(body); | ||
body = JSON.stringify(body) | ||
if (!res.headersSent) { | ||
ctx.length = Buffer.byteLength(body); | ||
ctx.length = Buffer.byteLength(body) | ||
} | ||
res.end(body); | ||
res.end(body) | ||
} | ||
@@ -330,2 +340,2 @@ | ||
module.exports.HttpError = HttpError; | ||
module.exports.HttpError = HttpError |
'use strict'; | ||
'use strict' | ||
@@ -8,10 +8,10 @@ /** | ||
const util = require('util'); | ||
const createError = require('http-errors'); | ||
const httpAssert = require('http-assert'); | ||
const delegate = require('delegates'); | ||
const statuses = require('statuses'); | ||
const Cookies = require('cookies'); | ||
const util = require('util') | ||
const createError = require('http-errors') | ||
const httpAssert = require('http-assert') | ||
const delegate = require('delegates') | ||
const statuses = require('statuses') | ||
const Cookies = require('cookies') | ||
const COOKIES = Symbol('context#cookies'); | ||
const COOKIES = Symbol('context#cookies') | ||
@@ -32,5 +32,5 @@ /** | ||
inspect() { | ||
if (this === proto) return this; | ||
return this.toJSON(); | ||
inspect () { | ||
if (this === proto) return this | ||
return this.toJSON() | ||
}, | ||
@@ -50,3 +50,3 @@ | ||
toJSON() { | ||
toJSON () { | ||
return { | ||
@@ -60,3 +60,3 @@ request: this.request.toJSON(), | ||
socket: '<original node socket>' | ||
}; | ||
} | ||
}, | ||
@@ -100,4 +100,4 @@ | ||
throw(...args) { | ||
throw createError(...args); | ||
throw (...args) { | ||
throw createError(...args) | ||
}, | ||
@@ -112,7 +112,7 @@ | ||
onerror(err) { | ||
onerror (err) { | ||
// don't do anything if there is no error. | ||
// this allows you to pass `this.onerror` | ||
// to node-style callbacks. | ||
if (null == err) return; | ||
if (err == null) return | ||
@@ -124,12 +124,12 @@ // When dealing with cross-globals a normal `instanceof` check doesn't work properly. | ||
Object.prototype.toString.call(err) === '[object Error]' || | ||
err instanceof Error; | ||
if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err)); | ||
err instanceof Error | ||
if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err)) | ||
let headerSent = false; | ||
let headerSent = false | ||
if (this.headerSent || !this.writable) { | ||
headerSent = err.headerSent = true; | ||
headerSent = err.headerSent = true | ||
} | ||
// delegate | ||
this.app.emit('error', err, this); | ||
this.app.emit('error', err, this) | ||
@@ -140,6 +140,6 @@ // nothing we can do here other | ||
if (headerSent) { | ||
return; | ||
return | ||
} | ||
const { res } = this; | ||
const { res } = this | ||
@@ -149,30 +149,30 @@ // first unset all headers | ||
if (typeof res.getHeaderNames === 'function') { | ||
res.getHeaderNames().forEach(name => res.removeHeader(name)); | ||
res.getHeaderNames().forEach(name => res.removeHeader(name)) | ||
} else { | ||
res._headers = {}; // Node < 7.7 | ||
res._headers = {} // Node < 7.7 | ||
} | ||
// then set those specified | ||
this.set(err.headers); | ||
this.set(err.headers) | ||
// force text/plain | ||
this.type = 'text'; | ||
this.type = 'text' | ||
let statusCode = err.status || err.statusCode; | ||
let statusCode = err.status || err.statusCode | ||
// ENOENT support | ||
if ('ENOENT' === err.code) statusCode = 404; | ||
if (err.code === 'ENOENT') statusCode = 404 | ||
// default to 500 | ||
if ('number' !== typeof statusCode || !statuses[statusCode]) statusCode = 500; | ||
if (typeof statusCode !== 'number' || !statuses[statusCode]) statusCode = 500 | ||
// respond | ||
const code = statuses[statusCode]; | ||
const msg = err.expose ? err.message : code; | ||
this.status = err.status = statusCode; | ||
this.length = Buffer.byteLength(msg); | ||
res.end(msg); | ||
const code = statuses[statusCode] | ||
const msg = err.expose ? err.message : code | ||
this.status = err.status = statusCode | ||
this.length = Buffer.byteLength(msg) | ||
res.end(msg) | ||
}, | ||
get cookies() { | ||
get cookies () { | ||
if (!this[COOKIES]) { | ||
@@ -182,11 +182,11 @@ this[COOKIES] = new Cookies(this.req, this.res, { | ||
secure: this.request.secure | ||
}); | ||
}) | ||
} | ||
return this[COOKIES]; | ||
return this[COOKIES] | ||
}, | ||
set cookies(_cookies) { | ||
this[COOKIES] = _cookies; | ||
set cookies (_cookies) { | ||
this[COOKIES] = _cookies | ||
} | ||
}; | ||
} | ||
@@ -202,3 +202,3 @@ /** | ||
if (util.inspect.custom) { | ||
module.exports[util.inspect.custom] = module.exports.inspect; | ||
module.exports[util.inspect.custom] = module.exports.inspect | ||
} | ||
@@ -227,3 +227,3 @@ | ||
.getter('headerSent') | ||
.getter('writable'); | ||
.getter('writable') | ||
@@ -263,2 +263,2 @@ /** | ||
.getter('ips') | ||
.getter('ip'); | ||
.getter('ip') |
'use strict'; | ||
'use strict' | ||
@@ -8,15 +8,15 @@ /** | ||
const URL = require('url').URL; | ||
const net = require('net'); | ||
const accepts = require('accepts'); | ||
const contentType = require('content-type'); | ||
const stringify = require('url').format; | ||
const parse = require('parseurl'); | ||
const qs = require('querystring'); | ||
const typeis = require('type-is'); | ||
const fresh = require('fresh'); | ||
const only = require('only'); | ||
const util = require('util'); | ||
const URL = require('url').URL | ||
const net = require('net') | ||
const accepts = require('accepts') | ||
const contentType = require('content-type') | ||
const stringify = require('url').format | ||
const parse = require('parseurl') | ||
const qs = require('querystring') | ||
const typeis = require('type-is') | ||
const fresh = require('fresh') | ||
const only = require('only') | ||
const util = require('util') | ||
const IP = Symbol('context#ip'); | ||
const IP = Symbol('context#ip') | ||
@@ -36,4 +36,4 @@ /** | ||
get header() { | ||
return this.req.headers; | ||
get header () { | ||
return this.req.headers | ||
}, | ||
@@ -47,4 +47,4 @@ | ||
set header(val) { | ||
this.req.headers = val; | ||
set header (val) { | ||
this.req.headers = val | ||
}, | ||
@@ -59,4 +59,4 @@ | ||
get headers() { | ||
return this.req.headers; | ||
get headers () { | ||
return this.req.headers | ||
}, | ||
@@ -70,4 +70,4 @@ | ||
set headers(val) { | ||
this.req.headers = val; | ||
set headers (val) { | ||
this.req.headers = val | ||
}, | ||
@@ -82,4 +82,4 @@ | ||
get url() { | ||
return this.req.url; | ||
get url () { | ||
return this.req.url | ||
}, | ||
@@ -93,4 +93,4 @@ | ||
set url(val) { | ||
this.req.url = val; | ||
set url (val) { | ||
this.req.url = val | ||
}, | ||
@@ -105,4 +105,4 @@ | ||
get origin() { | ||
return `${this.protocol}://${this.host}`; | ||
get origin () { | ||
return `${this.protocol}://${this.host}` | ||
}, | ||
@@ -117,6 +117,6 @@ | ||
get href() { | ||
get href () { | ||
// support: `GET http://example.com/foo` | ||
if (/^https?:\/\//i.test(this.originalUrl)) return this.originalUrl; | ||
return this.origin + this.originalUrl; | ||
if (/^https?:\/\//i.test(this.originalUrl)) return this.originalUrl | ||
return this.origin + this.originalUrl | ||
}, | ||
@@ -131,4 +131,4 @@ | ||
get method() { | ||
return this.req.method; | ||
get method () { | ||
return this.req.method | ||
}, | ||
@@ -143,4 +143,4 @@ | ||
set method(val) { | ||
this.req.method = val; | ||
set method (val) { | ||
this.req.method = val | ||
}, | ||
@@ -155,4 +155,4 @@ | ||
get path() { | ||
return parse(this.req).pathname; | ||
get path () { | ||
return parse(this.req).pathname | ||
}, | ||
@@ -167,10 +167,10 @@ | ||
set path(path) { | ||
const url = parse(this.req); | ||
if (url.pathname === path) return; | ||
set path (path) { | ||
const url = parse(this.req) | ||
if (url.pathname === path) return | ||
url.pathname = path; | ||
url.path = null; | ||
url.pathname = path | ||
url.path = null | ||
this.url = stringify(url); | ||
this.url = stringify(url) | ||
}, | ||
@@ -185,6 +185,6 @@ | ||
get query() { | ||
const str = this.querystring; | ||
const c = this._querycache = this._querycache || {}; | ||
return c[str] || (c[str] = qs.parse(str)); | ||
get query () { | ||
const str = this.querystring | ||
const c = this._querycache = this._querycache || {} | ||
return c[str] || (c[str] = qs.parse(str)) | ||
}, | ||
@@ -199,4 +199,4 @@ | ||
set query(obj) { | ||
this.querystring = qs.stringify(obj); | ||
set query (obj) { | ||
this.querystring = qs.stringify(obj) | ||
}, | ||
@@ -211,5 +211,5 @@ | ||
get querystring() { | ||
if (!this.req) return ''; | ||
return parse(this.req).query || ''; | ||
get querystring () { | ||
if (!this.req) return '' | ||
return parse(this.req).query || '' | ||
}, | ||
@@ -224,10 +224,10 @@ | ||
set querystring(str) { | ||
const url = parse(this.req); | ||
if (url.search === `?${str}`) return; | ||
set querystring (str) { | ||
const url = parse(this.req) | ||
if (url.search === `?${str}`) return | ||
url.search = str; | ||
url.path = null; | ||
url.search = str | ||
url.path = null | ||
this.url = stringify(url); | ||
this.url = stringify(url) | ||
}, | ||
@@ -243,5 +243,5 @@ | ||
get search() { | ||
if (!this.querystring) return ''; | ||
return `?${this.querystring}`; | ||
get search () { | ||
if (!this.querystring) return '' | ||
return `?${this.querystring}` | ||
}, | ||
@@ -257,4 +257,4 @@ | ||
set search(str) { | ||
this.querystring = str; | ||
set search (str) { | ||
this.querystring = str | ||
}, | ||
@@ -271,11 +271,11 @@ | ||
get host() { | ||
const proxy = this.app.proxy; | ||
let host = proxy && this.get('X-Forwarded-Host'); | ||
get host () { | ||
const proxy = this.app.proxy | ||
let host = proxy && this.get('X-Forwarded-Host') | ||
if (!host) { | ||
if (this.req.httpVersionMajor >= 2) host = this.get(':authority'); | ||
if (!host) host = this.get('Host'); | ||
if (this.req.httpVersionMajor >= 2) host = this.get(':authority') | ||
if (!host) host = this.get('Host') | ||
} | ||
if (!host) return ''; | ||
return host.split(/\s*,\s*/, 1)[0]; | ||
if (!host) return '' | ||
return host.split(/\s*,\s*/, 1)[0] | ||
}, | ||
@@ -292,7 +292,7 @@ | ||
get hostname() { | ||
const host = this.host; | ||
if (!host) return ''; | ||
if ('[' === host[0]) return this.URL.hostname || ''; // IPv6 | ||
return host.split(':', 1)[0]; | ||
get hostname () { | ||
const host = this.host | ||
if (!host) return '' | ||
if (host[0] === '[') return this.URL.hostname || '' // IPv6 | ||
return host.split(':', 1)[0] | ||
}, | ||
@@ -308,13 +308,13 @@ | ||
get URL() { | ||
get URL () { | ||
/* istanbul ignore else */ | ||
if (!this.memoizedURL) { | ||
const originalUrl = this.originalUrl || ''; // avoid undefined in template string | ||
const originalUrl = this.originalUrl || '' // avoid undefined in template string | ||
try { | ||
this.memoizedURL = new URL(`${this.origin}${originalUrl}`); | ||
this.memoizedURL = new URL(`${this.origin}${originalUrl}`) | ||
} catch (err) { | ||
this.memoizedURL = Object.create(null); | ||
this.memoizedURL = Object.create(null) | ||
} | ||
} | ||
return this.memoizedURL; | ||
return this.memoizedURL | ||
}, | ||
@@ -331,15 +331,15 @@ | ||
get fresh() { | ||
const method = this.method; | ||
const s = this.ctx.status; | ||
get fresh () { | ||
const method = this.method | ||
const s = this.ctx.status | ||
// GET or HEAD for weak freshness validation only | ||
if ('GET' !== method && 'HEAD' !== method) return false; | ||
if (method !== 'GET' && method !== 'HEAD') return false | ||
// 2xx or 304 as per rfc2616 14.26 | ||
if ((s >= 200 && s < 300) || 304 === s) { | ||
return fresh(this.header, this.response.header); | ||
if ((s >= 200 && s < 300) || s === 304) { | ||
return fresh(this.header, this.response.header) | ||
} | ||
return false; | ||
return false | ||
}, | ||
@@ -356,4 +356,4 @@ | ||
get stale() { | ||
return !this.fresh; | ||
get stale () { | ||
return !this.fresh | ||
}, | ||
@@ -368,5 +368,5 @@ | ||
get idempotent() { | ||
const methods = ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS', 'TRACE']; | ||
return !!~methods.indexOf(this.method); | ||
get idempotent () { | ||
const methods = ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS', 'TRACE'] | ||
return !!~methods.indexOf(this.method) | ||
}, | ||
@@ -381,4 +381,4 @@ | ||
get socket() { | ||
return this.req.socket; | ||
get socket () { | ||
return this.req.socket | ||
}, | ||
@@ -393,8 +393,8 @@ | ||
get charset() { | ||
get charset () { | ||
try { | ||
const { parameters } = contentType.parse(this.req); | ||
return parameters.charset || ''; | ||
const { parameters } = contentType.parse(this.req) | ||
return parameters.charset || '' | ||
} catch (e) { | ||
return ''; | ||
return '' | ||
} | ||
@@ -410,6 +410,6 @@ }, | ||
get length() { | ||
const len = this.get('Content-Length'); | ||
if (len === '') return; | ||
return ~~len; | ||
get length () { | ||
const len = this.get('Content-Length') | ||
if (len === '') return | ||
return ~~len | ||
}, | ||
@@ -429,7 +429,7 @@ | ||
get protocol() { | ||
if (this.socket.encrypted) return 'https'; | ||
if (!this.app.proxy) return 'http'; | ||
const proto = this.get('X-Forwarded-Proto'); | ||
return proto ? proto.split(/\s*,\s*/, 1)[0] : 'http'; | ||
get protocol () { | ||
if (this.socket.encrypted) return 'https' | ||
if (!this.app.proxy) return 'http' | ||
const proto = this.get('X-Forwarded-Proto') | ||
return proto ? proto.split(/\s*,\s*/, 1)[0] : 'http' | ||
}, | ||
@@ -446,4 +446,4 @@ | ||
get secure() { | ||
return 'https' === this.protocol; | ||
get secure () { | ||
return this.protocol === 'https' | ||
}, | ||
@@ -463,12 +463,12 @@ | ||
get ips() { | ||
const proxy = this.app.proxy; | ||
const val = this.get(this.app.proxyIpHeader); | ||
get ips () { | ||
const proxy = this.app.proxy | ||
const val = this.get(this.app.proxyIpHeader) | ||
let ips = proxy && val | ||
? val.split(/\s*,\s*/) | ||
: []; | ||
: [] | ||
if (this.app.maxIpsCount > 0) { | ||
ips = ips.slice(-this.app.maxIpsCount); | ||
ips = ips.slice(-this.app.maxIpsCount) | ||
} | ||
return ips; | ||
return ips | ||
}, | ||
@@ -485,11 +485,11 @@ | ||
get ip() { | ||
get ip () { | ||
if (!this[IP]) { | ||
this[IP] = this.ips[0] || this.socket.remoteAddress || ''; | ||
this[IP] = this.ips[0] || this.socket.remoteAddress || '' | ||
} | ||
return this[IP]; | ||
return this[IP] | ||
}, | ||
set ip(_ip) { | ||
this[IP] = _ip; | ||
set ip (_ip) { | ||
this[IP] = _ip | ||
}, | ||
@@ -513,10 +513,10 @@ | ||
get subdomains() { | ||
const offset = this.app.subdomainOffset; | ||
const hostname = this.hostname; | ||
if (net.isIP(hostname)) return []; | ||
get subdomains () { | ||
const offset = this.app.subdomainOffset | ||
const hostname = this.hostname | ||
if (net.isIP(hostname)) return [] | ||
return hostname | ||
.split('.') | ||
.reverse() | ||
.slice(offset); | ||
.slice(offset) | ||
}, | ||
@@ -532,4 +532,4 @@ | ||
get accept() { | ||
return this._accept || (this._accept = accepts(this.req)); | ||
get accept () { | ||
return this._accept || (this._accept = accepts(this.req)) | ||
}, | ||
@@ -544,4 +544,4 @@ | ||
set accept(obj) { | ||
this._accept = obj; | ||
set accept (obj) { | ||
this._accept = obj | ||
}, | ||
@@ -590,4 +590,4 @@ | ||
accepts(...args) { | ||
return this.accept.types(...args); | ||
accepts (...args) { | ||
return this.accept.types(...args) | ||
}, | ||
@@ -608,4 +608,4 @@ | ||
acceptsEncodings(...args) { | ||
return this.accept.encodings(...args); | ||
acceptsEncodings (...args) { | ||
return this.accept.encodings(...args) | ||
}, | ||
@@ -626,4 +626,4 @@ | ||
acceptsCharsets(...args) { | ||
return this.accept.charsets(...args); | ||
acceptsCharsets (...args) { | ||
return this.accept.charsets(...args) | ||
}, | ||
@@ -644,4 +644,4 @@ | ||
acceptsLanguages(...args) { | ||
return this.accept.languages(...args); | ||
acceptsLanguages (...args) { | ||
return this.accept.languages(...args) | ||
}, | ||
@@ -676,4 +676,4 @@ | ||
is(type, ...types) { | ||
return typeis(this.req, type, ...types); | ||
is (type, ...types) { | ||
return typeis(this.req, type, ...types) | ||
}, | ||
@@ -689,6 +689,6 @@ | ||
get type() { | ||
const type = this.get('Content-Type'); | ||
if (!type) return ''; | ||
return type.split(';')[0]; | ||
get type () { | ||
const type = this.get('Content-Type') | ||
if (!type) return '' | ||
return type.split(';')[0] | ||
}, | ||
@@ -718,10 +718,10 @@ | ||
get(field) { | ||
const req = this.req; | ||
get (field) { | ||
const req = this.req | ||
switch (field = field.toLowerCase()) { | ||
case 'referer': | ||
case 'referrer': | ||
return req.headers.referrer || req.headers.referer || ''; | ||
return req.headers.referrer || req.headers.referer || '' | ||
default: | ||
return req.headers[field] || ''; | ||
return req.headers[field] || '' | ||
} | ||
@@ -737,5 +737,5 @@ }, | ||
inspect() { | ||
if (!this.req) return; | ||
return this.toJSON(); | ||
inspect () { | ||
if (!this.req) return | ||
return this.toJSON() | ||
}, | ||
@@ -750,3 +750,3 @@ | ||
toJSON() { | ||
toJSON () { | ||
return only(this, [ | ||
@@ -756,5 +756,5 @@ 'method', | ||
'header' | ||
]); | ||
]) | ||
} | ||
}; | ||
} | ||
@@ -770,3 +770,3 @@ /** | ||
if (util.inspect.custom) { | ||
module.exports[util.inspect.custom] = module.exports.inspect; | ||
module.exports[util.inspect.custom] = module.exports.inspect | ||
} |
'use strict'; | ||
'use strict' | ||
@@ -8,16 +8,16 @@ /** | ||
const contentDisposition = require('content-disposition'); | ||
const getType = require('cache-content-type'); | ||
const onFinish = require('on-finished'); | ||
const escape = require('escape-html'); | ||
const typeis = require('type-is').is; | ||
const statuses = require('statuses'); | ||
const destroy = require('destroy'); | ||
const assert = require('assert'); | ||
const extname = require('path').extname; | ||
const vary = require('vary'); | ||
const only = require('only'); | ||
const util = require('util'); | ||
const encodeUrl = require('encodeurl'); | ||
const Stream = require('stream'); | ||
const contentDisposition = require('content-disposition') | ||
const getType = require('cache-content-type') | ||
const onFinish = require('on-finished') | ||
const escape = require('escape-html') | ||
const typeis = require('type-is').is | ||
const statuses = require('statuses') | ||
const destroy = require('destroy') | ||
const assert = require('assert') | ||
const extname = require('path').extname | ||
const vary = require('vary') | ||
const only = require('only') | ||
const util = require('util') | ||
const encodeUrl = require('encodeurl') | ||
const Stream = require('stream') | ||
@@ -37,4 +37,4 @@ /** | ||
get socket() { | ||
return this.res.socket; | ||
get socket () { | ||
return this.res.socket | ||
}, | ||
@@ -49,7 +49,7 @@ | ||
get header() { | ||
const { res } = this; | ||
get header () { | ||
const { res } = this | ||
return typeof res.getHeaders === 'function' | ||
? res.getHeaders() | ||
: res._headers || {}; // Node < 7.7 | ||
: res._headers || {} // Node < 7.7 | ||
}, | ||
@@ -64,4 +64,4 @@ | ||
get headers() { | ||
return this.header; | ||
get headers () { | ||
return this.header | ||
}, | ||
@@ -76,4 +76,4 @@ | ||
get status() { | ||
return this.res.statusCode; | ||
get status () { | ||
return this.res.statusCode | ||
}, | ||
@@ -88,11 +88,11 @@ | ||
set status(code) { | ||
if (this.headerSent) return; | ||
set status (code) { | ||
if (this.headerSent) return | ||
assert(Number.isInteger(code), 'status code must be a number'); | ||
assert(code >= 100 && code <= 999, `invalid status code: ${code}`); | ||
this._explicitStatus = true; | ||
this.res.statusCode = code; | ||
if (this.req.httpVersionMajor < 2) this.res.statusMessage = statuses[code]; | ||
if (this.body && statuses.empty[code]) this.body = null; | ||
assert(Number.isInteger(code), 'status code must be a number') | ||
assert(code >= 100 && code <= 999, `invalid status code: ${code}`) | ||
this._explicitStatus = true | ||
this.res.statusCode = code | ||
if (this.req.httpVersionMajor < 2) this.res.statusMessage = statuses[code] | ||
if (this.body && statuses.empty[code]) this.body = null | ||
}, | ||
@@ -107,4 +107,4 @@ | ||
get message() { | ||
return this.res.statusMessage || statuses[this.status]; | ||
get message () { | ||
return this.res.statusMessage || statuses[this.status] | ||
}, | ||
@@ -119,4 +119,4 @@ | ||
set message(msg) { | ||
this.res.statusMessage = msg; | ||
set message (msg) { | ||
this.res.statusMessage = msg | ||
}, | ||
@@ -131,4 +131,4 @@ | ||
get body() { | ||
return this._body; | ||
get body () { | ||
return this._body | ||
}, | ||
@@ -143,27 +143,33 @@ | ||
set body(val) { | ||
const original = this._body; | ||
this._body = val; | ||
set body (val) { | ||
const original = this._body | ||
this._body = val | ||
// no content | ||
if (null == val) { | ||
if (!statuses.empty[this.status]) this.status = 204; | ||
if (val === null) this._explicitNullBody = true; | ||
this.remove('Content-Type'); | ||
this.remove('Content-Length'); | ||
this.remove('Transfer-Encoding'); | ||
return; | ||
if (val == null) { | ||
if (!statuses.empty[this.status]) { | ||
if (this.type === 'application/json') { | ||
this._body = 'null' | ||
return | ||
} | ||
this.status = 204 | ||
} | ||
if (val === null) this._explicitNullBody = true | ||
this.remove('Content-Type') | ||
this.remove('Content-Length') | ||
this.remove('Transfer-Encoding') | ||
return | ||
} | ||
// set the status | ||
if (!this._explicitStatus) this.status = 200; | ||
if (!this._explicitStatus) this.status = 200 | ||
// set the content-type only if not yet set | ||
const setType = !this.has('Content-Type'); | ||
const setType = !this.has('Content-Type') | ||
// string | ||
if ('string' === typeof val) { | ||
if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text'; | ||
this.length = Buffer.byteLength(val); | ||
return; | ||
if (typeof val === 'string') { | ||
if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text' | ||
this.length = Buffer.byteLength(val) | ||
return | ||
} | ||
@@ -173,5 +179,5 @@ | ||
if (Buffer.isBuffer(val)) { | ||
if (setType) this.type = 'bin'; | ||
this.length = val.length; | ||
return; | ||
if (setType) this.type = 'bin' | ||
this.length = val.length | ||
return | ||
} | ||
@@ -181,16 +187,16 @@ | ||
if (val instanceof Stream) { | ||
onFinish(this.res, destroy.bind(null, val)); | ||
if (original != val) { | ||
val.once('error', err => this.ctx.onerror(err)); | ||
onFinish(this.res, destroy.bind(null, val)) | ||
if (original !== val) { | ||
val.once('error', err => this.ctx.onerror(err)) | ||
// overwriting | ||
if (null != original) this.remove('Content-Length'); | ||
if (original != null) this.remove('Content-Length') | ||
} | ||
if (setType) this.type = 'bin'; | ||
return; | ||
if (setType) this.type = 'bin' | ||
return | ||
} | ||
// json | ||
this.remove('Content-Length'); | ||
this.type = 'json'; | ||
this.remove('Content-Length') | ||
this.type = 'json' | ||
}, | ||
@@ -205,5 +211,5 @@ | ||
set length(n) { | ||
set length (n) { | ||
if (!this.has('Transfer-Encoding')) { | ||
this.set('Content-Length', n); | ||
this.set('Content-Length', n) | ||
} | ||
@@ -219,12 +225,12 @@ }, | ||
get length() { | ||
get length () { | ||
if (this.has('Content-Length')) { | ||
return parseInt(this.get('Content-Length'), 10) || 0; | ||
return parseInt(this.get('Content-Length'), 10) || 0 | ||
} | ||
const { body } = this; | ||
if (!body || body instanceof Stream) return undefined; | ||
if ('string' === typeof body) return Buffer.byteLength(body); | ||
if (Buffer.isBuffer(body)) return body.length; | ||
return Buffer.byteLength(JSON.stringify(body)); | ||
const { body } = this | ||
if (!body || body instanceof Stream) return undefined | ||
if (typeof body === 'string') return Buffer.byteLength(body) | ||
if (Buffer.isBuffer(body)) return body.length | ||
return Buffer.byteLength(JSON.stringify(body)) | ||
}, | ||
@@ -239,4 +245,4 @@ | ||
get headerSent() { | ||
return this.res.headersSent; | ||
get headerSent () { | ||
return this.res.headersSent | ||
}, | ||
@@ -251,6 +257,6 @@ | ||
vary(field) { | ||
if (this.headerSent) return; | ||
vary (field) { | ||
if (this.headerSent) return | ||
vary(this.res, field); | ||
vary(this.res, field) | ||
}, | ||
@@ -277,21 +283,21 @@ | ||
redirect(url, alt) { | ||
redirect (url, alt) { | ||
// location | ||
if ('back' === url) url = this.ctx.get('Referrer') || alt || '/'; | ||
this.set('Location', encodeUrl(url)); | ||
if (url === 'back') url = this.ctx.get('Referrer') || alt || '/' | ||
this.set('Location', encodeUrl(url)) | ||
// status | ||
if (!statuses.redirect[this.status]) this.status = 302; | ||
if (!statuses.redirect[this.status]) this.status = 302 | ||
// html | ||
if (this.ctx.accepts('html')) { | ||
url = escape(url); | ||
this.type = 'text/html; charset=utf-8'; | ||
this.body = `Redirecting to <a href="${url}">${url}</a>.`; | ||
return; | ||
url = escape(url) | ||
this.type = 'text/html; charset=utf-8' | ||
this.body = `Redirecting to <a href="${url}">${url}</a>.` | ||
return | ||
} | ||
// text | ||
this.type = 'text/plain; charset=utf-8'; | ||
this.body = `Redirecting to ${url}.`; | ||
this.type = 'text/plain; charset=utf-8' | ||
this.body = `Redirecting to ${url}.` | ||
}, | ||
@@ -306,5 +312,5 @@ | ||
attachment(filename, options) { | ||
if (filename) this.type = extname(filename); | ||
this.set('Content-Disposition', contentDisposition(filename, options)); | ||
attachment (filename, options) { | ||
if (filename) this.type = extname(filename) | ||
this.set('Content-Disposition', contentDisposition(filename, options)) | ||
}, | ||
@@ -328,8 +334,8 @@ | ||
set type(type) { | ||
type = getType(type); | ||
set type (type) { | ||
type = getType(type) | ||
if (type) { | ||
this.set('Content-Type', type); | ||
this.set('Content-Type', type) | ||
} else { | ||
this.remove('Content-Type'); | ||
this.remove('Content-Type') | ||
} | ||
@@ -348,5 +354,5 @@ }, | ||
set lastModified(val) { | ||
if ('string' === typeof val) val = new Date(val); | ||
this.set('Last-Modified', val.toUTCString()); | ||
set lastModified (val) { | ||
if (typeof val === 'string') val = new Date(val) | ||
this.set('Last-Modified', val.toUTCString()) | ||
}, | ||
@@ -361,5 +367,5 @@ | ||
get lastModified() { | ||
const date = this.get('last-modified'); | ||
if (date) return new Date(date); | ||
get lastModified () { | ||
const date = this.get('last-modified') | ||
if (date) return new Date(date) | ||
}, | ||
@@ -379,5 +385,5 @@ | ||
set etag(val) { | ||
if (!/^(W\/)?"/.test(val)) val = `"${val}"`; | ||
this.set('ETag', val); | ||
set etag (val) { | ||
if (!/^(W\/)?"/.test(val)) val = `"${val}"` | ||
this.set('ETag', val) | ||
}, | ||
@@ -392,4 +398,4 @@ | ||
get etag() { | ||
return this.get('ETag'); | ||
get etag () { | ||
return this.get('ETag') | ||
}, | ||
@@ -405,6 +411,6 @@ | ||
get type() { | ||
const type = this.get('Content-Type'); | ||
if (!type) return ''; | ||
return type.split(';', 1)[0]; | ||
get type () { | ||
const type = this.get('Content-Type') | ||
if (!type) return '' | ||
return type.split(';', 1)[0] | ||
}, | ||
@@ -422,4 +428,4 @@ | ||
is(type, ...types) { | ||
return typeis(this.type, type, ...types); | ||
is (type, ...types) { | ||
return typeis(this.type, type, ...types) | ||
}, | ||
@@ -439,8 +445,8 @@ | ||
* @param {String} field | ||
* @return {String} | ||
* @return {any} | ||
* @api public | ||
*/ | ||
get(field) { | ||
return this.header[field.toLowerCase()] || ''; | ||
get (field) { | ||
return this.res.getHeader(field) | ||
}, | ||
@@ -465,7 +471,7 @@ | ||
has(field) { | ||
has (field) { | ||
return typeof this.res.hasHeader === 'function' | ||
? this.res.hasHeader(field) | ||
// Node < 7.7 | ||
: field.toLowerCase() in this.headers; | ||
: field.toLowerCase() in this.headers | ||
}, | ||
@@ -488,12 +494,12 @@ | ||
set(field, val) { | ||
if (this.headerSent) return; | ||
set (field, val) { | ||
if (this.headerSent) return | ||
if (2 === arguments.length) { | ||
if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v)); | ||
else if (typeof val !== 'string') val = String(val); | ||
this.res.setHeader(field, val); | ||
if (arguments.length === 2) { | ||
if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v)) | ||
else if (typeof val !== 'string') val = String(val) | ||
this.res.setHeader(field, val) | ||
} else { | ||
for (const key in field) { | ||
this.set(key, field[key]); | ||
this.set(key, field[key]) | ||
} | ||
@@ -519,4 +525,4 @@ } | ||
append(field, val) { | ||
const prev = this.get(field); | ||
append (field, val) { | ||
const prev = this.get(field) | ||
@@ -526,6 +532,6 @@ if (prev) { | ||
? prev.concat(val) | ||
: [prev].concat(val); | ||
: [prev].concat(val) | ||
} | ||
return this.set(field, val); | ||
return this.set(field, val) | ||
}, | ||
@@ -540,6 +546,6 @@ | ||
remove(field) { | ||
if (this.headerSent) return; | ||
remove (field) { | ||
if (this.headerSent) return | ||
this.res.removeHeader(field); | ||
this.res.removeHeader(field) | ||
}, | ||
@@ -556,3 +562,3 @@ | ||
get writable() { | ||
get writable () { | ||
// can't write any more after response finished | ||
@@ -563,9 +569,9 @@ // response.writableEnded is available since Node > 12.9 | ||
// https://stackoverflow.com/questions/16254385/undocumented-response-finished-in-node-js | ||
if (this.res.writableEnded || this.res.finished) return false; | ||
if (this.res.writableEnded || this.res.finished) return false | ||
const socket = this.res.socket; | ||
const socket = this.res.socket | ||
// There are already pending outgoing res, but still writable | ||
// https://github.com/nodejs/node/blob/v4.4.7/lib/_http_server.js#L486 | ||
if (!socket) return true; | ||
return socket.writable; | ||
if (!socket) return true | ||
return socket.writable | ||
}, | ||
@@ -580,7 +586,7 @@ | ||
inspect() { | ||
if (!this.res) return; | ||
const o = this.toJSON(); | ||
o.body = this.body; | ||
return o; | ||
inspect () { | ||
if (!this.res) return | ||
const o = this.toJSON() | ||
o.body = this.body | ||
return o | ||
}, | ||
@@ -595,3 +601,3 @@ | ||
toJSON() { | ||
toJSON () { | ||
return only(this, [ | ||
@@ -601,3 +607,3 @@ 'status', | ||
'header' | ||
]); | ||
]) | ||
}, | ||
@@ -609,6 +615,6 @@ | ||
flushHeaders() { | ||
this.res.flushHeaders(); | ||
flushHeaders () { | ||
this.res.flushHeaders() | ||
} | ||
}; | ||
} | ||
@@ -624,3 +630,3 @@ /** | ||
if (util.inspect.custom) { | ||
module.exports[util.inspect.custom] = module.exports.inspect; | ||
module.exports[util.inspect.custom] = module.exports.inspect | ||
} |
{ | ||
"name": "koa", | ||
"version": "2.14.1", | ||
"version": "3.0.0-alpha.0", | ||
"publishConfig": { | ||
"tag": "experimental" | ||
}, | ||
"description": "Koa web app framework", | ||
@@ -11,10 +14,2 @@ "main": "lib/application.js", | ||
}, | ||
"./lib/request": "./lib/request.js", | ||
"./lib/request.js": "./lib/request.js", | ||
"./lib/response": "./lib/response.js", | ||
"./lib/response.js": "./lib/response.js", | ||
"./lib/application": "./lib/application.js", | ||
"./lib/application.js": "./lib/application.js", | ||
"./lib/context": "./lib/context.js", | ||
"./lib/context.js": "./lib/context.js", | ||
"./*": "./*.js", | ||
@@ -51,3 +46,2 @@ "./*.js": "./*.js", | ||
"delegates": "^1.0.0", | ||
"depd": "^2.0.0", | ||
"destroy": "^1.0.4", | ||
@@ -59,5 +53,3 @@ "encodeurl": "^1.0.2", | ||
"http-errors": "^1.6.3", | ||
"is-generator-function": "^1.0.7", | ||
"koa-compose": "^4.1.0", | ||
"koa-convert": "^2.0.0", | ||
"on-finished": "^2.3.0", | ||
@@ -72,3 +64,2 @@ "only": "~0.0.2", | ||
"eslint": "^7.32.0", | ||
"eslint-config-koa": "^2.0.0", | ||
"eslint-config-standard": "^16.0.3", | ||
@@ -80,7 +71,7 @@ "eslint-plugin-import": "^2.18.2", | ||
"gen-esm-wrapper": "^1.0.6", | ||
"jest": "^27.0.6", | ||
"supertest": "^3.1.0" | ||
"jest": "^28.1.2", | ||
"supertest": "^6.2.4" | ||
}, | ||
"engines": { | ||
"node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" | ||
"node": ">= 12.17.0" | ||
}, | ||
@@ -87,0 +78,0 @@ "files": [ |
@@ -5,3 +5,3 @@ <img src="/docs/logo.png" alt="Koa middleware framework for nodejs"/> | ||
[![NPM version][npm-image]][npm-url] | ||
[![build status][travis-image]][travis-url] | ||
[![build status][github-action-image]][github-action-url] | ||
[![Test coverage][coveralls-image]][coveralls-url] | ||
@@ -21,3 +21,3 @@ [![OpenCollective Backers][backers-image]](#backers) | ||
Koa requires __node v7.6.0__ or higher for ES2015 and async function support. | ||
Koa requires __node v12.17.0__ or higher for ES2015 and async function support. | ||
@@ -45,6 +45,4 @@ ``` | ||
- [Kick-Off-Koa](https://github.com/koajs/kick-off-koa) - An intro to Koa via a set of self-guided workshops. | ||
- [Workshop](https://github.com/koajs/workshop) - A workshop to learn the basics of Koa, Express' spiritual successor. | ||
- [Introduction Screencast](https://knowthen.com/episode-3-koajs-quickstart-guide/) - An introduction to installing and getting started with Koa | ||
- [Guide](docs/guide.md) - Go straight to the docs. | ||
## Middleware | ||
@@ -187,2 +185,3 @@ | ||
- [KoaJS Slack Group](https://join.slack.com/t/koa-js/shared_invite/zt-5pjgthmb-1JeKDbByqqcARtlPbtf~vQ) | ||
- [Badgeboard](https://koajs.github.io/badgeboard) and list of official modules | ||
@@ -283,4 +282,4 @@ - [Examples](https://github.com/koajs/examples) | ||
[npm-url]: https://www.npmjs.com/package/koa | ||
[travis-image]: https://img.shields.io/travis/koajs/koa/master.svg?style=flat-square | ||
[travis-url]: https://travis-ci.org/koajs/koa | ||
[github-action-image]: https://github.com/koajs/koa/actions/workflows/node.js.yml/badge.svg | ||
[github-action-url]: https://github.com/koajs/koa/actions/workflows/node.js.yml | ||
[coveralls-image]: https://img.shields.io/codecov/c/github/koajs/koa.svg?style=flat-square | ||
@@ -287,0 +286,0 @@ [coveralls-url]: https://codecov.io/github/koajs/koa?branch=master |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
20
9
1626
60483
8
2
289
- Removeddepd@^2.0.0
- Removedis-generator-function@^1.0.7
- Removedkoa-convert@^2.0.0
- Removedco@4.6.0(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedis-generator-function@1.0.10(transitive)
- Removedkoa-convert@2.0.0(transitive)