@midwayjs/koa 3.0.0-beta.6 → 3.0.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.
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupOnerror = void 0;
4
+ const http = require("http");
5
+ const utils_1 = require("./utils");
6
+ function setupOnerror(app, config, logger) {
7
+ const errorOptions = Object.assign({
8
+ // support customize accepts function
9
+ accepts() {
10
+ const fn = config.accepts || utils_1.accepts;
11
+ return fn(this);
12
+ },
13
+ /**
14
+ * default text error handler
15
+ * @param {Error} err
16
+ * @param ctx
17
+ */
18
+ text(err, ctx) {
19
+ // unset all headers, and set those specified
20
+ ctx.res._headers = {};
21
+ ctx.set(err.headers);
22
+ if ((0, utils_1.isProduction)(app)) {
23
+ ctx.body = http.STATUS_CODES[ctx.status];
24
+ }
25
+ else {
26
+ ctx.body = err.message;
27
+ }
28
+ },
29
+ /**
30
+ * default html error handler
31
+ * @param {Error} err
32
+ */
33
+ html(err, ctx) {
34
+ const status = (0, utils_1.detectStatus)(err);
35
+ if ((0, utils_1.isProduction)(app)) {
36
+ // 5xx
37
+ if (status >= 500) {
38
+ ctx.status = 500;
39
+ ctx.body = `<h2>Internal Server Error, real status: ${status}</h2>`;
40
+ return;
41
+ }
42
+ else {
43
+ // 4xx
44
+ ctx.status = status;
45
+ ctx.body = `<h2>${status} ${http.STATUS_CODES[status]}</h2>`;
46
+ return;
47
+ }
48
+ }
49
+ // show simple error format for unittest
50
+ if (app.getEnv() === 'unittest' || app.getEnv() === 'test') {
51
+ ctx.status = status;
52
+ ctx.body = `${err.name}: ${err.message}\n${err.stack}`;
53
+ return;
54
+ }
55
+ ctx.body = utils_1.tpl
56
+ .replace('{{status}}', (0, utils_1.escapeHtml)(err.status))
57
+ .replace('{{stack}}', (0, utils_1.escapeHtml)(err.stack));
58
+ ctx.type = 'html';
59
+ },
60
+ /**
61
+ * default json error handler
62
+ * @param {Error} err
63
+ * @param ctx
64
+ */
65
+ json(err, ctx) {
66
+ const status = (0, utils_1.detectStatus)(err);
67
+ const code = err.code || err.type;
68
+ if ((0, utils_1.isProduction)(app)) {
69
+ if (status >= 500) {
70
+ ctx.body = { code, message: http.STATUS_CODES[status] };
71
+ }
72
+ else {
73
+ ctx.body = { code, message: err.message };
74
+ }
75
+ }
76
+ else {
77
+ ctx.body = { code, message: err.message, stack: err.stack };
78
+ }
79
+ },
80
+ }, config);
81
+ app.on('error', (err, ctx) => {
82
+ ctx = ctx || app.createAnonymousContext();
83
+ const status = (0, utils_1.detectStatus)(err);
84
+ // 5xx
85
+ if (status >= 500) {
86
+ try {
87
+ ctx.logger.error(err);
88
+ }
89
+ catch (ex) {
90
+ logger.error(err);
91
+ logger.error(ex);
92
+ }
93
+ return;
94
+ }
95
+ // 4xx
96
+ try {
97
+ ctx.logger.warn(err);
98
+ }
99
+ catch (ex) {
100
+ logger.warn(err);
101
+ logger.error(ex);
102
+ }
103
+ });
104
+ app.context.onerror = function (err) {
105
+ // don't do anything if there is no error.
106
+ // this allows you to pass `this.onerror`
107
+ // to node-style callbacks.
108
+ if (err == null)
109
+ return;
110
+ // ignore all pedding request stream
111
+ if (this.req)
112
+ (0, utils_1.sendToWormhole)(this.req);
113
+ // wrap non-error object
114
+ if (!(err instanceof Error)) {
115
+ const newError = new Error('non-error thrown: ' + err);
116
+ // err maybe an object, try to copy the name, message and stack to the new error instance
117
+ if (err) {
118
+ if (err.name)
119
+ newError.name = err.name;
120
+ if (err.message)
121
+ newError.message = err.message;
122
+ if (err.stack)
123
+ newError.stack = err.stack;
124
+ if (err.status)
125
+ newError['status'] = err.status;
126
+ if (err.headers)
127
+ newError['headers'] = err.headers;
128
+ }
129
+ err = newError;
130
+ }
131
+ const headerSent = this.headerSent || !this.writable;
132
+ if (headerSent)
133
+ err.headerSent = true;
134
+ // delegate
135
+ app.emit('error', err, this);
136
+ // nothing we can do here other
137
+ // than delegate to the app-level
138
+ // handler and log.
139
+ if (headerSent)
140
+ return;
141
+ // ENOENT support
142
+ if (err.code === 'ENOENT')
143
+ err.status = 404;
144
+ if (typeof err.status !== 'number' || !http.STATUS_CODES[err.status]) {
145
+ err.status = 500;
146
+ }
147
+ this.status = err.status;
148
+ this.set(err.headers);
149
+ let type = 'text';
150
+ if (errorOptions.accepts) {
151
+ type = errorOptions.accepts.call(this, 'html', 'text', 'json');
152
+ }
153
+ else {
154
+ type = this.accepts('html', 'text', 'json');
155
+ }
156
+ type = type || 'text';
157
+ if (errorOptions.all) {
158
+ errorOptions.all.call(this, err, this);
159
+ }
160
+ else {
161
+ if (errorOptions.redirect && type !== 'json') {
162
+ this.redirect(errorOptions.redirect);
163
+ }
164
+ else {
165
+ errorOptions[type].call(this, err, this);
166
+ this.type = type;
167
+ }
168
+ }
169
+ if (type === 'json') {
170
+ this.body = JSON.stringify(this.body);
171
+ }
172
+ this.res.end(this.body);
173
+ };
174
+ }
175
+ exports.setupOnerror = setupOnerror;
176
+ //# sourceMappingURL=onerror.js.map
@@ -0,0 +1,14 @@
1
+ export declare function detectStatus(err: any): any;
2
+ export declare function accepts(ctx: any): "json" | "js" | "html";
3
+ export declare function sendToWormhole(stream: any): Promise<void>;
4
+ export declare function isProduction(app: any): boolean;
5
+ export declare const tpl = "\n<!DOCTYPE html>\n<html>\n <head>\n <title>Error - {{status}}</title>\n <meta name=\"viewport\" content=\"user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n\n <style>\n body {\n padding: 50px 80px;\n font: 14px \"Helvetica Neue\", Helvetica, sans-serif;\n }\n\n h1 {\n font-size: 2em;\n margin-bottom: 5px;\n }\n\n pre {\n font-size: .8em;\n }\n </style>\n </head>\n <body>\n <div id=\"error\">\n <h1>Error</h1>\n <p>Looks like something broke!</p>\n <pre>\n <code>\n{{stack}}\n </code>\n </pre>\n </div>\n </body>\n</html>";
6
+ /**
7
+ * Escape special characters in the given string of text.
8
+ *
9
+ * @param {string} string The string to escape for inserting into HTML
10
+ * @return {string}
11
+ * @public
12
+ */
13
+ export declare function escapeHtml(string: any): string;
14
+ //# sourceMappingURL=utils.d.ts.map
package/dist/utils.js ADDED
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.escapeHtml = exports.tpl = exports.isProduction = exports.sendToWormhole = exports.accepts = exports.detectStatus = void 0;
4
+ function detectStatus(err) {
5
+ // detect status
6
+ let status = err.status || 500;
7
+ if (status < 200) {
8
+ // invalid status consider as 500, like urllib will return -1 status
9
+ status = 500;
10
+ }
11
+ return status;
12
+ }
13
+ exports.detectStatus = detectStatus;
14
+ function accepts(ctx) {
15
+ if (ctx.acceptJSON)
16
+ return 'json';
17
+ if (ctx.acceptJSONP)
18
+ return 'js';
19
+ return 'html';
20
+ }
21
+ exports.accepts = accepts;
22
+ function sendToWormhole(stream) {
23
+ return new Promise(resolve => {
24
+ if (typeof stream.resume !== 'function') {
25
+ return resolve();
26
+ }
27
+ // unpipe it
28
+ stream.unpipe && stream.unpipe();
29
+ // enable resume first
30
+ stream.resume();
31
+ if (stream._readableState && stream._readableState.ended) {
32
+ return resolve();
33
+ }
34
+ if (!stream.readable || stream.destroyed) {
35
+ return resolve();
36
+ }
37
+ function cleanup() {
38
+ stream.removeListener('end', onEnd);
39
+ stream.removeListener('close', onEnd);
40
+ stream.removeListener('error', onError);
41
+ }
42
+ function onEnd() {
43
+ cleanup();
44
+ resolve();
45
+ }
46
+ function onError() {
47
+ cleanup();
48
+ resolve();
49
+ }
50
+ stream.on('end', onEnd);
51
+ stream.on('close', onEnd);
52
+ stream.on('error', onError);
53
+ });
54
+ }
55
+ exports.sendToWormhole = sendToWormhole;
56
+ function isProduction(app) {
57
+ return app.getEnv() !== 'local' && app.getEnv() !== 'unittest';
58
+ }
59
+ exports.isProduction = isProduction;
60
+ exports.tpl = `
61
+ <!DOCTYPE html>
62
+ <html>
63
+ <head>
64
+ <title>Error - {{status}}</title>
65
+ <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
66
+
67
+ <style>
68
+ body {
69
+ padding: 50px 80px;
70
+ font: 14px "Helvetica Neue", Helvetica, sans-serif;
71
+ }
72
+
73
+ h1 {
74
+ font-size: 2em;
75
+ margin-bottom: 5px;
76
+ }
77
+
78
+ pre {
79
+ font-size: .8em;
80
+ }
81
+ </style>
82
+ </head>
83
+ <body>
84
+ <div id="error">
85
+ <h1>Error</h1>
86
+ <p>Looks like something broke!</p>
87
+ <pre>
88
+ <code>
89
+ {{stack}}
90
+ </code>
91
+ </pre>
92
+ </div>
93
+ </body>
94
+ </html>`;
95
+ const matchHtmlRegExp = /["'&<>]/;
96
+ /**
97
+ * Escape special characters in the given string of text.
98
+ *
99
+ * @param {string} string The string to escape for inserting into HTML
100
+ * @return {string}
101
+ * @public
102
+ */
103
+ function escapeHtml(string) {
104
+ const str = '' + string;
105
+ const match = matchHtmlRegExp.exec(str);
106
+ if (!match) {
107
+ return str;
108
+ }
109
+ let escape;
110
+ let html = '';
111
+ let index = 0;
112
+ let lastIndex = 0;
113
+ for (index = match.index; index < str.length; index++) {
114
+ switch (str.charCodeAt(index)) {
115
+ case 34: // "
116
+ escape = '&quot;';
117
+ break;
118
+ case 38: // &
119
+ escape = '&amp;';
120
+ break;
121
+ case 39: // '
122
+ escape = '&#39;';
123
+ break;
124
+ case 60: // <
125
+ escape = '&lt;';
126
+ break;
127
+ case 62: // >
128
+ escape = '&gt;';
129
+ break;
130
+ default:
131
+ continue;
132
+ }
133
+ if (lastIndex !== index) {
134
+ html += str.substring(lastIndex, index);
135
+ }
136
+ lastIndex = index + 1;
137
+ html += escape;
138
+ }
139
+ return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
140
+ }
141
+ exports.escapeHtml = escapeHtml;
142
+ //# sourceMappingURL=utils.js.map
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@midwayjs/koa",
3
- "version": "3.0.0-beta.6",
3
+ "version": "3.0.0",
4
4
  "description": "Midway Web Framework for KOA",
5
5
  "main": "dist/index",
6
6
  "typings": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "test": "node --require=ts-node/register ../../node_modules/.bin/jest",
10
- "cov": "node --require=ts-node/register ../../node_modules/.bin/jest --coverage --forceExit",
9
+ "test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
10
+ "cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit",
11
11
  "ci": "npm run test"
12
12
  },
13
13
  "keywords": [
@@ -23,21 +23,20 @@
23
23
  ],
24
24
  "license": "MIT",
25
25
  "devDependencies": {
26
- "@midwayjs/decorator": "^3.0.0-beta.6",
27
- "@midwayjs/mock": "^3.0.0-beta.6",
28
- "@midwayjs/validate": "^3.0.0-beta.6",
29
- "@types/koa": "^2.11.4",
30
- "@types/koa-router": "^7.4.1",
31
- "fs-extra": "^8.0.1",
32
- "koa-bodyparser": "^4.3.0",
33
- "koa-qs": "^3.0.0"
26
+ "@midwayjs/decorator": "^3.0.0",
27
+ "@midwayjs/logger": "2.14.0",
28
+ "@midwayjs/mock": "^3.0.0",
29
+ "@types/koa": "2.13.4",
30
+ "@types/koa-router": "7.4.4",
31
+ "fs-extra": "10.0.0"
34
32
  },
35
33
  "dependencies": {
36
34
  "@koa/router": "^10.0.0",
37
- "@midwayjs/core": "^3.0.0-beta.6",
38
- "@midwayjs/logger": "^3.0.0-beta.6",
39
- "koa": "^2.13.0",
40
- "koa-onerror": "^4.1.0"
35
+ "@midwayjs/cookies": "1.0.1",
36
+ "@midwayjs/core": "^3.0.0",
37
+ "@midwayjs/session": "^3.0.0",
38
+ "koa": "2.13.4",
39
+ "koa-bodyparser": "4.3.0"
41
40
  },
42
41
  "author": "Harry Chen <czy88840616@gmail.com>",
43
42
  "repository": {
@@ -47,5 +46,5 @@
47
46
  "engines": {
48
47
  "node": ">=12"
49
48
  },
50
- "gitHead": "e4595d30b369e36bef21b36f2b3737d8bc2f802d"
49
+ "gitHead": "55c26029bccf7bbb739fa1597e8f418dafa2caa0"
51
50
  }