« get me outta code hell

sugar: expose and integrate async-adaptive error decorators - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-11-06 16:28:37 -0400
committer(quasar) nebula <qznebula@protonmail.com>2023-11-06 16:28:37 -0400
commit8d06ad886607e7acdf636e07719bd4fbae3de767 (patch)
tree15d669bd6d8b27120a549f5766395728d91ee729
parentab306affb06b9f94a2f6b8dc8607614949b3ab0e (diff)
sugar: expose and integrate async-adaptive error decorators
-rw-r--r--src/util/sugar.js88
1 files changed, 66 insertions, 22 deletions
diff --git a/src/util/sugar.js b/src/util/sugar.js
index d5f0fbd..9646be3 100644
--- a/src/util/sugar.js
+++ b/src/util/sugar.js
@@ -656,28 +656,6 @@ export function annotateErrorWithIndex(error, index) {
   });
 }
 
-export function decorateErrorWithIndex(fn) {
-  return (x, index, array) => {
-    try {
-      return fn(x, index, array);
-    } catch (error) {
-      annotateErrorWithIndex(error, index);
-      throw error;
-    }
-  };
-}
-
-export function decorateErrorWithCause(fn, cause) {
-  return (...args) => {
-    try {
-      return fn(...args);
-    } catch (error) {
-      error.cause = cause;
-      throw error;
-    }
-  };
-}
-
 export function annotateErrorWithFile(error, file) {
   return Object.assign(error, {
     [Symbol.for('hsmusic.annotateError.file')]:
@@ -690,6 +668,72 @@ export function annotateErrorWithFile(error, file) {
   });
 }
 
+export function asyncAdaptiveDecorateError(fn, callback) {
+  if (typeof callback !== 'function') {
+    throw new Error(`Expected callback to be a function, got ${typeAppearance(callback)}`);
+  }
+
+  const syncDecorated = function (...args) {
+    try {
+      return fn(...args);
+    } catch (caughtError) {
+      throw callback(caughtError, ...args);
+    }
+  };
+
+  const asyncDecorated = async function(...args) {
+    try {
+      return await fn(...args);
+    } catch (caughtError) {
+      throw callback(caughtError);
+    }
+  };
+
+  syncDecorated.async = asyncDecorated;
+
+  return syncDecorated;
+}
+
+export function decorateError(fn, callback) {
+  return asyncAdaptiveDecorateError(fn, callback);
+}
+
+export function asyncDecorateError(fn, callback) {
+  return asyncAdaptiveDecorateError(fn, callback).async;
+}
+
+export function decorateErrorWithAnnotation(fn, ...annotationCallbacks) {
+  return asyncAdaptiveDecorateError(fn,
+    (caughtError, ...args) =>
+      annotateError(caughtError,
+        ...annotationCallbacks
+          .map(callback => error => callback(error, ...args))));
+}
+
+export function decorateErrorWithIndex(fn) {
+  return decorateErrorWithAnnotation(fn,
+    (caughtError, _value, index) =>
+      annotateErrorWithIndex(caughtError, index));
+}
+
+export function decorateErrorWithCause(fn, cause) {
+  return asyncAdaptiveDecorateError(fn,
+    (caughtError) =>
+      Object.assign(caughtError, {cause}));
+}
+
+export function asyncDecorateErrorWithAnnotation(fn, ...annotationCallbacks) {
+  return decorateErrorWithAnnotation(fn, ...annotationCallbacks).async;
+}
+
+export function asyncDecorateErrorWithIndex(fn) {
+  return decorateErrorWithIndex(fn).async;
+}
+
+export function asyncDecorateErrorWithCause(fn, cause) {
+  return decorateErrorWithCause(fn, cause).async;
+}
+
 export function conditionallySuppressError(conditionFn, callbackFn) {
   return (...args) => {
     try {