koa 2.14.1 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/response.js CHANGED
@@ -1,24 +1,24 @@
1
1
 
2
- 'use strict';
2
+ 'use strict'
3
3
 
4
4
  /**
5
5
  * Module dependencies.
6
6
  */
7
7
 
8
- const contentDisposition = require('content-disposition');
9
- const getType = require('cache-content-type');
10
- const onFinish = require('on-finished');
11
- const escape = require('escape-html');
12
- const typeis = require('type-is').is;
13
- const statuses = require('statuses');
14
- const destroy = require('destroy');
15
- const assert = require('assert');
16
- const extname = require('path').extname;
17
- const vary = require('vary');
18
- const only = require('only');
19
- const util = require('util');
20
- const encodeUrl = require('encodeurl');
21
- const Stream = require('stream');
8
+ const contentDisposition = require('content-disposition')
9
+ const getType = require('cache-content-type')
10
+ const onFinish = require('on-finished')
11
+ const escape = require('escape-html')
12
+ const typeis = require('type-is').is
13
+ const statuses = require('statuses')
14
+ const destroy = require('destroy')
15
+ const assert = require('assert')
16
+ const extname = require('path').extname
17
+ const vary = require('vary')
18
+ const only = require('only')
19
+ const util = require('util')
20
+ const encodeUrl = require('encodeurl')
21
+ const Stream = require('stream')
22
22
 
23
23
  /**
24
24
  * Prototype.
@@ -33,8 +33,8 @@ module.exports = {
33
33
  * @api public
34
34
  */
35
35
 
36
- get socket() {
37
- return this.res.socket;
36
+ get socket () {
37
+ return this.res.socket
38
38
  },
39
39
 
40
40
  /**
@@ -44,11 +44,11 @@ module.exports = {
44
44
  * @api public
45
45
  */
46
46
 
47
- get header() {
48
- const { res } = this;
47
+ get header () {
48
+ const { res } = this
49
49
  return typeof res.getHeaders === 'function'
50
50
  ? res.getHeaders()
51
- : res._headers || {}; // Node < 7.7
51
+ : res._headers || {} // Node < 7.7
52
52
  },
53
53
 
54
54
  /**
@@ -58,8 +58,8 @@ module.exports = {
58
58
  * @api public
59
59
  */
60
60
 
61
- get headers() {
62
- return this.header;
61
+ get headers () {
62
+ return this.header
63
63
  },
64
64
 
65
65
  /**
@@ -69,8 +69,8 @@ module.exports = {
69
69
  * @api public
70
70
  */
71
71
 
72
- get status() {
73
- return this.res.statusCode;
72
+ get status () {
73
+ return this.res.statusCode
74
74
  },
75
75
 
76
76
  /**
@@ -80,15 +80,15 @@ module.exports = {
80
80
  * @api public
81
81
  */
82
82
 
83
- set status(code) {
84
- if (this.headerSent) return;
83
+ set status (code) {
84
+ if (this.headerSent) return
85
85
 
86
- assert(Number.isInteger(code), 'status code must be a number');
87
- assert(code >= 100 && code <= 999, `invalid status code: ${code}`);
88
- this._explicitStatus = true;
89
- this.res.statusCode = code;
90
- if (this.req.httpVersionMajor < 2) this.res.statusMessage = statuses[code];
91
- if (this.body && statuses.empty[code]) this.body = null;
86
+ assert(Number.isInteger(code), 'status code must be a number')
87
+ assert(code >= 100 && code <= 999, `invalid status code: ${code}`)
88
+ this._explicitStatus = true
89
+ this.res.statusCode = code
90
+ if (this.req.httpVersionMajor < 2) this.res.statusMessage = statuses[code]
91
+ if (this.body && statuses.empty[code]) this.body = null
92
92
  },
93
93
 
94
94
  /**
@@ -98,8 +98,8 @@ module.exports = {
98
98
  * @api public
99
99
  */
100
100
 
101
- get message() {
102
- return this.res.statusMessage || statuses[this.status];
101
+ get message () {
102
+ return this.res.statusMessage || statuses[this.status]
103
103
  },
104
104
 
105
105
  /**
@@ -109,8 +109,8 @@ module.exports = {
109
109
  * @api public
110
110
  */
111
111
 
112
- set message(msg) {
113
- this.res.statusMessage = msg;
112
+ set message (msg) {
113
+ this.res.statusMessage = msg
114
114
  },
115
115
 
116
116
  /**
@@ -120,8 +120,8 @@ module.exports = {
120
120
  * @api public
121
121
  */
122
122
 
123
- get body() {
124
- return this._body;
123
+ get body () {
124
+ return this._body
125
125
  },
126
126
 
127
127
  /**
@@ -131,56 +131,62 @@ module.exports = {
131
131
  * @api public
132
132
  */
133
133
 
134
- set body(val) {
135
- const original = this._body;
136
- this._body = val;
134
+ set body (val) {
135
+ const original = this._body
136
+ this._body = val
137
137
 
138
138
  // no content
139
- if (null == val) {
140
- if (!statuses.empty[this.status]) this.status = 204;
141
- if (val === null) this._explicitNullBody = true;
142
- this.remove('Content-Type');
143
- this.remove('Content-Length');
144
- this.remove('Transfer-Encoding');
145
- return;
139
+ if (val == null) {
140
+ if (!statuses.empty[this.status]) {
141
+ if (this.type === 'application/json') {
142
+ this._body = 'null'
143
+ return
144
+ }
145
+ this.status = 204
146
+ }
147
+ if (val === null) this._explicitNullBody = true
148
+ this.remove('Content-Type')
149
+ this.remove('Content-Length')
150
+ this.remove('Transfer-Encoding')
151
+ return
146
152
  }
147
153
 
148
154
  // set the status
149
- if (!this._explicitStatus) this.status = 200;
155
+ if (!this._explicitStatus) this.status = 200
150
156
 
151
157
  // set the content-type only if not yet set
152
- const setType = !this.has('Content-Type');
158
+ const setType = !this.has('Content-Type')
153
159
 
154
160
  // string
155
- if ('string' === typeof val) {
156
- if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text';
157
- this.length = Buffer.byteLength(val);
158
- return;
161
+ if (typeof val === 'string') {
162
+ if (setType) this.type = /^\s*</.test(val) ? 'html' : 'text'
163
+ this.length = Buffer.byteLength(val)
164
+ return
159
165
  }
160
166
 
161
167
  // buffer
162
168
  if (Buffer.isBuffer(val)) {
163
- if (setType) this.type = 'bin';
164
- this.length = val.length;
165
- return;
169
+ if (setType) this.type = 'bin'
170
+ this.length = val.length
171
+ return
166
172
  }
167
173
 
168
174
  // stream
169
175
  if (val instanceof Stream) {
170
- onFinish(this.res, destroy.bind(null, val));
171
- if (original != val) {
172
- val.once('error', err => this.ctx.onerror(err));
176
+ onFinish(this.res, destroy.bind(null, val))
177
+ if (original !== val) {
178
+ val.once('error', err => this.ctx.onerror(err))
173
179
  // overwriting
174
- if (null != original) this.remove('Content-Length');
180
+ if (original != null) this.remove('Content-Length')
175
181
  }
176
182
 
177
- if (setType) this.type = 'bin';
178
- return;
183
+ if (setType) this.type = 'bin'
184
+ return
179
185
  }
180
186
 
181
187
  // json
182
- this.remove('Content-Length');
183
- this.type = 'json';
188
+ this.remove('Content-Length')
189
+ this.type = 'json'
184
190
  },
185
191
 
186
192
  /**
@@ -190,9 +196,9 @@ module.exports = {
190
196
  * @api public
191
197
  */
192
198
 
193
- set length(n) {
199
+ set length (n) {
194
200
  if (!this.has('Transfer-Encoding')) {
195
- this.set('Content-Length', n);
201
+ this.set('Content-Length', n)
196
202
  }
197
203
  },
198
204
 
@@ -203,16 +209,16 @@ module.exports = {
203
209
  * @api public
204
210
  */
205
211
 
206
- get length() {
212
+ get length () {
207
213
  if (this.has('Content-Length')) {
208
- return parseInt(this.get('Content-Length'), 10) || 0;
214
+ return parseInt(this.get('Content-Length'), 10) || 0
209
215
  }
210
216
 
211
- const { body } = this;
212
- if (!body || body instanceof Stream) return undefined;
213
- if ('string' === typeof body) return Buffer.byteLength(body);
214
- if (Buffer.isBuffer(body)) return body.length;
215
- return Buffer.byteLength(JSON.stringify(body));
217
+ const { body } = this
218
+ if (!body || body instanceof Stream) return undefined
219
+ if (typeof body === 'string') return Buffer.byteLength(body)
220
+ if (Buffer.isBuffer(body)) return body.length
221
+ return Buffer.byteLength(JSON.stringify(body))
216
222
  },
217
223
 
218
224
  /**
@@ -222,8 +228,8 @@ module.exports = {
222
228
  * @api public
223
229
  */
224
230
 
225
- get headerSent() {
226
- return this.res.headersSent;
231
+ get headerSent () {
232
+ return this.res.headersSent
227
233
  },
228
234
 
229
235
  /**
@@ -233,10 +239,10 @@ module.exports = {
233
239
  * @api public
234
240
  */
235
241
 
236
- vary(field) {
237
- if (this.headerSent) return;
242
+ vary (field) {
243
+ if (this.headerSent) return
238
244
 
239
- vary(this.res, field);
245
+ vary(this.res, field)
240
246
  },
241
247
 
242
248
  /**
@@ -258,25 +264,25 @@ module.exports = {
258
264
  * @api public
259
265
  */
260
266
 
261
- redirect(url, alt) {
267
+ redirect (url, alt) {
262
268
  // location
263
- if ('back' === url) url = this.ctx.get('Referrer') || alt || '/';
264
- this.set('Location', encodeUrl(url));
269
+ if (url === 'back') url = this.ctx.get('Referrer') || alt || '/'
270
+ this.set('Location', encodeUrl(url))
265
271
 
266
272
  // status
267
- if (!statuses.redirect[this.status]) this.status = 302;
273
+ if (!statuses.redirect[this.status]) this.status = 302
268
274
 
269
275
  // html
270
276
  if (this.ctx.accepts('html')) {
271
- url = escape(url);
272
- this.type = 'text/html; charset=utf-8';
273
- this.body = `Redirecting to <a href="${url}">${url}</a>.`;
274
- return;
277
+ url = escape(url)
278
+ this.type = 'text/html; charset=utf-8'
279
+ this.body = `Redirecting to <a href="${url}">${url}</a>.`
280
+ return
275
281
  }
276
282
 
277
283
  // text
278
- this.type = 'text/plain; charset=utf-8';
279
- this.body = `Redirecting to ${url}.`;
284
+ this.type = 'text/plain; charset=utf-8'
285
+ this.body = `Redirecting to ${url}.`
280
286
  },
281
287
 
282
288
  /**
@@ -286,9 +292,9 @@ module.exports = {
286
292
  * @api public
287
293
  */
288
294
 
289
- attachment(filename, options) {
290
- if (filename) this.type = extname(filename);
291
- this.set('Content-Disposition', contentDisposition(filename, options));
295
+ attachment (filename, options) {
296
+ if (filename) this.type = extname(filename)
297
+ this.set('Content-Disposition', contentDisposition(filename, options))
292
298
  },
293
299
 
294
300
  /**
@@ -307,12 +313,12 @@ module.exports = {
307
313
  * @api public
308
314
  */
309
315
 
310
- set type(type) {
311
- type = getType(type);
316
+ set type (type) {
317
+ type = getType(type)
312
318
  if (type) {
313
- this.set('Content-Type', type);
319
+ this.set('Content-Type', type)
314
320
  } else {
315
- this.remove('Content-Type');
321
+ this.remove('Content-Type')
316
322
  }
317
323
  },
318
324
 
@@ -326,9 +332,9 @@ module.exports = {
326
332
  * @api public
327
333
  */
328
334
 
329
- set lastModified(val) {
330
- if ('string' === typeof val) val = new Date(val);
331
- this.set('Last-Modified', val.toUTCString());
335
+ set lastModified (val) {
336
+ if (typeof val === 'string') val = new Date(val)
337
+ this.set('Last-Modified', val.toUTCString())
332
338
  },
333
339
 
334
340
  /**
@@ -338,9 +344,9 @@ module.exports = {
338
344
  * @api public
339
345
  */
340
346
 
341
- get lastModified() {
342
- const date = this.get('last-modified');
343
- if (date) return new Date(date);
347
+ get lastModified () {
348
+ const date = this.get('last-modified')
349
+ if (date) return new Date(date)
344
350
  },
345
351
 
346
352
  /**
@@ -355,9 +361,9 @@ module.exports = {
355
361
  * @api public
356
362
  */
357
363
 
358
- set etag(val) {
359
- if (!/^(W\/)?"/.test(val)) val = `"${val}"`;
360
- this.set('ETag', val);
364
+ set etag (val) {
365
+ if (!/^(W\/)?"/.test(val)) val = `"${val}"`
366
+ this.set('ETag', val)
361
367
  },
362
368
 
363
369
  /**
@@ -367,8 +373,8 @@ module.exports = {
367
373
  * @api public
368
374
  */
369
375
 
370
- get etag() {
371
- return this.get('ETag');
376
+ get etag () {
377
+ return this.get('ETag')
372
378
  },
373
379
 
374
380
  /**
@@ -379,10 +385,10 @@ module.exports = {
379
385
  * @api public
380
386
  */
381
387
 
382
- get type() {
383
- const type = this.get('Content-Type');
384
- if (!type) return '';
385
- return type.split(';', 1)[0];
388
+ get type () {
389
+ const type = this.get('Content-Type')
390
+ if (!type) return ''
391
+ return type.split(';', 1)[0]
386
392
  },
387
393
 
388
394
  /**
@@ -395,8 +401,8 @@ module.exports = {
395
401
  * @api public
396
402
  */
397
403
 
398
- is(type, ...types) {
399
- return typeis(this.type, type, ...types);
404
+ is (type, ...types) {
405
+ return typeis(this.type, type, ...types)
400
406
  },
401
407
 
402
408
  /**
@@ -411,12 +417,12 @@ module.exports = {
411
417
  * // => "text/plain"
412
418
  *
413
419
  * @param {String} field
414
- * @return {String}
420
+ * @return {any}
415
421
  * @api public
416
422
  */
417
423
 
418
- get(field) {
419
- return this.header[field.toLowerCase()] || '';
424
+ get (field) {
425
+ return this.res.getHeader(field)
420
426
  },
421
427
 
422
428
  /**
@@ -436,11 +442,11 @@ module.exports = {
436
442
  * @api public
437
443
  */
438
444
 
439
- has(field) {
445
+ has (field) {
440
446
  return typeof this.res.hasHeader === 'function'
441
447
  ? this.res.hasHeader(field)
442
448
  // Node < 7.7
443
- : field.toLowerCase() in this.headers;
449
+ : field.toLowerCase() in this.headers
444
450
  },
445
451
 
446
452
  /**
@@ -458,16 +464,16 @@ module.exports = {
458
464
  * @api public
459
465
  */
460
466
 
461
- set(field, val) {
462
- if (this.headerSent) return;
467
+ set (field, val) {
468
+ if (this.headerSent) return
463
469
 
464
- if (2 === arguments.length) {
465
- if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v));
466
- else if (typeof val !== 'string') val = String(val);
467
- this.res.setHeader(field, val);
470
+ if (arguments.length === 2) {
471
+ if (Array.isArray(val)) val = val.map(v => typeof v === 'string' ? v : String(v))
472
+ else if (typeof val !== 'string') val = String(val)
473
+ this.res.setHeader(field, val)
468
474
  } else {
469
475
  for (const key in field) {
470
- this.set(key, field[key]);
476
+ this.set(key, field[key])
471
477
  }
472
478
  }
473
479
  },
@@ -488,16 +494,16 @@ module.exports = {
488
494
  * @api public
489
495
  */
490
496
 
491
- append(field, val) {
492
- const prev = this.get(field);
497
+ append (field, val) {
498
+ const prev = this.get(field)
493
499
 
494
500
  if (prev) {
495
501
  val = Array.isArray(prev)
496
502
  ? prev.concat(val)
497
- : [prev].concat(val);
503
+ : [prev].concat(val)
498
504
  }
499
505
 
500
- return this.set(field, val);
506
+ return this.set(field, val)
501
507
  },
502
508
 
503
509
  /**
@@ -507,10 +513,10 @@ module.exports = {
507
513
  * @api public
508
514
  */
509
515
 
510
- remove(field) {
511
- if (this.headerSent) return;
516
+ remove (field) {
517
+ if (this.headerSent) return
512
518
 
513
- this.res.removeHeader(field);
519
+ this.res.removeHeader(field)
514
520
  },
515
521
 
516
522
  /**
@@ -522,19 +528,19 @@ module.exports = {
522
528
  * @api private
523
529
  */
524
530
 
525
- get writable() {
531
+ get writable () {
526
532
  // can't write any more after response finished
527
533
  // response.writableEnded is available since Node > 12.9
528
534
  // https://nodejs.org/api/http.html#http_response_writableended
529
535
  // response.finished is undocumented feature of previous Node versions
530
536
  // https://stackoverflow.com/questions/16254385/undocumented-response-finished-in-node-js
531
- if (this.res.writableEnded || this.res.finished) return false;
537
+ if (this.res.writableEnded || this.res.finished) return false
532
538
 
533
- const socket = this.res.socket;
539
+ const socket = this.res.socket
534
540
  // There are already pending outgoing res, but still writable
535
541
  // https://github.com/nodejs/node/blob/v4.4.7/lib/_http_server.js#L486
536
- if (!socket) return true;
537
- return socket.writable;
542
+ if (!socket) return true
543
+ return socket.writable
538
544
  },
539
545
 
540
546
  /**
@@ -544,11 +550,11 @@ module.exports = {
544
550
  * @api public
545
551
  */
546
552
 
547
- inspect() {
548
- if (!this.res) return;
549
- const o = this.toJSON();
550
- o.body = this.body;
551
- return o;
553
+ inspect () {
554
+ if (!this.res) return
555
+ const o = this.toJSON()
556
+ o.body = this.body
557
+ return o
552
558
  },
553
559
 
554
560
  /**
@@ -558,22 +564,22 @@ module.exports = {
558
564
  * @api public
559
565
  */
560
566
 
561
- toJSON() {
567
+ toJSON () {
562
568
  return only(this, [
563
569
  'status',
564
570
  'message',
565
571
  'header'
566
- ]);
572
+ ])
567
573
  },
568
574
 
569
575
  /**
570
576
  * Flush any set headers and begin the body
571
577
  */
572
578
 
573
- flushHeaders() {
574
- this.res.flushHeaders();
579
+ flushHeaders () {
580
+ this.res.flushHeaders()
575
581
  }
576
- };
582
+ }
577
583
 
578
584
  /**
579
585
  * Custom inspection implementation for node 6+.
@@ -584,5 +590,5 @@ module.exports = {
584
590
 
585
591
  /* istanbul ignore else */
586
592
  if (util.inspect.custom) {
587
- module.exports[util.inspect.custom] = module.exports.inspect;
593
+ module.exports[util.inspect.custom] = module.exports.inspect
588
594
  }
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "koa",
3
- "version": "2.14.1",
3
+ "version": "3.0.0-alpha.0",
4
+ "publishConfig": {
5
+ "tag": "experimental"
6
+ },
4
7
  "description": "Koa web app framework",
5
8
  "main": "lib/application.js",
6
9
  "exports": {
@@ -8,14 +11,6 @@
8
11
  "require": "./lib/application.js",
9
12
  "import": "./dist/koa.mjs"
10
13
  },
11
- "./lib/request": "./lib/request.js",
12
- "./lib/request.js": "./lib/request.js",
13
- "./lib/response": "./lib/response.js",
14
- "./lib/response.js": "./lib/response.js",
15
- "./lib/application": "./lib/application.js",
16
- "./lib/application.js": "./lib/application.js",
17
- "./lib/context": "./lib/context.js",
18
- "./lib/context.js": "./lib/context.js",
19
14
  "./*": "./*.js",
20
15
  "./*.js": "./*.js",
21
16
  "./package": "./package.json",
@@ -47,16 +42,13 @@
47
42
  "cookies": "~0.8.0",
48
43
  "debug": "^4.3.2",
49
44
  "delegates": "^1.0.0",
50
- "depd": "^2.0.0",
51
45
  "destroy": "^1.0.4",
52
46
  "encodeurl": "^1.0.2",
53
47
  "escape-html": "^1.0.3",
54
48
  "fresh": "~0.5.2",
55
49
  "http-assert": "^1.3.0",
56
50
  "http-errors": "^1.6.3",
57
- "is-generator-function": "^1.0.7",
58
51
  "koa-compose": "^4.1.0",
59
- "koa-convert": "^2.0.0",
60
52
  "on-finished": "^2.3.0",
61
53
  "only": "~0.0.2",
62
54
  "parseurl": "^1.3.2",
@@ -66,18 +58,17 @@
66
58
  },
67
59
  "devDependencies": {
68
60
  "eslint": "^7.32.0",
69
- "eslint-config-koa": "^2.0.0",
70
61
  "eslint-config-standard": "^16.0.3",
71
62
  "eslint-plugin-import": "^2.18.2",
72
63
  "eslint-plugin-node": "^11.1.0",
73
64
  "eslint-plugin-promise": "^5.1.0",
74
65
  "eslint-plugin-standard": "^5.0.0",
75
66
  "gen-esm-wrapper": "^1.0.6",
76
- "jest": "^27.0.6",
77
- "supertest": "^3.1.0"
67
+ "jest": "^28.1.2",
68
+ "supertest": "^6.2.4"
78
69
  },
79
70
  "engines": {
80
- "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
71
+ "node": ">= 12.17.0"
81
72
  },
82
73
  "files": [
83
74
  "dist",