From 586f2344df5d97587266139768b04f99f693c401 Mon Sep 17 00:00:00 2001 From: Nicolas Demers Date: Thu, 18 Apr 2024 08:50:24 -0400 Subject: [PATCH] update bug catcher on client side --- asset/negundo/js/debug.js | 132 +++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/asset/negundo/js/debug.js b/asset/negundo/js/debug.js index 55f7775..4fb3f3e 100644 --- a/asset/negundo/js/debug.js +++ b/asset/negundo/js/debug.js @@ -1,69 +1,85 @@ - -class ErrorHandler -{ +class ErrorHandler { constructor(options) { - if ( options ) { - if ( "url" in options ) { - this.url = options['url']; - } - else { - // throw une erreur ici - } - - if ( "apikey" in options ) { - this.apikey = options['apikey']; - } - else { - // throw une erreur ici - } - } + if (!options) throw new Error("Options not provided"); + if (!options.url) throw new Error("URL is required"); + if (!options.apikey) throw new Error("API key is required"); + this.url = options.url; + this.apikey = options.apikey; this.catchError(); } + getSourceCode(lineNumber) { + return this.getInlineSourceCode(lineNumber) || this.getFullSourceWithHighlight(lineNumber); + } + + getInlineSourceCode(lineNumber) { + const scripts = document.querySelectorAll('script'); + for (let script of scripts) { + if (!script.src) { + const scriptLines = script.textContent.split("\n"); + const scriptPosition = this.getErrorPosition(script); + if (lineNumber >= scriptPosition.startLine && lineNumber <= scriptPosition.endLine) { + return this.highlightSource(scriptLines, lineNumber - scriptPosition.startLine); + } + } + } + return null; + } + + getFullSourceWithHighlight(lineNumber) { + const lines = document.documentElement.outerHTML.split("\n"); + return this.highlightSource(lines, lineNumber - 1); + } + + highlightSource(lines, lineNumber) { + const start = Math.max(lineNumber - 2, 0); + const end = Math.min(lineNumber + 2, lines.length - 1); + lines[lineNumber] = '>> ' + lines[lineNumber] + ' <<'; + return lines.slice(start, end + 1).join("\n"); + } + + getErrorPosition(script) { + let totalLines = 0; + let element = script.previousElementSibling; + while (element) { + totalLines += (element.outerHTML || element.textContent).split("\n").length; + element = element.previousElementSibling; + } + return { + startLine: totalLines + 1, + endLine: totalLines + script.textContent.split("\n").length + }; + } + catchError() { - - console.log(this.url); - - window.onerror = function(message, url, line, column, error) { - // build l'url ET l'api key ensemble pour créer l'URL de réception de bug - - fetch(this.url ? this.url : window.location.href, { - method: "post", - headers: { - 'Accept': "application/json", - 'Content-Type': "application/json", - 'User-Agent': "NegundoClient/1.0" - }, - body: JSON.stringify({ - message: message, - url: url, - line: line, - column: column, - stack: error.stack, - location: window.location.toString() - }) - }).then( response => response ).then(data => { - console.info("Error reported", data); - }); - + window.onerror = (message, url, lineNumber, column, error) => { + this.reportError(message, url, lineNumber, column, error.stack, 'JavaScript Error'); return false; - }.bind(this); + }; + + window.addEventListener('unhandledrejection', event => { + this.reportError(event.reason.toString(), document.location.href, 0, 0, event.reason.stack, 'Promise Rejection'); + }); } - get url() { - return this._url; - } - - set url(set) { - return this._url = set; - } - - get apikey() { - return this._apikey; - } - - set apikey(set) { - return this._apikey = set; + reportError(message, url, lineNumber, column, stack, type = 'JavaScript Error') { + fetch(this.url ? `${location.protocol}//${this.url}/${this.apikey}` : window.location.href, { + method: "post", + headers: { + 'Accept': "application/json", + 'Content-Type': "application/json" + }, + body: JSON.stringify({ + type, + message, + url, + lineNumber, + column, + stack, + location: window.location.href, + source: this.getSourceCode(lineNumber) + }) + }).then(response => response.json()).then(console.info); } }