« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/data/things/composite.js327
1 files changed, 153 insertions, 174 deletions
diff --git a/src/data/things/composite.js b/src/data/things/composite.js
index 0f943ec3..26be4a67 100644
--- a/src/data/things/composite.js
+++ b/src/data/things/composite.js
@@ -489,77 +489,75 @@ function validateInputValue(value, description) {
 export function templateCompositeFrom(description) {
   const compositionName = getCompositionName(description);
 
-  const descriptionAggregate = openAggregate({message: `Errors in description for ${compositionName}`});
-
-  if ('steps' in description) {
-    if (Array.isArray(description.steps)) {
-      descriptionAggregate.push(new TypeError(`Wrap steps array in a function`));
-    } else if (typeof description.steps !== 'function') {
-      descriptionAggregate.push(new TypeError(`Expected steps to be a function (returning an array)`));
+  withAggregate({message: `Errors in description for ${compositionName}`}, ({map, nest, push}) => {
+    if ('steps' in description) {
+      if (Array.isArray(description.steps)) {
+        push(new TypeError(`Wrap steps array in a function`));
+      } else if (typeof description.steps !== 'function') {
+        push(new TypeError(`Expected steps to be a function (returning an array)`));
+      }
     }
-  }
 
-  validateInputs:
-  if ('inputs' in description) {
-    if (Array.isArray(description.inputs)) {
-      descriptionAggregate.push(new Error(`Expected inputs to be object, got array`));
-      break validateInputs;
-    } else if (typeof description.inputs !== 'object') {
-      descriptionAggregate.push(new Error(`Expected inputs to be object, got ${typeof description.inputs}`));
-      break validateInputs;
-    }
+    validateInputs:
+    if ('inputs' in description) {
+      if (Array.isArray(description.inputs)) {
+        push(new Error(`Expected inputs to be object, got array`));
+        break validateInputs;
+      } else if (typeof description.inputs !== 'object') {
+        push(new Error(`Expected inputs to be object, got ${typeof description.inputs}`));
+        break validateInputs;
+      }
 
-    descriptionAggregate.nest({message: `Errors in static input descriptions for ${compositionName}`}, ({push}) => {
-      const missingCallsToInput = [];
-      const wrongCallsToInput = [];
+      nest({message: `Errors in static input descriptions for ${compositionName}`}, ({push}) => {
+        const missingCallsToInput = [];
+        const wrongCallsToInput = [];
 
-      for (const [name, value] of Object.entries(description.inputs)) {
-        if (!isInputToken(value)) {
-          missingCallsToInput.push(name);
-          continue;
+        for (const [name, value] of Object.entries(description.inputs)) {
+          if (!isInputToken(value)) {
+            missingCallsToInput.push(name);
+            continue;
+          }
+
+          if (!['input', 'input.staticDependency', 'input.staticValue'].includes(getInputTokenShape(value))) {
+            wrongCallsToInput.push(name);
+          }
         }
 
-        if (!['input', 'input.staticDependency', 'input.staticValue'].includes(getInputTokenShape(value))) {
-          wrongCallsToInput.push(name);
+        for (const name of missingCallsToInput) {
+          push(new Error(`${name}: Missing call to input()`));
         }
-      }
 
-      for (const name of missingCallsToInput) {
-        push(new Error(`${name}: Missing call to input()`));
-      }
+        for (const name of wrongCallsToInput) {
+          const shape = getInputTokenShape(description.inputs[name]);
+          push(new Error(`${name}: Expected call to input, input.staticDependency, or input.staticValue, got ${shape}`));
+        }
+      });
+    }
 
-      for (const name of wrongCallsToInput) {
-        const shape = getInputTokenShape(description.inputs[name]);
-        push(new Error(`${name}: Expected call to input, input.staticDependency, or input.staticValue, got ${shape}`));
+    validateOutputs:
+    if ('outputs' in description) {
+      if (
+        !Array.isArray(description.outputs) &&
+        typeof description.outputs !== 'function'
+      ) {
+        push(new Error(`Expected outputs to be array or function, got ${typeof description.outputs}`));
+        break validateOutputs;
       }
-    });
-  }
 
-  validateOutputs:
-  if ('outputs' in description) {
-    if (
-      !Array.isArray(description.outputs) &&
-      typeof description.outputs !== 'function'
-    ) {
-      descriptionAggregate.push(new Error(`Expected outputs to be array or function, got ${typeof description.outputs}`));
-      break validateOutputs;
-    }
-
-    if (Array.isArray(description.outputs)) {
-      descriptionAggregate.map(
-        description.outputs,
-        decorateErrorWithIndex(value => {
-          if (typeof value !== 'string') {
-            throw new Error(`${value}: Expected string, got ${typeof value}`)
-          } else if (!value.startsWith('#')) {
-            throw new Error(`${value}: Expected "#" at start`);
-          }
-        }),
-        {message: `Errors in output descriptions for ${compositionName}`});
+      if (Array.isArray(description.outputs)) {
+        map(
+          description.outputs,
+          decorateErrorWithIndex(value => {
+            if (typeof value !== 'string') {
+              throw new Error(`${value}: Expected string, got ${typeof value}`)
+            } else if (!value.startsWith('#')) {
+              throw new Error(`${value}: Expected "#" at start`);
+            }
+          }),
+          {message: `Errors in output descriptions for ${compositionName}`});
+      }
     }
-  }
-
-  descriptionAggregate.close();
+  });
 
   const expectedInputNames =
     (description.inputs
@@ -567,106 +565,104 @@ export function templateCompositeFrom(description) {
       : []);
 
   const instantiate = (inputOptions = {}) => {
-    const inputOptionsAggregate = openAggregate({message: `Errors in input options passed to ${compositionName}`});
-
-    const providedInputNames = Object.keys(inputOptions);
-
-    const misplacedInputNames =
-      providedInputNames
-        .filter(name => !expectedInputNames.includes(name));
-
-    const missingInputNames =
-      expectedInputNames
-        .filter(name => !providedInputNames.includes(name))
-        .filter(name => {
-          const inputDescription = description.inputs[name].value;
-          if (!inputDescription) return true;
-          if ('defaultValue' in inputDescription) return false;
-          if ('defaultDependency' in inputDescription) return false;
-          return true;
-        });
+    withAggregate({message: `Errors in input options passed to ${compositionName}`}, ({push}) => {
+      const providedInputNames = Object.keys(inputOptions);
+
+      const misplacedInputNames =
+        providedInputNames
+          .filter(name => !expectedInputNames.includes(name));
+
+      const missingInputNames =
+        expectedInputNames
+          .filter(name => !providedInputNames.includes(name))
+          .filter(name => {
+            const inputDescription = description.inputs[name].value;
+            if (!inputDescription) return true;
+            if ('defaultValue' in inputDescription) return false;
+            if ('defaultDependency' in inputDescription) return false;
+            return true;
+          });
 
-    const wrongTypeInputNames = [];
+      const wrongTypeInputNames = [];
 
-    const expectedStaticValueInputNames = [];
-    const expectedStaticDependencyInputNames = [];
+      const expectedStaticValueInputNames = [];
+      const expectedStaticDependencyInputNames = [];
 
-    const validateFailedInputNames = [];
-    const validateFailedErrors = [];
+      const validateFailedInputNames = [];
+      const validateFailedErrors = [];
 
-    for (const [name, value] of Object.entries(inputOptions)) {
-      if (misplacedInputNames.includes(name)) {
-        continue;
-      }
+      for (const [name, value] of Object.entries(inputOptions)) {
+        if (misplacedInputNames.includes(name)) {
+          continue;
+        }
 
-      if (typeof value !== 'string' && !isInputToken(value)) {
-        wrongTypeInputNames.push(name);
-        continue;
-      }
+        if (typeof value !== 'string' && !isInputToken(value)) {
+          wrongTypeInputNames.push(name);
+          continue;
+        }
 
-      const descriptionShape = getInputTokenShape(description.inputs[name]);
-      const descriptionValue = getInputTokenValue(description.inputs[name]);
+        const descriptionShape = getInputTokenShape(description.inputs[name]);
+        const descriptionValue = getInputTokenValue(description.inputs[name]);
 
-      const tokenShape = (isInputToken(value) ? getInputTokenShape(value) : null);
-      const tokenValue = (isInputToken(value) ? getInputTokenValue(value) : null);
+        const tokenShape = (isInputToken(value) ? getInputTokenShape(value) : null);
+        const tokenValue = (isInputToken(value) ? getInputTokenValue(value) : null);
 
-      if (descriptionShape === 'input.staticValue') {
-        if (tokenShape !== 'input.value') {
-          expectedStaticValueInputNames.push(name);
-          continue;
+        if (descriptionShape === 'input.staticValue') {
+          if (tokenShape !== 'input.value') {
+            expectedStaticValueInputNames.push(name);
+            continue;
+          }
         }
-      }
 
-      if (descriptionShape === 'input.staticDependency') {
-        if (typeof value !== 'string' && tokenShape !== 'input.dependency') {
-          expectedStaticDependencyInputNames.push(name);
-          continue;
+        if (descriptionShape === 'input.staticDependency') {
+          if (typeof value !== 'string' && tokenShape !== 'input.dependency') {
+            expectedStaticDependencyInputNames.push(name);
+            continue;
+          }
         }
-      }
 
-      if (descriptionValue && 'validate' in descriptionValue) {
-        if (tokenShape === 'input.value') {
-          try {
-            descriptionValue.validate(tokenValue);
-          } catch (error) {
-            validateFailedInputNames.push(name);
-            validateFailedErrors.push(error);
+        if (descriptionValue && 'validate' in descriptionValue) {
+          if (tokenShape === 'input.value') {
+            try {
+              descriptionValue.validate(tokenValue);
+            } catch (error) {
+              validateFailedInputNames.push(name);
+              validateFailedErrors.push(error);
+            }
           }
         }
       }
-    }
-
-    if (!empty(misplacedInputNames)) {
-      inputOptionsAggregate.push(new Error(`Unexpected input names: ${misplacedInputNames.join(', ')}`));
-    }
 
-    if (!empty(missingInputNames)) {
-      inputOptionsAggregate.push(new Error(`Required these inputs: ${missingInputNames.join(', ')}`));
-    }
+      if (!empty(misplacedInputNames)) {
+        push(new Error(`Unexpected input names: ${misplacedInputNames.join(', ')}`));
+      }
 
-    if (!empty(expectedStaticDependencyInputNames)) {
-      inputOptionsAggregate.push(new Error(`Expected static dependencies: ${expectedStaticDependencyInputNames.join(', ')}`));
-    }
+      if (!empty(missingInputNames)) {
+        push(new Error(`Required these inputs: ${missingInputNames.join(', ')}`));
+      }
 
-    if (!empty(expectedStaticValueInputNames)) {
-      inputOptionsAggregate.push(new Error(`Expected static values: ${expectedStaticValueInputNames.join(', ')}`));
-    }
+      if (!empty(expectedStaticDependencyInputNames)) {
+        push(new Error(`Expected static dependencies: ${expectedStaticDependencyInputNames.join(', ')}`));
+      }
 
-    for (const {name, validationError} of stitchArrays({
-      name: validateFailedInputNames,
-      validationError: validateFailedErrors,
-    })) {
-      const error = new Error(`${name}: Validation failed for static value`);
-      error.cause = validationError;
-      inputOptionsAggregate.push(error);
-    }
+      if (!empty(expectedStaticValueInputNames)) {
+        push(new Error(`Expected static values: ${expectedStaticValueInputNames.join(', ')}`));
+      }
 
-    for (const name of wrongTypeInputNames) {
-      const type = typeof inputOptions[name];
-      inputOptionsAggregate.push(new Error(`${name}: Expected string or input() call, got ${type}`));
-    }
+      for (const {name, validationError} of stitchArrays({
+        name: validateFailedInputNames,
+        validationError: validateFailedErrors,
+      })) {
+        const error = new Error(`${name}: Validation failed for static value`);
+        error.cause = validationError;
+        push(error);
+      }
 
-    inputOptionsAggregate.close();
+      for (const name of wrongTypeInputNames) {
+        const type = typeof inputOptions[name];
+        push(new Error(`${name}: Expected string or input() call, got ${type}`));
+      }
+    });
 
     const inputMetadata = getStaticInputMetadata(inputOptions);
 
@@ -694,48 +690,31 @@ export function templateCompositeFrom(description) {
       symbol: templateCompositeFrom.symbol,
 
       outputs(providedOptions) {
-        const outputOptionsAggregate = openAggregate({message: `Errors in output options passed to ${compositionName}`});
-
-        const misplacedOutputNames = [];
-        const wrongTypeOutputNames = [];
-        // const notPrivateOutputNames = [];
+        withAggregate({message: `Errors in output options passed to ${compositionName}`}, ({push}) => {
+          const misplacedOutputNames = [];
+          const wrongTypeOutputNames = [];
+
+          for (const [name, value] of Object.entries(providedOptions)) {
+            if (!expectedOutputNames.includes(name)) {
+              misplacedOutputNames.push(name);
+              continue;
+            }
 
-        for (const [name, value] of Object.entries(providedOptions)) {
-          if (!expectedOutputNames.includes(name)) {
-            misplacedOutputNames.push(name);
-            continue;
+            if (typeof value !== 'string') {
+              wrongTypeOutputNames.push(name);
+              continue;
+            }
           }
 
-          if (typeof value !== 'string') {
-            wrongTypeOutputNames.push(name);
-            continue;
+          if (!empty(misplacedOutputNames)) {
+            push(new Error(`Unexpected output names: ${misplacedOutputNames.join(', ')}`));
           }
 
-          /*
-          if (!value.startsWith('#')) {
-            notPrivateOutputNames.push(name);
-            continue;
+          for (const name of wrongTypeOutputNames) {
+            const type = typeof providedOptions[name];
+            push(new Error(`${name}: Expected string, got ${type}`));
           }
-          */
-        }
-
-        if (!empty(misplacedOutputNames)) {
-          outputOptionsAggregate.push(new Error(`Unexpected output names: ${misplacedOutputNames.join(', ')}`));
-        }
-
-        for (const name of wrongTypeOutputNames) {
-          const type = typeof providedOptions[name];
-          outputOptionsAggregate.push(new Error(`${name}: Expected string, got ${type}`));
-        }
-
-        /*
-        for (const name of notPrivateOutputNames) {
-          const into = providedOptions[name];
-          outputOptionsAggregate.push(new Error(`${name}: Expected "#" at start, got ${into}`));
-        }
-        */
-
-        outputOptionsAggregate.close();
+        });
 
         Object.assign(outputOptions, providedOptions);
         return instantiatedTemplate;