« get me outta code hell

data: track: experimental Thing.compose.from() processing style - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/things/track.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-08-21 17:28:15 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-09-05 21:02:48 -0300
commit55e4afead38bc541cba4ae1cef183527c254f99a (patch)
tree6fac3aaed4cba2c8e934a61b913849c6239cb340 /src/data/things/track.js
parent218a99a3164e8ae6967335190b72fd36275d1892 (diff)
data: track: experimental Thing.compose.from() processing style
Diffstat (limited to 'src/data/things/track.js')
-rw-r--r--src/data/things/track.js290
1 files changed, 148 insertions, 142 deletions
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 39c2930f..fe6af205 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -54,49 +54,53 @@ export class Track extends Thing {
     // track's unique cover artwork, if any, and does not inherit the cover's
     // main artwork. (It does inherit `trackCoverArtFileExtension` if present
     // on the album.)
-    coverArtFileExtension: {
-      flags: {update: true, expose: true},
-
-      update: {validate: isFileExtension},
-
-      expose: Track.withAlbumProperties(['trackCoverArtistContribsByRef', 'trackCoverArtFileExtension'], {
-        dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
-
-        transform(coverArtFileExtension, {
-          coverArtistContribsByRef,
-          disableUniqueCoverArt,
-          album: {trackCoverArtistContribsByRef, trackCoverArtFileExtension},
-        }) {
-          if (disableUniqueCoverArt) return null;
-          if (empty(coverArtistContribsByRef) && empty(trackCoverArtistContribsByRef)) return null;
-          return coverArtFileExtension ?? trackCoverArtFileExtension ?? 'jpg';
+    coverArtFileExtension: Thing.composite.from([
+      Track.withAlbumProperties(['trackCoverArtistContribsByRef', 'trackCoverArtFileExtension']),
+
+      {
+        flags: {update: true, expos: true},
+        update: {validate: isFileExtension},
+        expose: {
+          dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
+
+          transform(coverArtFileExtension, {
+            coverArtistContribsByRef,
+            disableUniqueCoverArt,
+            album: {trackCoverArtistContribsByRef, trackCoverArtFileExtension},
+          }) {
+            if (disableUniqueCoverArt) return null;
+            if (empty(coverArtistContribsByRef) && empty(trackCoverArtistContribsByRef)) return null;
+            return coverArtFileExtension ?? trackCoverArtFileExtension ?? 'jpg';
+          },
         },
-      }),
-    },
+      },
+    ]),
 
     // Date of cover art release. Like coverArtFileExtension, this represents
     // only the track's own unique cover artwork, if any. This exposes only as
     // the track's own coverArtDate or its album's trackArtDate, so if neither
     // is specified, this value is null.
-    coverArtDate: {
-      flags: {update: true, expose: true},
-
-      update: {validate: isDate},
-
-      expose: Track.withAlbumProperties(['trackArtDate', 'trackCoverArtistContribsByRef'], {
-        dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
-
-        transform(coverArtDate, {
-          coverArtistContribsByRef,
-          disableUniqueCoverArt,
-          album: {trackArtDate, trackCoverArtistContribsByRef},
-        }) {
-          if (disableUniqueCoverArt) return null;
-          if (empty(coverArtistContribsByRef) && empty(trackCoverArtistContribsByRef)) return null;
-          return coverArtDate ?? trackArtDate;
+    coverArtDate: Thing.composite.from([
+      Track.withAlbumProperties(['trackArtDate', 'trackCoverArtistContribsByRef']),
+
+      {
+        flags: {update: true, expose: true},
+        update: {validate: isDate},
+        expose: {
+          dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
+
+          transform(coverArtDate, {
+            coverArtistContribsByRef,
+            disableUniqueCoverArt,
+            album: {trackArtDate, trackCoverArtistContribsByRef},
+          }) {
+            if (disableUniqueCoverArt) return null;
+            if (empty(coverArtistContribsByRef) && empty(trackCoverArtistContribsByRef)) return null;
+            return coverArtDate ?? trackArtDate;
+          },
         },
-      }),
-    },
+      }
+    ]),
 
     originalReleaseTrackByRef: Thing.common.singleReference(Track),
 
@@ -176,23 +180,26 @@ export class Track extends Thing {
     // or a placeholder. (This property is named hasUniqueCoverArt instead of
     // the usual hasCoverArt to emphasize that it does not inherit from the
     // album.)
-    hasUniqueCoverArt: {
-      flags: {expose: true},
-
-      expose: Track.withAlbumProperties(['trackCoverArtistContribsByRef'], {
-        dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
-        compute({
-          coverArtistContribsByRef,
-          disableUniqueCoverArt,
-          album: {trackCoverArtistContribsByRef},
-        }) {
-          if (disableUniqueCoverArt) return false;
-          if (!empty(coverArtistContribsByRef)) true;
-          if (!empty(trackCoverArtistContribsByRef)) return true;
-          return false;
+    hasUniqueCoverArt: Thing.composite.from([
+      Track.withAlbumProperties(['trackCoverArtistContribsByRef']),
+
+      {
+        flags: {expose: true},
+        expose: {
+          dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
+          compute({
+            coverArtistContribsByRef,
+            disableUniqueCoverArt,
+            album: {trackCoverArtistContribsByRef},
+          }) {
+            if (disableUniqueCoverArt) return false;
+            if (!empty(coverArtistContribsByRef)) true;
+            if (!empty(trackCoverArtistContribsByRef)) return true;
+            return false;
+          },
         },
-      }),
-    },
+      },
+    ]),
 
     originalReleaseTrack: Thing.common.dynamicThingFromSingleReference(
       'originalReleaseTrackByRef',
@@ -228,43 +235,70 @@ export class Track extends Thing {
       },
     },
 
-    artistContribs:
-      Track.inheritFromOriginalRelease('artistContribs', [],
-        Thing.common.dynamicInheritContribs(
-          null,
-          'artistContribsByRef',
-          'artistContribsByRef',
-          'albumData',
-          Track.findAlbum)),
+    artistContribs: Thing.composite.from([
+      Track.inheritFromOriginalRelease('artistContribs'),
+
+      {
+        flags: {expose: true},
+        expose: {
+          dependencies: ['artistContribs'],
+
+          compute({
+            artistContribsByRef: contribsFromTrack,
+            album: {artistContribsByRef: contribsFromAlbum},
+          }) {
+            let contribsByRef = contribsFromTrack;
+            if (empty(contribsByRef)) contribsByRef = contribsFromAlbum;
+            if (empty(contribsByRef)) return null;
 
-    contributorContribs:
-      Track.inheritFromOriginalRelease('contributorContribs', [],
-        Thing.common.dynamicContribs('contributorContribsByRef')),
+            return Thing.findArtistsFromContribs(contribsByRef, artistData);
+          },
+        },
+      },
+    ]),
+
+    contributorContribs: Thing.composite.from([
+      Track.inheritFromOriginalRelease('contributorContribs'),
+      Thing.common.dynamicContribs('contributorContribsByRef'),
+    ]),
 
     // Cover artists aren't inherited from the original release, since it
     // typically varies by release and isn't defined by the musical qualities
     // of the track.
-    coverArtistContribs:
-      Thing.common.dynamicInheritContribs(
-        'hasCoverArt',
-        'coverArtistContribsByRef',
-        'trackCoverArtistContribsByRef',
-        'albumData',
-        Track.findAlbum),
-
-    referencedTracks:
-      Track.inheritFromOriginalRelease('referencedTracks', [],
-        Thing.common.dynamicThingsFromReferenceList(
-          'referencedTracksByRef',
-          'trackData',
-          find.track)),
-
-    sampledTracks:
-      Track.inheritFromOriginalRelease('sampledTracks', [],
-        Thing.common.dynamicThingsFromReferenceList(
-          'sampledTracksByRef',
-          'trackData',
-          find.track)),
+    coverArtistContribs: Thing.composite.from([
+      Track.withAlbumProperties(['trackCoverArtistContribsByRef']),
+
+      {
+        flags: {expose: true},
+        expose: {
+          dependencies: ['coverArtistContribsByRef', 'disableUniqueCoverArt'],
+
+          compute({
+            coverArtistContribsByRef: contribsFromTrack,
+            disableUniqueCoverArt,
+            album: {trackCoverArtistContribsByRef: contribsFromAlbum},
+          }) {
+            if (disableUniqueCoverArt) return null;
+
+            let contribsByRef = contribsFromTrack;
+            if (empty(contribsByRef)) contribsByRef = contribsFromAlbum;
+            if (empty(contribsByRef)) return null;
+
+            return Thing.findArtistsFromContribs(contribsByRef, artistData);
+          },
+        },
+      },
+    ]),
+
+    referencedTracks: Thing.composite.from([
+      Track.inheritFromOriginalRelease('referencedTracks'),
+      Thing.common.dynamicThingsFromReferenceList('referencedTracksByRef', 'trackData', find.track),
+    ]),
+
+    sampledTracks: Thing.composite.from([
+      Track.inheritFromOriginalRelease('sampledTracks'),
+      Thing.common.dynamicThingsFromReferenceList('sampledTracksByRef', 'trackData', find.track),
+    ]),
 
     // Specifically exclude re-releases from this list - while it's useful to
     // get from a re-release to the tracks it references, re-releases aren't
@@ -317,72 +351,44 @@ export class Track extends Thing {
     ),
   });
 
-  static inheritFromOriginalRelease(
-    originalProperty,
-    originalMissingValue,
-    ownPropertyDescriptor
-  ) {
-    return {
-      flags: {expose: true},
+  static inheritFromOriginalRelease = originalProperty => ({
+    flags: {expose: true, compose: true},
 
-      expose: {
-        dependencies: [
-          ...ownPropertyDescriptor.expose.dependencies,
-          'originalReleaseTrackByRef',
-          'trackData',
-        ],
-
-        compute(dependencies) {
-          const {
-            originalReleaseTrackByRef,
-            trackData,
-          } = dependencies;
-
-          if (originalReleaseTrackByRef) {
-            if (!trackData) return originalMissingValue;
-            const original = find.track(originalReleaseTrackByRef, trackData, {mode: 'quiet'});
-            if (!original) return originalMissingValue;
-            return original[originalProperty];
-          }
+    expose: {
+      dependencies: ['originalReleaseTrackByRef', 'trackData'],
 
-          return ownPropertyDescriptor.expose.compute(dependencies);
-        },
-      },
-    };
-  }
+      compute({originalReleaseTrackByRef, trackData}, callback) {
+        if (!originalReleaseTrackByRef) return callback();
 
-  static withAlbumProperties(albumProperties, oldExpose) {
-    const applyAlbumDependency = dependencies => {
-      const track = dependencies[Track.instance];
-      const album =
-        dependencies.albumData
-          ?.find((album) => album.tracks.includes(track));
-
-      const filteredAlbum = Object.create(null);
-      for (const property of albumProperties) {
-        filteredAlbum[property] =
-          (album
-            ? album[property]
-            : null);
-      }
+        if (!trackData) return null;
+        const original = find.track(originalReleaseTrackByRef, trackData, {mode: 'quiet'});
+        if (!original) return null;
+        return original[originalProperty];
+      },
+    },
+  });
 
-      return {...dependencies, album: filteredAlbum};
-    };
+  static withAlbumProperties = albumProperties => ({
+    flags: {expose: true, compose: true},
 
-    const newExpose = {dependencies: [...oldExpose.dependencies, 'albumData']};
+    expose: {
+      dependencies: ['albumData'],
 
-    if (oldExpose.compute) {
-      newExpose.compute = dependencies =>
-        oldExpose.compute(applyAlbumDependency(dependencies));
-    }
+      compute({albumData, [Track.instance]: track}, callback) {
+        const album = albumData?.find((album) => album.tracks.includes(track));
 
-    if (oldExpose.transform) {
-      newExpose.transform = (value, dependencies) =>
-        oldExpose.transform(value, applyAlbumDependency(dependencies));
-    }
+        const filteredAlbum = Object.create(null);
+        for (const property of albumProperties) {
+          filteredAlbum[property] =
+            (album
+              ? album[property]
+              : null);
+        }
 
-    return newExpose;
-  }
+        return callback({album: filteredAlbum});
+      },
+    },
+  });
 
   [inspect.custom]() {
     const base = Thing.prototype[inspect.custom].apply(this);