« get me outta code hell

data: MORE composite wip - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/things/thing.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-09-18 13:26:18 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-09-18 13:26:18 -0300
commitfd102ee597e2ad2ba8f0950ce1a16fd34029963d (patch)
tree09c1ee833e9d8cc1cc9f01503ef3d584dd034d1e /src/data/things/thing.js
parentb4dd9d3f288130acdd9fefa2321b4b547f348b32 (diff)
data: MORE composite wip
Diffstat (limited to 'src/data/things/thing.js')
-rw-r--r--src/data/things/thing.js265
1 files changed, 118 insertions, 147 deletions
diff --git a/src/data/things/thing.js b/src/data/things/thing.js
index 45e9123..a5f0b78 100644
--- a/src/data/things/thing.js
+++ b/src/data/things/thing.js
@@ -5,7 +5,7 @@ import {inspect} from 'node:util';
 
 import {colors} from '#cli';
 import find from '#find';
-import {empty, stitchArrays, unique} from '#sugar';
+import {stitchArrays, unique} from '#sugar';
 import {filterMultipleArrays, getKebabCase} from '#wiki-data';
 import {oneOf} from '#validators';
 
@@ -253,6 +253,18 @@ export function additionalFiles() {
   };
 }
 
+const thingClassInput = {
+  validate(thingClass) {
+    isType(thingClass, 'function');
+
+    if (!Object.hasOwn(thingClass, Thing.referenceType)) {
+      throw new TypeError(`Expected a Thing constructor, missing Thing.referenceType`);
+    }
+
+    return true;
+  },
+};
+
 // A reference list! Keep in mind this is for general references to wiki
 // objects of (usually) other Thing subclasses, not specifically leitmotif
 // references in tracks (although that property uses referenceList too!).
@@ -267,18 +279,7 @@ export const referenceList = templateCompositeFrom({
   compose: false,
 
   inputs: {
-    class: input({
-      validate(thingClass) {
-        isType(thingClass, 'function');
-
-        if (!Object.hasOwn(thingClass, Thing.referenceType)) {
-          throw new TypeError(`Expected a Thing constructor, missing Thing.referenceType`);
-        }
-
-        return true;
-      },
-    }),
-
+    class: input(thingClassInput),
     find: input({type: 'function'}),
 
     // todo: validate
@@ -300,127 +301,100 @@ export const referenceList = templateCompositeFrom({
 
   steps: () => [
     withResolvedReferenceList({
-      list: '#updateValue',
-      data: '#composition.data',
-      find: '#composition.findFunction',
+      list: input.updateValue(),
+      data: input('data'),
+      find: input('find'),
     }),
 
     exposeDependency({dependency: '#resolvedReferenceList'}),
   ],
-})
-export function referenceList({
-  class: thingClass,
-  data,
-  find: findFunction,
-}) {
-  return compositeFrom({
-    annotation: `referenceList`,
-
-    mapDependencies: {
-      '#composition.data': data,
-    },
-
-    constantDependencies: {
-      '#composition.findFunction': findFunction,
-    },
-
-    steps: () => [
-      withUpdateValueAsDependency(),
-    ],
-  });
-}
+});
 
 // Corresponding function for a single reference.
-export function singleReference({
-  class: thingClass,
-  data,
-  find: findFunction,
-}) {
-  if (!thingClass) {
-    throw new TypeError(`Expected a Thing class`);
-  }
+export const singleReference = templateCompositeFrom({
+  annotation: `singleReference`,
 
-  const {[Thing.referenceType]: referenceType} = thingClass;
-  if (!referenceType) {
-    throw new Error(`The passed constructor ${thingClass.name} doesn't define Thing.referenceType!`);
-  }
+  compose: false,
 
-  return compositeFrom({
-    annotation: `singleReference`,
+  inputs: {
+    class: input(thingClassInput),
+    find: input({type: 'function'}),
 
-    update: {
-      validate: validateReference(referenceType),
-    },
+    // todo: validate
+    data: input(),
+  },
 
-    mapDependencies: {
-      '#composition.data': data,
-    },
+  update: {
+    dependencies: [
+      input.staticValue('class'),
+    ],
 
-    constantDependencies: {
-      '#composition.findFunction': findFunction,
+    compute({
+      [input.staticValue('class')]: thingClass,
+    }) {
+      const {[Thing.referenceType]: referenceType} = thingClass;
+      return {validate: validateReference(referenceType)};
     },
+  },
 
-    steps: () => [
-      withUpdateValueAsDependency(),
-
-      withResolvedReference({
-        ref: '#updateValue',
-        data: '#composition.data',
-        find: '#composition.findFunction',
-      }),
+  steps: () => [
+    withResolvedReference({
+      ref: input.updateValue(),
+      data: input('data'),
+      find: input('findFunction'),
+    }),
 
-      exposeDependency({dependency: '#resolvedReference'}),
-    ],
-  });
-}
+    exposeDependency({dependency: '#resolvedReference'}),
+  ],
+});
 
 // Nice 'n simple shorthand for an exposed-only flag which is true when any
 // contributions are present in the specified property.
-export function contribsPresent({
-  contribs,
-}) {
-  return compositeFrom({
-    annotation: `contribsPresent`,
+export const contribsPresent = templateCompositeFrom({
+  annotation: `contribsPresent`,
 
-    mapDependencies: {
-      '#composition.contribs': contribs,
-    },
+  compose: false,
 
-    steps: () => [
-      withResultOfAvailabilityCheck({
-        fromDependency: '#composition.contribs',
-        mode: 'empty',
-      }),
+  inputs: {
+    contribs: input({type: 'string'}),
+  },
 
-      exposeDependency({dependency: '#availability'}),
-    ],
-  });
-}
+  steps: () => [
+    withResultOfAvailabilityCheck({
+      fromDependency: input('contribs'),
+      mode: input.value('empty'),
+    }),
+
+    exposeDependency({dependency: '#availability'}),
+  ],
+});
 
 // Neat little shortcut for "reversing" the reference lists stored on other
 // things - for example, tracks specify a "referenced tracks" property, and
 // you would use this to compute a corresponding "referenced *by* tracks"
 // property. Naturally, the passed ref list property is of the things in the
 // wiki data provided, not the requesting Thing itself.
-export function reverseReferenceList({data, list}) {
-  return compositeFrom({
-    annotation: `reverseReferenceList`,
+export const reverseReferenceList = templateCompositeFrom({
+  annotation: `reverseReferenceList`,
 
-    mapDependencies: {
-      '#composition.data': data,
-      '#composition.list': list,
-    },
+  compose: false,
 
-    steps: () => [
-      withReverseReferenceList({
-        data: '#composition.data',
-        list: '#composition.list',
-      }),
+  inputs: {
+    // todo: validate
+    data: input(),
 
-      exposeDependency({dependency: '#reverseReferenceList'}),
-    ],
-  });
-}
+    list: input({type: 'string'}),
+  },
+
+  steps: () => [
+    withReverseReferenceList({
+      data: input('data'),
+      list: input('list'),
+    }),
+
+    exposeDependency({dependency: '#reverseReferenceList'}),
+  ],
+});
 
 // General purpose wiki data constructor, for properties like artistData,
 // trackData, etc.
@@ -436,53 +410,50 @@ export function wikiData(thingClass) {
 // This one's kinda tricky: it parses artist "references" from the
 // commentary content, and finds the matching artist for each reference.
 // This is mostly useful for credits and listings on artist pages.
-export function commentatorArtists() {
-  return compositeFrom({
-    annotation: `commentatorArtists`,
+export const commentatorArtists = templateCompositeFrom({
+  annotation: `commentatorArtists`,
+
+  compose: false,
+
+  steps: () => [
+    exitWithoutDependency({
+      dependency: 'commentary',
+      mode: input.value('falsy'),
+      value: input.value([]),
+    }),
 
-    constantDependencies: {
-      '#composition.findFunction': find.artists,
+    {
+      dependencies: ['commentary'],
+      compute: (continuation, {commentary}) =>
+        continuation({
+          '#artistRefs':
+            Array.from(
+              commentary
+                .replace(/<\/?b>/g, '')
+                .matchAll(/<i>(?<who>.*?):<\/i>/g))
+              .map(({groups: {who}}) => who),
+        }),
     },
 
-    steps: () => [
-      exitWithoutDependency({
-        dependency: 'commentary',
-        mode: 'falsy',
-        value: [],
-      }),
-
-      {
-        dependencies: ['commentary'],
-        compute: ({commentary}, continuation) =>
-          continuation({
-            '#artistRefs':
-              Array.from(
-                commentary
-                  .replace(/<\/?b>/g, '')
-                  .matchAll(/<i>(?<who>.*?):<\/i>/g))
-                .map(({groups: {who}}) => who),
-          }),
-      },
+    withResolvedReferenceList({
+      list: '#artistRefs',
+      data: 'artistData',
+      find: input.value(find.artist),
+    }).outputs({
+      '#resolvedReferenceList': '#artists',
+    }),
+
+    {
+      flags: {expose: true},
 
-      withResolvedReferenceList({
-        list: '#artistRefs',
-        data: 'artistData',
-        into: '#artists',
-        find: '#composition.findFunction',
-      }),
-
-      {
-        flags: {expose: true},
-
-        expose: {
-          dependencies: ['#artists'],
-          compute: ({'#artists': artists}) =>
-            unique(artists),
-        },
+      expose: {
+        dependencies: ['#artists'],
+        compute: ({'#artists': artists}) =>
+          unique(artists),
       },
-    ],
-  });
-}
+    },
+  ],
+});
 
 // Compositional utilities