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.
@@ -55,11 +55,13 @@ export type ServerBug = {
55
55
  },
56
56
 
57
57
  // Error
58
- error: Error,
59
- stacktrace: string,
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-79",
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, Anomaly, CoreError } from '@common/errors';
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
- public async createBugReport( error: Error | CoreError | Anomaly, request?: ServerRequest ) {
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
- error: originalError,
376
- stacktrace: (originalError.stack || originalError.message || error.stack || error.message) as string,
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
- <b>Error</b>: ${report.error.message}<br />
400
- ${this.printHtml(report.stacktrace)}<br />
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.runtime.prettyFormatLogObj(log.args, this.logger.settings);
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");
@@ -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: LexicalState;
95
- if (typeof content === 'string' && content.trim().startsWith('{')) {
96
- try {
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
- const html = await this.jsonToHtml( json, options );
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"|"long-arrow-right"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"chart-bar"|"crosshairs"|"arrow-right"|"plus-circle"|"comments-alt"|"user-circle"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"link"|"key"|"user"|"at"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"file-alt"|"long-arrow-left"|"magnet"|"paper-plane"|"plus"|"calendar-alt"|"clock"|"cog"|"trash"|"ellipsis-h"|"binoculars"|"brands/linkedin"|"search"|"lightbulb"|"angle-up"|"angle-down"|"solid/crown"|"brands/discord"|"pen"|"file"|"envelope"|"coins"|"times-circle"|"angle-right"|"download"|"check"|"info-circle"|"check-circle"|"exclamation-circle"|"meh-rolling-eyes"|"arrow-left"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"power-off"|"bars"|"plane-departure"|"brands/whatsapp"|"wind"|"play"|"minus-circle"|"question-circle"|"external-link"|"exclamation-triangle"|"solid/check-circle"|"solid/exclamation-triangle"|"solid/times-circle"|"broom"|"comment-alt"|"minus"|"map-marker-alt"|"arrow-to-bottom"|"users"|"bug"|"solid/magic"|"briefcase"|"map-marker"|"fire"|"magic"|"globe"|"industry"|"calendar"|"building"|"graduation-cap"|"coin"|"unlink"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"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"
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"