« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data
diff options
context:
space:
mode:
Diffstat (limited to 'src/data')
-rw-r--r--src/data/things/composite.js142
-rw-r--r--src/data/things/thing.js2
-rw-r--r--src/data/things/track.js53
3 files changed, 141 insertions, 56 deletions
diff --git a/src/data/things/composite.js b/src/data/things/composite.js
index cbbe6f8f..cfa557de 100644
--- a/src/data/things/composite.js
+++ b/src/data/things/composite.js
@@ -5,6 +5,7 @@ import {TupleMap} from '#wiki-data';
 
 import {
   isArray,
+  isString,
   isWholeNumber,
   oneOf,
   validateArrayItems,
@@ -1426,17 +1427,24 @@ export function debugComposite(fn) {
 // compositional step, the property will be exposed as undefined instead
 // of null.
 //
-export function exposeDependency({dependency}) {
-  return {
-    annotation: `exposeDependency`,
-    flags: {expose: true},
+export const exposeDependency = templateCompositeFrom({
+  annotation: `exposeDependency`,
 
-    expose: {
-      mapDependencies: {dependency},
-      compute: ({dependency}) => dependency,
+  compose: false,
+
+  inputs: {
+    dependency: input.staticDependency(),
+  },
+
+  steps: () => [
+    {
+      dependencies: [input('dependency')],
+      compute: ({
+        [input('dependency')]: dependency
+      }) => dependency,
     },
-  };
-}
+  ],
+});
 
 // Exposes a constant value exactly as it is; like exposeDependency, this
 // is typically the base of a composition serving as a particular property
@@ -1488,7 +1496,7 @@ export const withResultOfAvailabilityCheck = templateCompositeFrom({
       dependencies: [input('from'), input('mode')],
 
       compute: (continuation, {
-        [input('from')]: dependency,
+        [input('from')]: value,
         [input('mode')]: mode,
       }) => {
         let availability;
@@ -1591,7 +1599,7 @@ export const exitWithoutDependency = templateCompositeFrom({
 
     {
       dependencies: ['#availability', input('value')],
-      continuation: (continuation, {
+      compute: (continuation, {
         ['#availability']: availability,
         [input('value')]: value,
       }) =>
@@ -1628,9 +1636,13 @@ export const raiseOutputWithoutDependency = templateCompositeFrom({
   inputs: {
     dependency: input(),
     mode: input(availabilityCheckModeInput),
-    output: input({defaultValue: {}}),
+    output: input.staticValue({defaultValue: {}}),
   },
 
+  outputs: ({
+    [input.staticValue('output')]: output,
+  }) => Object.keys(output),
+
   steps: () => [
     withResultOfAvailabilityCheck({
       from: input('dependency'),
@@ -1657,9 +1669,13 @@ export const raiseOutputWithoutUpdateValue = templateCompositeFrom({
 
   inputs: {
     mode: input(availabilityCheckModeInput),
-    output: input({defaultValue: {}}),
+    output: input.staticValue({defaultValue: {}}),
   },
 
+  outputs: ({
+    [input.staticValue('output')]: output,
+  }) => Object.keys(output),
+
   steps: () => [
     withResultOfAvailabilityCheck({
       from: input.updateValue(),
@@ -1820,41 +1836,81 @@ export function withPropertyFromList({
 // Gets the listed properties from each of a list of objects, providing lists
 // of property values each into a dependency prefixed with the same name as the
 // list (by default). Like withPropertyFromList, this doesn't alter indices.
-export function withPropertiesFromList({
-  list,
-  properties,
-  prefix =
-    (list.startsWith('#')
-      ? list
-      : `#${list}`),
-}) {
-  return {
-    annotation: `withPropertiesFromList`,
-    flags: {expose: true, compose: true},
+export const withPropertiesFromList = templateCompositeFrom({
+  annotation: `withPropertiesFromList`,
 
-    expose: {
-      mapDependencies: {list},
-      options: {prefix, properties},
+  inputs: {
+    list: input({type: 'array'}),
+
+    properties: input({
+      validate: validateArrayItems(isString),
+    }),
 
-      compute(continuation, {list, '#options': {prefix, properties}}) {
-        const lists =
+    prefix: input({
+      type: 'string',
+      null: true,
+    }),
+  },
+
+  outputs: ({
+    [input.staticDependency('list')]: list,
+    [input.staticValue('properties')]: properties,
+    [input.staticValue('prefix')]: prefix,
+  }) =>
+    (properties
+      ? properties.map(property =>
+          (prefix
+            ? `${prefix}.${property}`
+         : list
+            ? `${list}.${property}`
+            : `#list.${property}`))
+      : '#lists'),
+
+  steps: () => [
+    {
+      dependencies: [input('list'), input('properties')],
+      compute: (continuation, {
+        [input('list')]: list,
+        [input('properties')]: properties,
+      }) => continuation({
+        ['#lists']:
           Object.fromEntries(
-            properties.map(property => [`${prefix}.${property}`, []]));
+            properties.map(property => [
+              property,
+              list.map(item => item[property] ?? null),
+            ])),
+      }),
+    },
 
-        for (const item of list) {
-          for (const property of properties) {
-            lists[`${prefix}.${property}`].push(
-              (item === null || item === undefined
-                ? null
-                : item[property] ?? null));
-          }
-        }
+    {
+      dependencies: [
+        input.staticDependency('list'),
+        input.staticValue('properties'),
+        input.staticValue('prefix'),
+        '#lists',
+      ],
 
-        return continuation(lists);
-      }
-    }
-  }
-}
+      compute: (continuation, {
+        [input.staticDependency('list')]: list,
+        [input.staticValue('properties')]: properties,
+        [input.staticValue('prefix')]: prefix,
+        ['#lists']: lists,
+      }) =>
+        (properties
+          ? continuation(
+              Object.fromEntries(
+                properties.map(property => [
+                  (prefix
+                    ? `${prefix}.${property}`
+                 : list
+                    ? `${list}.${property}`
+                    : `#list.${property}`),
+                  lists[property],
+                ])))
+          : continuation({'#lists': lists})),
+    },
+  ],
+});
 
 // Replaces items of a list, which are null or undefined, with some fallback
 // value, either a constant (set {value}) or from a dependency ({dependency}).
diff --git a/src/data/things/thing.js b/src/data/things/thing.js
index 265cfe18..f63a619d 100644
--- a/src/data/things/thing.js
+++ b/src/data/things/thing.js
@@ -363,7 +363,7 @@ export const contribsPresent = templateCompositeFrom({
 
   steps: () => [
     withResultOfAvailabilityCheck({
-      fromDependency: input('contribs'),
+      from: input('contribs'),
       mode: input.value('empty'),
     }),
 
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 05b762b9..f31fe3ae 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -68,10 +68,18 @@ export class Track extends Thing {
       }),
 
       withContainingTrackSection(),
-      withPropertyFromObject({object: '#trackSection', property: 'color'}),
+
+      withPropertyFromObject({
+        object: '#trackSection',
+        property: input.value('color'),
+      }),
+
       exposeDependencyOrContinue({dependency: '#trackSection.color'}),
 
-      withPropertyFromAlbum({property: 'color'}),
+      withPropertyFromAlbum({
+        property: input.value('color'),
+      }),
+
       exposeDependency({dependency: '#album.color'}),
     ],
 
@@ -127,9 +135,15 @@ export class Track extends Thing {
         validate: input.value(isFileExtension),
       }),
 
-      withPropertyFromAlbum({property: 'trackCoverArtFileExtension'}),
+      withPropertyFromAlbum({
+        property: input.value('trackCoverArtFileExtension'),
+      }),
+
       exposeDependencyOrContinue({dependency: '#album.trackCoverArtFileExtension'}),
-      exposeConstant({value: 'jpg'}),
+
+      exposeConstant({
+        value: input.value('jpg'),
+      }),
     ],
 
     // Date of cover art release. Like coverArtFileExtension, this represents
@@ -148,7 +162,10 @@ export class Track extends Thing {
         validate: input.value(isDate),
       }),
 
-      withPropertyFromAlbum({property: 'trackArtDate'}),
+      withPropertyFromAlbum({
+        property: input.value('trackArtDate'),
+      }),
+
       exposeDependency({dependency: '#album.trackArtDate'}),
     ],
 
@@ -185,7 +202,10 @@ export class Track extends Thing {
 
       exposeDependencyOrContinue({dependency: '#artistContribs'}),
 
-      withPropertyFromAlbum({property: 'artistContribs'}),
+      withPropertyFromAlbum({
+        property: input.value('artistContribs'),
+      }),
+
       exposeDependency({dependency: '#album.artistContribs'}),
     ],
 
@@ -208,7 +228,10 @@ export class Track extends Thing {
 
       exposeDependencyOrContinue({dependency: '#coverArtistContribs'}),
 
-      withPropertyFromAlbum({property: 'trackCoverArtistContribs'}),
+      withPropertyFromAlbum({
+        property: input.value('trackCoverArtistContribs'),
+      }),
+
       exposeDependency({dependency: '#album.trackCoverArtistContribs'}),
     ],
 
@@ -257,7 +280,11 @@ export class Track extends Thing {
 
     date: [
       exposeDependencyOrContinue({dependency: 'dateFirstReleased'}),
-      withPropertyFromAlbum({property: 'date'}),
+
+      withPropertyFromAlbum({
+        property: input.value('date'),
+      }),
+
       exposeDependency({dependency: '#album.date'}),
     ],
 
@@ -608,9 +635,7 @@ export const withHasUniqueCoverArt = templateCompositeFrom({
           : continuation()),
     },
 
-    withResolvedContribs({
-      from: 'coverArtistContribs',
-    }),
+    withResolvedContribs({from: 'coverArtistContribs'}),
 
     {
       dependencies: ['#resolvedContribs'],
@@ -625,7 +650,9 @@ export const withHasUniqueCoverArt = templateCompositeFrom({
             })),
     },
 
-    withPropertyFromAlbum({property: 'trackCoverArtistContribs'}),
+    withPropertyFromAlbum({
+      property: input.value('trackCoverArtistContribs'),
+    }),
 
     {
       dependencies: ['#album.trackCoverArtistContribs'],
@@ -663,6 +690,8 @@ export const exitWithoutUniqueCoverArt = templateCompositeFrom({
 export const trackReverseReferenceList = templateCompositeFrom({
   annotation: `trackReverseReferenceList`,
 
+  compose: false,
+
   inputs: {
     list: input({type: 'string'}),
   },