5htp-core 0.6.0-79 → 0.6.0-81
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/common/errors/index.tsx +4 -2
- package/package.json +1 -1
- package/server/app/container/console/index.ts +47 -41
- package/server/utils/rte.ts +24 -12
- package/types/icons.d.ts +1 -1
package/common/errors/index.tsx
CHANGED
|
@@ -55,11 +55,13 @@ export type ServerBug = {
|
|
|
55
55
|
},
|
|
56
56
|
|
|
57
57
|
// Error
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
title?: string,
|
|
59
|
+
errors: TCatchedError[],
|
|
60
60
|
logs: TJsonLog[],
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export type TCatchedError = Error | CoreError | Anomaly;
|
|
64
|
+
|
|
63
65
|
/*----------------------------------
|
|
64
66
|
- ERREURS
|
|
65
67
|
----------------------------------*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "5htp-core",
|
|
3
3
|
"description": "Convenient TypeScript framework designed for Performance and Productivity.",
|
|
4
|
-
"version": "0.6.0-
|
|
4
|
+
"version": "0.6.0-81",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@ import Ansi2Html from 'ansi-to-html';
|
|
|
17
17
|
// Core libs
|
|
18
18
|
import type ApplicationContainer from '..';
|
|
19
19
|
import context from '@server/context';
|
|
20
|
-
import type { ServerBug,
|
|
20
|
+
import type { ServerBug, TCatchedError, CoreError } from '@common/errors';
|
|
21
21
|
import type ServerRequest from '@server/services/router/request';
|
|
22
22
|
import { SqlError } from '@server/services/database/debug';
|
|
23
23
|
|
|
@@ -99,8 +99,6 @@ export type TJsonLog = {
|
|
|
99
99
|
|
|
100
100
|
const LogPrefix = '[console]'
|
|
101
101
|
|
|
102
|
-
const errorMailInterval = (1 * 60 * 60 * 1000); // 1 hour
|
|
103
|
-
|
|
104
102
|
const logLevels = {
|
|
105
103
|
'log': 0,
|
|
106
104
|
'info': 3,
|
|
@@ -144,13 +142,6 @@ export default class Console {
|
|
|
144
142
|
public logger!: Logger<ILogObj>;
|
|
145
143
|
// Buffers
|
|
146
144
|
public logs: TJsonLog[] = [];
|
|
147
|
-
// Bug ID => Timestamp latest send
|
|
148
|
-
private sentBugs: {[bugId: string]: number} = {};
|
|
149
|
-
|
|
150
|
-
// Old (still useful???)
|
|
151
|
-
/*public clients: TGuestLogs[] = [];
|
|
152
|
-
public requests: TRequestLogs[] = [];
|
|
153
|
-
public sqlQueries: TDbQueryLog[] = [];*/
|
|
154
145
|
|
|
155
146
|
/*----------------------------------
|
|
156
147
|
- LIFECYCLE
|
|
@@ -283,11 +274,9 @@ export default class Console {
|
|
|
283
274
|
this.logs = this.logs.slice(bufferOverflow);
|
|
284
275
|
}
|
|
285
276
|
|
|
286
|
-
|
|
277
|
+
// We don't prevent duplicates because we want to receive all variants of the same error
|
|
278
|
+
public async createBugReport( error: TCatchedError, request?: ServerRequest ) {
|
|
287
279
|
|
|
288
|
-
// Print error
|
|
289
|
-
const originalError = ('originalError' in error && error.originalError) ? error.originalError : error;
|
|
290
|
-
this.logger.error(LogPrefix, `Sending bug report for the following error:`, error, originalError);
|
|
291
280
|
/*const youchRes = new Youch(error, {});
|
|
292
281
|
const jsonResponse = await youchRes.toJSON()
|
|
293
282
|
console.log( forTerminal(jsonResponse, {
|
|
@@ -314,28 +303,6 @@ export default class Console {
|
|
|
314
303
|
if (application === undefined)
|
|
315
304
|
return console.error(LogPrefix, "Can't send bug report because the application is not instanciated");
|
|
316
305
|
|
|
317
|
-
// Print the error so it's accessible via logs
|
|
318
|
-
if (error instanceof SqlError) {
|
|
319
|
-
let printedQuery: string;
|
|
320
|
-
try {
|
|
321
|
-
printedQuery = this.printSql( error.query );
|
|
322
|
-
} catch (error) {
|
|
323
|
-
printedQuery = 'Failed to print query:' + (error || 'unknown error');
|
|
324
|
-
}
|
|
325
|
-
console.error(`Error caused by this query:`, printedQuery);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
if (('dataForDebugging' in error) && error.dataForDebugging !== undefined)
|
|
329
|
-
console.error(LogPrefix, `More data about the error:`, error.dataForDebugging);
|
|
330
|
-
|
|
331
|
-
// Prevent spamming the mailbox if infinite loop
|
|
332
|
-
const bugId = ['server', request?.user?.name, undefined, error.message].filter(e => !!e).join('::');
|
|
333
|
-
const lastSending = this.sentBugs[bugId];
|
|
334
|
-
this.sentBugs[bugId] = Date.now();
|
|
335
|
-
const shouldSendReport = lastSending === undefined || lastSending < Date.now() - errorMailInterval;
|
|
336
|
-
if (!shouldSendReport)
|
|
337
|
-
return;
|
|
338
|
-
|
|
339
306
|
// Get context
|
|
340
307
|
const now = new Date();
|
|
341
308
|
const hash = uuid();
|
|
@@ -345,6 +312,35 @@ export default class Console {
|
|
|
345
312
|
// Car cette denrière a plus de chances de provoquer une erreur
|
|
346
313
|
const logs = this.logs.filter(e => e.channel.channelId === channelId).slice(-100);
|
|
347
314
|
|
|
315
|
+
const errors: TCatchedError[] = []
|
|
316
|
+
let currentError: TCatchedError | undefined = error;
|
|
317
|
+
let title: string | undefined;
|
|
318
|
+
while (currentError !== undefined) {
|
|
319
|
+
|
|
320
|
+
this.logger.error(LogPrefix, `Sending bug report for the following error:`, currentError);
|
|
321
|
+
if (('dataForDebugging' in currentError) && currentError.dataForDebugging !== undefined)
|
|
322
|
+
console.error(LogPrefix, `More data about the error:`, currentError.dataForDebugging);
|
|
323
|
+
|
|
324
|
+
// Print the error so it's accessible via logs
|
|
325
|
+
if (currentError instanceof SqlError) {
|
|
326
|
+
let printedQuery: string;
|
|
327
|
+
try {
|
|
328
|
+
printedQuery = this.printSql( currentError.query );
|
|
329
|
+
} catch (error) {
|
|
330
|
+
printedQuery = 'Failed to print query:' + (error || 'unknown error');
|
|
331
|
+
}
|
|
332
|
+
console.error(`Error caused by this query:`, printedQuery);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (title === undefined)
|
|
336
|
+
title = currentError.message;
|
|
337
|
+
|
|
338
|
+
errors.push(currentError);
|
|
339
|
+
currentError = 'originalError' in currentError
|
|
340
|
+
? currentError.originalError
|
|
341
|
+
: undefined
|
|
342
|
+
}
|
|
343
|
+
|
|
348
344
|
const bugReport: ServerBug = {
|
|
349
345
|
|
|
350
346
|
// Context
|
|
@@ -372,8 +368,8 @@ export default class Console {
|
|
|
372
368
|
} : {}),
|
|
373
369
|
|
|
374
370
|
// Error
|
|
375
|
-
|
|
376
|
-
|
|
371
|
+
title,
|
|
372
|
+
errors,
|
|
377
373
|
logs
|
|
378
374
|
}
|
|
379
375
|
|
|
@@ -392,12 +388,22 @@ export default class Console {
|
|
|
392
388
|
----------------------------------*/
|
|
393
389
|
|
|
394
390
|
public bugToHtml( report: ServerBug ) {
|
|
391
|
+
|
|
395
392
|
return `
|
|
396
393
|
<b>Channel</b>: ${report.channelType} (${report.channelId})<br />
|
|
397
394
|
<b>User</b>: ${report.user ? (report.user.name + ' (' + report.user.email + ')') : 'Unknown'}<br />
|
|
398
395
|
<b>IP</b>: ${report.ip}<br />
|
|
399
|
-
|
|
400
|
-
${
|
|
396
|
+
|
|
397
|
+
${report.errors.map(e => `
|
|
398
|
+
<hr />
|
|
399
|
+
<b>Error</b>: ${e.message}<br />
|
|
400
|
+
${this.printHtml(e.stack || e.message)}<br />
|
|
401
|
+
${'dataForDebugging' in e ? `
|
|
402
|
+
<b>Data for debugging</b><br />
|
|
403
|
+
${this.jsonToHTML(e.dataForDebugging)}<br />
|
|
404
|
+
` : ''}
|
|
405
|
+
`).join('')}
|
|
406
|
+
|
|
401
407
|
${report.request ? `
|
|
402
408
|
<hr />
|
|
403
409
|
<b>Request</b>: ${report.request.method} ${report.request.url}<br />
|
|
@@ -433,7 +439,7 @@ Logs: ${this.config.enable ? `<br/>` + this.logsToHTML(report.logs) : 'Logs coll
|
|
|
433
439
|
});
|
|
434
440
|
|
|
435
441
|
// Print args as ANSI
|
|
436
|
-
const logArgsAndErrorsMarkup = this.logger
|
|
442
|
+
const logArgsAndErrorsMarkup = this.logger["runtime"].prettyFormatLogObj(log.args, this.logger.settings);
|
|
437
443
|
const logErrors = logArgsAndErrorsMarkup.errors;
|
|
438
444
|
const logArgs = logArgsAndErrorsMarkup.args;
|
|
439
445
|
const logErrorsStr = (logErrors.length > 0 && logArgs.length > 0 ? "\n" : "") + logErrors.join("\n");
|
package/server/utils/rte.ts
CHANGED
|
@@ -43,6 +43,7 @@ export type LexicalNode = {
|
|
|
43
43
|
|
|
44
44
|
type TRenderOptions = {
|
|
45
45
|
|
|
46
|
+
format?: 'html' | 'text', // Default = html
|
|
46
47
|
transform?: RteUtils["transformNode"],
|
|
47
48
|
|
|
48
49
|
render?: (
|
|
@@ -91,17 +92,9 @@ export class RteUtils {
|
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
// Parse content if string
|
|
94
|
-
let json
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
json = JSON.parse(content) as LexicalState;
|
|
98
|
-
} catch (error) {
|
|
99
|
-
throw new Anomaly("Invalid JSON format for the given JSON RTE content.");
|
|
100
|
-
}
|
|
101
|
-
} else if (content && typeof content === 'object' && content.root)
|
|
102
|
-
json = content;
|
|
103
|
-
else
|
|
104
|
-
return { html: '', json: content, ...assets };
|
|
95
|
+
let json = this.parseState(content);
|
|
96
|
+
if (json === false)
|
|
97
|
+
return { html: '', json: content, ...assets }
|
|
105
98
|
|
|
106
99
|
// Parse prev version if string
|
|
107
100
|
if (typeof options?.attachements?.prevVersion === 'string') {
|
|
@@ -128,11 +121,30 @@ export class RteUtils {
|
|
|
128
121
|
}
|
|
129
122
|
|
|
130
123
|
// Convert json to HTML
|
|
131
|
-
|
|
124
|
+
let html: string;
|
|
125
|
+
if (options.format === 'text')
|
|
126
|
+
html = await this.jsonToText( json.root );
|
|
127
|
+
else
|
|
128
|
+
html = await this.jsonToHtml( json, options );
|
|
132
129
|
|
|
133
130
|
return { html, json: content, ...assets };
|
|
134
131
|
}
|
|
135
132
|
|
|
133
|
+
private parseState( content: string | LexicalState ): LexicalState | false {
|
|
134
|
+
|
|
135
|
+
if (typeof content === 'string' && content.trim().startsWith('{')) {
|
|
136
|
+
try {
|
|
137
|
+
return JSON.parse(content) as LexicalState;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
throw new Anomaly("Invalid JSON format for the given JSON RTE content.");
|
|
140
|
+
}
|
|
141
|
+
} else if (content && typeof content === 'object' && content.root)
|
|
142
|
+
return content;
|
|
143
|
+
else
|
|
144
|
+
return false;
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
|
|
136
148
|
private async processContent(
|
|
137
149
|
node: LexicalNode,
|
|
138
150
|
parent: LexicalNode | null,
|
package/types/icons.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type TIcones = "times"|"solid/spinner-third"|"
|
|
1
|
+
export type TIcones = "long-arrow-right"|"times"|"solid/spinner-third"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"chart-bar"|"crosshairs"|"arrow-right"|"user-circle"|"plus-circle"|"comments-alt"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"link"|"file-alt"|"long-arrow-left"|"at"|"calendar-alt"|"paper-plane"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"key"|"user"|"magnet"|"plus"|"binoculars"|"brands/linkedin"|"clock"|"cog"|"trash"|"ellipsis-h"|"times-circle"|"search"|"lightbulb"|"solid/crown"|"brands/discord"|"pen"|"file"|"envelope"|"angle-up"|"angle-down"|"coins"|"angle-right"|"download"|"info-circle"|"check-circle"|"exclamation-circle"|"check"|"meh-rolling-eyes"|"arrow-left"|"users"|"bug"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"power-off"|"bars"|"question-circle"|"plane-departure"|"brands/whatsapp"|"wind"|"play"|"minus-circle"|"external-link"|"broom"|"exclamation-triangle"|"solid/check-circle"|"solid/exclamation-triangle"|"solid/times-circle"|"minus"|"comment-alt"|"arrow-to-bottom"|"map-marker-alt"|"solid/magic"|"briefcase"|"map-marker"|"fire"|"industry"|"calendar"|"magic"|"globe"|"building"|"graduation-cap"|"coin"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"unlink"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"
|