@eggjs/onerror 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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/commonjs/agent.d.ts +6 -0
  4. package/dist/commonjs/agent.js +16 -0
  5. package/dist/commonjs/app.d.ts +12 -0
  6. package/dist/commonjs/app.js +150 -0
  7. package/dist/commonjs/config/config.default.d.ts +27 -0
  8. package/dist/commonjs/config/config.default.js +15 -0
  9. package/dist/commonjs/index.d.ts +1 -0
  10. package/dist/commonjs/index.js +4 -0
  11. package/dist/commonjs/lib/error_view.d.ts +154 -0
  12. package/dist/commonjs/lib/error_view.js +248 -0
  13. package/dist/commonjs/lib/onerror_page.mustache.html +761 -0
  14. package/dist/commonjs/lib/utils.d.ts +10 -0
  15. package/dist/commonjs/lib/utils.js +53 -0
  16. package/dist/commonjs/package.json +3 -0
  17. package/dist/commonjs/types.d.ts +7 -0
  18. package/dist/commonjs/types.js +3 -0
  19. package/dist/esm/agent.d.ts +6 -0
  20. package/dist/esm/agent.js +13 -0
  21. package/dist/esm/app.d.ts +12 -0
  22. package/dist/esm/app.js +144 -0
  23. package/dist/esm/config/config.default.d.ts +27 -0
  24. package/dist/esm/config/config.default.js +10 -0
  25. package/dist/esm/index.d.ts +1 -0
  26. package/dist/esm/index.js +2 -0
  27. package/dist/esm/lib/error_view.d.ts +154 -0
  28. package/dist/esm/lib/error_view.js +241 -0
  29. package/dist/esm/lib/onerror_page.mustache.html +761 -0
  30. package/dist/esm/lib/utils.d.ts +10 -0
  31. package/dist/esm/lib/utils.js +43 -0
  32. package/dist/esm/package.json +3 -0
  33. package/dist/esm/types.d.ts +7 -0
  34. package/dist/esm/types.js +2 -0
  35. package/dist/package.json +4 -0
  36. package/package.json +93 -0
  37. package/src/agent.ts +12 -0
  38. package/src/app.ts +160 -0
  39. package/src/config/config.default.ts +34 -0
  40. package/src/index.ts +1 -0
  41. package/src/lib/error_view.ts +281 -0
  42. package/src/lib/onerror_page.mustache.html +761 -0
  43. package/src/lib/utils.ts +47 -0
  44. package/src/types.ts +12 -0
  45. package/src/typings/index.d.ts +4 -0
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ // modify from https://github.com/poppinss/youch/blob/develop/src/Youch/index.js
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ErrorView = void 0;
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_util_1 = __importDefault(require("node:util"));
11
+ const cookie_1 = require("cookie");
12
+ const mustache_1 = __importDefault(require("mustache"));
13
+ const stack_trace_1 = __importDefault(require("stack-trace"));
14
+ const utils_js_1 = require("./utils.js");
15
+ const startingSlashRegex = /\\|\//;
16
+ class ErrorView {
17
+ ctx;
18
+ error;
19
+ request;
20
+ app;
21
+ assets;
22
+ viewTemplate;
23
+ codeContext = 5;
24
+ _filterHeaders = ['cookie', 'connection'];
25
+ constructor(ctx, error, template) {
26
+ this.ctx = ctx;
27
+ this.error = error;
28
+ this.request = ctx.request;
29
+ this.app = ctx.app;
30
+ this.assets = new Map();
31
+ this.viewTemplate = template;
32
+ }
33
+ /**
34
+ * get html error page
35
+ *
36
+ * @return {String} html page
37
+ */
38
+ toHTML() {
39
+ const stack = this.parseError();
40
+ const data = this.serializeData(stack, (frame, index) => {
41
+ const serializedFrame = this.serializeFrame(frame);
42
+ serializedFrame.classes = this.getFrameClasses(frame, index);
43
+ return serializedFrame;
44
+ });
45
+ return this.compileView(this.viewTemplate, {
46
+ ...data,
47
+ appInfo: this.serializeAppInfo(),
48
+ request: this.serializeRequest(),
49
+ });
50
+ }
51
+ /**
52
+ * compile view
53
+ *
54
+ * @param {String} tpl - template
55
+ * @param {Object} locals - data used by template
56
+ */
57
+ compileView(tpl, locals) {
58
+ return mustache_1.default.render(tpl, locals);
59
+ }
60
+ /**
61
+ * check if the frame is node native file.
62
+ *
63
+ * @param {Frame} frame - current frame
64
+ */
65
+ isNode(frame) {
66
+ if (frame.isNative()) {
67
+ return true;
68
+ }
69
+ const filename = frame.getFileName() || '';
70
+ return !node_path_1.default.isAbsolute(filename) && filename[0] !== '.';
71
+ }
72
+ /**
73
+ * check if the frame is app modules.
74
+ *
75
+ * @param {Object} frame - current frame
76
+ */
77
+ isApp(frame) {
78
+ if (this.isNode(frame)) {
79
+ return false;
80
+ }
81
+ const filename = frame.getFileName() || '';
82
+ return !filename.includes('node_modules' + node_path_1.default.sep);
83
+ }
84
+ /**
85
+ * cache file asserts
86
+ *
87
+ * @param {String} key - assert key
88
+ * @param {String} value - assert content
89
+ */
90
+ setAssets(key, value) {
91
+ this.assets.set(key, value);
92
+ }
93
+ /**
94
+ * get cache file asserts
95
+ *
96
+ * @param {String} key - assert key
97
+ */
98
+ getAssets(key) {
99
+ return this.assets.get(key);
100
+ }
101
+ /**
102
+ * get frame source
103
+ *
104
+ * @param {Object} frame - current frame
105
+ */
106
+ getFrameSource(frame) {
107
+ const filename = frame.getFileName();
108
+ const lineNumber = frame.getLineNumber();
109
+ let contents = this.getAssets(filename);
110
+ if (!contents) {
111
+ contents = node_fs_1.default.existsSync(filename) ? node_fs_1.default.readFileSync(filename, 'utf8') : '';
112
+ this.setAssets(filename, contents);
113
+ }
114
+ const lines = contents.split(/\r?\n/);
115
+ return {
116
+ pre: lines.slice(Math.max(0, lineNumber - (this.codeContext + 1)), lineNumber - 1),
117
+ line: lines[lineNumber - 1],
118
+ post: lines.slice(lineNumber, lineNumber + this.codeContext),
119
+ };
120
+ }
121
+ /**
122
+ * parse error and return frame stack
123
+ */
124
+ parseError() {
125
+ const stack = stack_trace_1.default.parse(this.error);
126
+ return stack.map((frame) => {
127
+ if (!this.isNode(frame)) {
128
+ frame.context = this.getFrameSource(frame);
129
+ }
130
+ return frame;
131
+ });
132
+ }
133
+ /**
134
+ * get stack context
135
+ *
136
+ * @param {Object} frame - current frame
137
+ */
138
+ getContext(frame) {
139
+ if (!frame.context) {
140
+ return {};
141
+ }
142
+ return {
143
+ start: frame.getLineNumber() - (frame.context.pre || []).length,
144
+ pre: frame.context.pre.join('\n'),
145
+ line: frame.context.line,
146
+ post: frame.context.post.join('\n'),
147
+ };
148
+ }
149
+ /**
150
+ * get frame classes, let view identify the frame
151
+ *
152
+ * @param {any} frame - current frame
153
+ * @param {any} index - current index
154
+ */
155
+ getFrameClasses(frame, index) {
156
+ const classes = [];
157
+ if (index === 0) {
158
+ classes.push('active');
159
+ }
160
+ if (!this.isApp(frame)) {
161
+ classes.push('native-frame');
162
+ }
163
+ return classes.join(' ');
164
+ }
165
+ /**
166
+ * serialize frame and return meaningful data
167
+ *
168
+ * @param {Object} frame - current frame
169
+ */
170
+ serializeFrame(frame) {
171
+ const filename = frame.getFileName();
172
+ const relativeFileName = filename.includes(process.cwd())
173
+ ? filename.replace(process.cwd(), '').replace(startingSlashRegex, '')
174
+ : filename;
175
+ const extname = node_path_1.default.extname(filename).replace('.', '');
176
+ return {
177
+ extname,
178
+ file: relativeFileName,
179
+ method: frame.getFunctionName(),
180
+ line: frame.getLineNumber(),
181
+ column: frame.getColumnNumber(),
182
+ context: this.getContext(frame),
183
+ classes: '',
184
+ };
185
+ }
186
+ /**
187
+ * serialize base data
188
+ *
189
+ * @param {Object} stack - frame stack
190
+ * @param {Function} frameFormatter - frame formatter function
191
+ */
192
+ serializeData(stack, frameFormatter) {
193
+ const code = Reflect.get(this.error, 'code') ?? Reflect.get(this.error, 'type');
194
+ let message = (0, utils_js_1.detectErrorMessage)(this.ctx, this.error);
195
+ if (code) {
196
+ message = `${message} (code: ${code})`;
197
+ }
198
+ return {
199
+ code,
200
+ message,
201
+ name: this.error.name,
202
+ status: this.error.status,
203
+ frames: stack instanceof Array ? stack.filter(frame => frame.getFileName()).map(frameFormatter) : [],
204
+ };
205
+ }
206
+ /**
207
+ * serialize request object
208
+ */
209
+ serializeRequest() {
210
+ const headers = [];
211
+ Object.keys(this.request.headers).forEach(key => {
212
+ if (this._filterHeaders.includes(key)) {
213
+ return;
214
+ }
215
+ headers.push({
216
+ key,
217
+ value: this.request.headers[key],
218
+ });
219
+ });
220
+ const parsedCookies = (0, cookie_1.parse)(this.request.headers.cookie || '');
221
+ const cookies = Object.keys(parsedCookies).map(key => {
222
+ return { key, value: parsedCookies[key] };
223
+ });
224
+ return {
225
+ url: this.request.url,
226
+ httpVersion: this.request.req.httpVersion,
227
+ method: this.request.method,
228
+ connection: this.request.headers.connection,
229
+ headers,
230
+ cookies,
231
+ };
232
+ }
233
+ /**
234
+ * serialize app info object
235
+ */
236
+ serializeAppInfo() {
237
+ let config = this.app.config;
238
+ if ('dumpConfigToObject' in this.app && typeof this.app.dumpConfigToObject === 'function') {
239
+ config = this.app.dumpConfigToObject().config.config;
240
+ }
241
+ return {
242
+ baseDir: this.app.config.baseDir,
243
+ config: node_util_1.default.inspect(config),
244
+ };
245
+ }
246
+ }
247
+ exports.ErrorView = ErrorView;
248
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3Jfdmlldy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvZXJyb3Jfdmlldy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsZ0ZBQWdGOzs7Ozs7QUFFaEYsc0RBQXlCO0FBQ3pCLDBEQUE2QjtBQUM3QiwwREFBNkI7QUFDN0IsbUNBQStCO0FBQy9CLHdEQUFnQztBQUNoQyw4REFBMEQ7QUFDMUQseUNBQWdEO0FBSWhELE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDO0FBWW5DLE1BQWEsU0FBUztJQUNwQixHQUFHLENBQVU7SUFDYixLQUFLLENBQWU7SUFDcEIsT0FBTyxDQUFxQjtJQUM1QixHQUFHLENBQWlCO0lBQ3BCLE1BQU0sQ0FBc0I7SUFDNUIsWUFBWSxDQUFTO0lBRXJCLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDaEIsY0FBYyxHQUFHLENBQUUsUUFBUSxFQUFFLFlBQVksQ0FBRSxDQUFDO0lBRTVDLFlBQVksR0FBWSxFQUFFLEtBQW1CLEVBQUUsUUFBZ0I7UUFDN0QsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUM7UUFDM0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDO1FBQ25CLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU07UUFDSixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDdEQsTUFB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