From 90a3a7ddfa0eb03445fe0a4a43a40d2a7ee913d7 Mon Sep 17 00:00:00 2001
From: mbehzad <mehran.behzad@diva-e.com>
Date: Tue, 25 Jun 2024 12:24:11 +0200
Subject: [PATCH] feat(assemble-lite): improve intergartion of error messages
 in webpack

---
 packages/assemble-lite/Assemble.js            | 46 +++++++++++++------
 packages/pv-stylemark/webpack-plugin/index.js |  3 ++
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/packages/assemble-lite/Assemble.js b/packages/assemble-lite/Assemble.js
index 5e43145..11dfeb8 100644
--- a/packages/assemble-lite/Assemble.js
+++ b/packages/assemble-lite/Assemble.js
@@ -47,6 +47,20 @@ module.exports = class Assemble {
     if (this.verbose) console.log("[Assemble-Lite] ", ...args);
   }
 
+  // first error message during build, will be used to throw when there was no custom onError handler and the build should hard fail
+  _errorMsg = null;
+  // call the optional provided callback function with the error message
+  error(msg, error) {
+    console.error(msg);
+    console.error(error);
+
+    const errorMsg = `${msg} :: ${error.message}`;
+
+    if (this.onError) this.onError?.(errorMsg);
+    // there is no custom error handler, throw and fail the build
+    else if (!this._errorMsg) this._errorMsg = errorMsg;
+  }
+
   /**
    * builds all the html pages, based on the provided arguments,
    * an re-uses cached items from the previous builds
@@ -60,6 +74,7 @@ module.exports = class Assemble {
    *     layouts,
    *     componentsTargetDirectory,
    *     pagesTargetDirectory,
+   *     onError?,
    *   }
    * @param {string[] | null} modifiedFiles - list of paths of files which have been modified compared to the last build
    * @memberof Assemble
@@ -75,11 +90,14 @@ module.exports = class Assemble {
       layouts,
       componentsTargetDirectory,
       pagesTargetDirectory,
+      onError,
     },
     modifiedFiles
   ) {
     this.log("--------------------------------");
     this.log("Build start ...");
+    this.onError = onError;
+    this._errorMsg = null;
 
     // use a timer to measure execution duration for individual tasks
     const timer = new Timer();
@@ -289,6 +307,8 @@ module.exports = class Assemble {
     );
     this.log("Build end. took:", timer.measure("BUILD", true), "s");
     this.log("--------------------------------");
+
+    if (this._errorMsg) throw this._errorMsg;
   }
 
   /**
@@ -449,10 +469,10 @@ module.exports = class Assemble {
         pvHandlebars.registerHelper(helperFn);
         this.helpers[getName(path)] = { path, name: getName(path) };
       } catch (error) {
-        console.error(
-          `[Assemble-Lite] Failed reading handlebars helper ${basename(path)}`
+        this.error(
+          `[Assemble-Lite] Failed reading handlebars helper ${basename(path)}`,
+          error
         );
-        console.error(error);
         // make sure on the next iteration, the helper is re-read,
         // so the user can't forget about this issue
         this.failedPaths.push(path);
@@ -483,10 +503,10 @@ module.exports = class Assemble {
             });
           }
         } catch (error) {
-          console.error(
-            `[assemble-lite] Failed reading data file ${basename(path)}`
+          this.error(
+            `[assemble-lite] Failed reading data file ${basename(path)}`,
+            error
           );
-          console.error(error);
           // make sure on the next iteration, the helper is re-read,
           // so the user can't forget about this issue (if it still exist)
           this.failedPaths.push(path);
@@ -520,8 +540,7 @@ module.exports = class Assemble {
         path
       )}`;
       const errorMarkup = `<!-- ${errorMessage} -->`;
-      console.error(errorMessage);
-      console.error(error);
+      this.error(errorMessage, error);
 
       return {
         clearedMarkup: errorMarkup,
@@ -545,11 +564,11 @@ module.exports = class Assemble {
         failed: false,
       };
     } catch (error) {
-      console.error();
-      const errorMessage = `[assemble-lite] error parsing ${filename}.hbs`;
+      const errorMessage = `[assemble-lite] error parsing ${basename(
+        filename
+      )}`;
       const errorMarkup = `<!-- ${errorMessage} -->`;
-      console.error(errorMessage);
-      console.error(error);
+      this.error(errorMessage, error);
 
       return {
         ast: pvHandlebars.parse(errorMarkup),
@@ -578,8 +597,7 @@ module.exports = class Assemble {
         const errorMessage = `[assemble-lite] failed to render template for ${basename(
           path
         )}`;
-        console.error(errorMessage);
-        console.error(error);
+        this.error(errorMessage, error);
 
         return `<!-- ${errorMessage} -->`;
       }
diff --git a/packages/pv-stylemark/webpack-plugin/index.js b/packages/pv-stylemark/webpack-plugin/index.js
index ea18d74..b5cdbce 100644
--- a/packages/pv-stylemark/webpack-plugin/index.js
+++ b/packages/pv-stylemark/webpack-plugin/index.js
@@ -54,6 +54,9 @@ class PvStylemarkPlugin {
             layouts: resolveApp(fileGlobes.assembleFiles.layouts),
             componentsTargetDirectory: resolveApp(join(destPath, "components")),
             pagesTargetDirectory: resolveApp(join(destPath, "pages")),
+            onError(errorMessage) {
+              compilation.errors.push(errorMessage);
+            },
           },
           this.firstRun ? null : changedAssembleFiles,
         );