From ab7591e45e7e31b4e2c0e2f81e224672145993fa Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sun, 1 Oct 2023 17:01:21 -0300 Subject: data, test: refactor utilities into own file Primarily for more precies test coverage mapping, but also to make navigation a bit easier and consolidate complex functions with lots of imports out of the same space as other, more simple or otherwise specialized files. --- src/data/things/track.js | 471 ++++------------------------------------------- 1 file changed, 32 insertions(+), 439 deletions(-) (limited to 'src/data/things/track.js') diff --git a/src/data/things/track.js b/src/data/things/track.js index c77bf889..193ad891 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -1,35 +1,28 @@ import {inspect} from 'node:util'; import {colors} from '#cli'; +import {input} from '#composite'; import find from '#find'; -import {empty} from '#sugar'; import { - exitWithoutDependency, - excludeFromList, - exposeConstant, - exposeDependency, - exposeDependencyOrContinue, - exposeUpdateValueOrContinue, - input, - raiseOutputWithoutDependency, - templateCompositeFrom, - withPropertyFromObject, -} from '#composite'; - -import { - is, - isBoolean, isColor, isContributionList, isDate, isFileExtension, - validateWikiData, } from '#validators'; -import CacheableObject from './cacheable-object.js'; +import {withPropertyFromObject} from '#composite/data'; +import {withResolvedContribs} from '#composite/wiki-data'; + +import { + exitWithoutDependency, + exposeConstant, + exposeDependency, + exposeDependencyOrContinue, + exposeUpdateValueOrContinue, +} from '#composite/control-flow'; -import Thing, { +import { additionalFiles, commentary, commentatorArtists, @@ -45,10 +38,22 @@ import Thing, { simpleString, urls, wikiData, - withResolvedContribs, - withResolvedReference, - withReverseReferenceList, -} from './thing.js'; +} from '#composite/wiki-properties'; + +import { + exitWithoutUniqueCoverArt, + inheritFromOriginalRelease, + trackReverseReferenceList, + withAlbum, + withAlwaysReferenceByDirectory, + withContainingTrackSection, + withHasUniqueCoverArt, + withOtherReleases, + withPropertyFromAlbum, +} from '#composite/things/track'; + +import CacheableObject from './cacheable-object.js'; +import Thing from './thing.js'; export class Track extends Thing { static [Thing.referenceType] = 'track'; @@ -84,39 +89,9 @@ export class Track extends Thing { exposeDependency({dependency: '#album.color'}), ], - // Controls how find.track works - it'll never be matched by a reference - // just to the track's name, which means you don't have to always reference - // some *other* (much more commonly referenced) track by directory instead - // of more naturally by name. alwaysReferenceByDirectory: [ - exposeUpdateValueOrContinue({ - validate: input.value(isBoolean), - }), - - excludeFromList({ - list: 'trackData', - item: input.myself(), - }), - - withOriginalRelease({ - data: '#trackData', - }), - - exitWithoutDependency({ - dependency: '#originalRelease', - value: input.value(false), - }), - - withPropertyFromObject({ - object: '#originalRelease', - property: input.value('name'), - }), - - { - dependencies: ['name', '#originalRelease.name'], - compute: ({name, '#originalRelease.name': originalName}) => - name === originalName, - }, + withAlwaysReferenceByDirectory(), + exposeDependency({dependency: '#alwaysReferenceByDirectory'}), ], // Disables presenting the track as though it has its own unique artwork. @@ -298,61 +273,20 @@ export class Track extends Thing { exposeDependency({dependency: '#album.date'}), ], - // Whether or not the track has "unique" cover artwork - a cover which is - // specifically associated with this track in particular, rather than with - // the track's album as a whole. This is typically used to select between - // displaying the track artwork and a fallback, such as the album artwork - // or a placeholder. (This property is named hasUniqueCoverArt instead of - // the usual hasCoverArt to emphasize that it does not inherit from the - // album.) hasUniqueCoverArt: [ withHasUniqueCoverArt(), exposeDependency({dependency: '#hasUniqueCoverArt'}), ], otherReleases: [ - exitWithoutDependency({ - dependency: 'trackData', - mode: input.value('empty'), - }), - - withOriginalRelease({ - selfIfOriginal: input.value(true), - }), - - { - flags: {expose: true}, - expose: { - dependencies: [input.myself(), '#originalRelease', 'trackData'], - compute: ({ - [input.myself()]: thisTrack, - ['#originalRelease']: originalRelease, - trackData, - }) => - (originalRelease === thisTrack - ? [] - : [originalRelease]) - .concat(trackData.filter(track => - track !== originalRelease && - track !== thisTrack && - track.originalReleaseTrack === originalRelease)), - }, - }, + withOtherReleases(), + exposeDependency({dependency: '#otherReleases'}), ], - // 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 - // generally relevant from the perspective of the tracks being referenced. - // Filtering them from data here hides them from the corresponding field - // on the site (obviously), and has the bonus of not counting them when - // counting the number of times a track has been referenced, for use in - // the "Tracks - by Times Referenced" listing page (or other data - // processing). referencedByTracks: trackReverseReferenceList({ list: input.value('referencedTracks'), }), - // For the same reasoning, exclude re-releases from sampled tracks too. sampledByTracks: trackReverseReferenceList({ list: input.value('sampledTracks'), }), @@ -386,344 +320,3 @@ export class Track extends Thing { return parts.join(''); } } - -// Early exits with a value inherited from the original release, if -// this track is a rerelease, and otherwise continues with no further -// dependencies provided. If allowOverride is true, then the continuation -// will also be called if the original release exposed the requested -// property as null. -export const inheritFromOriginalRelease = templateCompositeFrom({ - annotation: `Track.inheritFromOriginalRelease`, - - inputs: { - property: input({type: 'string'}), - allowOverride: input({type: 'boolean', defaultValue: false}), - }, - - steps: () => [ - withOriginalRelease(), - - { - dependencies: [ - '#originalRelease', - input('property'), - input('allowOverride'), - ], - - compute: (continuation, { - ['#originalRelease']: originalRelease, - [input('property')]: originalProperty, - [input('allowOverride')]: allowOverride, - }) => { - if (!originalRelease) return continuation(); - - const value = originalRelease[originalProperty]; - if (allowOverride && value === null) return continuation(); - - return continuation.exit(value); - }, - }, - ], -}); - -// Gets the track's album. This will early exit if albumData is missing. -// By default, if there's no album whose list of tracks includes this track, -// the output dependency will be null; set {notFoundMode: 'exit'} to early -// exit instead. -export const withAlbum = templateCompositeFrom({ - annotation: `Track.withAlbum`, - - inputs: { - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), - }, - - outputs: ['#album'], - - steps: () => [ - raiseOutputWithoutDependency({ - dependency: 'albumData', - mode: input.value('empty'), - output: input.value({ - ['#album']: null, - }), - }), - - { - dependencies: [input.myself(), 'albumData'], - compute: (continuation, { - [input.myself()]: track, - ['albumData']: albumData, - }) => - continuation({ - ['#album']: - albumData.find(album => album.tracks.includes(track)), - }), - }, - - raiseOutputWithoutDependency({ - dependency: '#album', - output: input.value({ - ['#album']: null, - }), - }), - - { - dependencies: ['#album'], - compute: (continuation, {'#album': album}) => - continuation.raiseOutput({'#album': album}), - }, - ], -}); - -// Gets a single property from this track's album, providing it as the same -// property name prefixed with '#album.' (by default). If the track's album -// isn't available, then by default, the property will be provided as null; -// set {notFoundMode: 'exit'} to early exit instead. -export const withPropertyFromAlbum = templateCompositeFrom({ - annotation: `withPropertyFromAlbum`, - - inputs: { - property: input.staticValue({type: 'string'}), - - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), - }, - - outputs: ({ - [input.staticValue('property')]: property, - }) => ['#album.' + property], - - steps: () => [ - withAlbum({ - notFoundMode: input('notFoundMode'), - }), - - withPropertyFromObject({ - object: '#album', - property: input('property'), - }), - - { - dependencies: ['#value', input.staticValue('property')], - compute: (continuation, { - ['#value']: value, - [input.staticValue('property')]: property, - }) => continuation({ - ['#album.' + property]: value, - }), - }, - ], -}); - -// Gets the track section containing this track from its album's track list. -// If notFoundMode is set to 'exit', this will early exit if the album can't be -// found or if none of its trackSections includes the track for some reason. -export const withContainingTrackSection = templateCompositeFrom({ - annotation: `withContainingTrackSection`, - - inputs: { - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), - }, - - outputs: ['#trackSection'], - - steps: () => [ - withPropertyFromAlbum({ - property: input.value('trackSections'), - notFoundMode: input('notFoundMode'), - }), - - { - dependencies: [ - input.myself(), - input('notFoundMode'), - '#album.trackSections', - ], - - compute(continuation, { - [input.myself()]: track, - [input('notFoundMode')]: notFoundMode, - ['#album.trackSections']: trackSections, - }) { - if (!trackSections) { - return continuation.raiseOutput({ - ['#trackSection']: null, - }); - } - - const trackSection = - trackSections.find(({tracks}) => tracks.includes(track)); - - if (trackSection) { - return continuation.raiseOutput({ - ['#trackSection']: trackSection, - }); - } else if (notFoundMode === 'exit') { - return continuation.exit(null); - } else { - return continuation.raiseOutput({ - ['#trackSection']: null, - }); - } - }, - }, - ], -}); - -// Just includes the original release of this track as a dependency. -// If this track isn't a rerelease, then it'll provide null, unless the -// {selfIfOriginal} option is set, in which case it'll provide this track -// itself. Note that this will early exit if the original release is -// specified by reference and that reference doesn't resolve to anything. -// Outputs to '#originalRelease' by default. -export const withOriginalRelease = templateCompositeFrom({ - annotation: `withOriginalRelease`, - - inputs: { - selfIfOriginal: input({type: 'boolean', defaultValue: false}), - - data: input({ - validate: validateWikiData({referenceType: 'track'}), - defaultDependency: 'trackData', - }), - }, - - outputs: ['#originalRelease'], - - steps: () => [ - withResolvedReference({ - ref: 'originalReleaseTrack', - data: input('data'), - find: input.value(find.track), - notFoundMode: input.value('exit'), - }).outputs({ - ['#resolvedReference']: '#originalRelease', - }), - - { - dependencies: [ - input.myself(), - input('selfIfOriginal'), - '#originalRelease', - ], - - compute: (continuation, { - [input.myself()]: track, - [input('selfIfOriginal')]: selfIfOriginal, - ['#originalRelease']: originalRelease, - }) => - continuation({ - ['#originalRelease']: - (originalRelease ?? - (selfIfOriginal - ? track - : null)), - }), - }, - ], -}); - -// The algorithm for checking if a track has unique cover art is used in a -// couple places, so it's defined in full as a compositional step. -export const withHasUniqueCoverArt = templateCompositeFrom({ - annotation: 'withHasUniqueCoverArt', - - outputs: ['#hasUniqueCoverArt'], - - steps: () => [ - { - dependencies: ['disableUniqueCoverArt'], - compute: (continuation, {disableUniqueCoverArt}) => - (disableUniqueCoverArt - ? continuation.raiseOutput({ - ['#hasUniqueCoverArt']: false, - }) - : continuation()), - }, - - withResolvedContribs({from: 'coverArtistContribs'}), - - { - dependencies: ['#resolvedContribs'], - compute: (continuation, { - ['#resolvedContribs']: contribsFromTrack, - }) => - (empty(contribsFromTrack) - ? continuation() - : continuation.raiseOutput({ - ['#hasUniqueCoverArt']: true, - })), - }, - - withPropertyFromAlbum({ - property: input.value('trackCoverArtistContribs'), - }), - - { - dependencies: ['#album.trackCoverArtistContribs'], - compute: (continuation, { - ['#album.trackCoverArtistContribs']: contribsFromAlbum, - }) => - continuation.raiseOutput({ - ['#hasUniqueCoverArt']: - !empty(contribsFromAlbum), - }), - }, - ], -}); - -// Shorthand for checking if the track has unique cover art and exposing a -// fallback value if it isn't. -export const exitWithoutUniqueCoverArt = templateCompositeFrom({ - annotation: `exitWithoutUniqueCoverArt`, - - inputs: { - value: input({defaultValue: null}), - }, - - steps: () => [ - withHasUniqueCoverArt(), - - exitWithoutDependency({ - dependency: '#hasUniqueCoverArt', - mode: input.value('falsy'), - value: input('value'), - }), - ], -}); - -export const trackReverseReferenceList = templateCompositeFrom({ - annotation: `trackReverseReferenceList`, - - compose: false, - - inputs: { - list: input({type: 'string'}), - }, - - steps: () => [ - withReverseReferenceList({ - data: 'trackData', - list: input('list'), - }), - - { - flags: {expose: true}, - expose: { - dependencies: ['#reverseReferenceList'], - compute: ({ - ['#reverseReferenceList']: reverseReferenceList, - }) => - reverseReferenceList.filter(track => !track.originalReleaseTrack), - }, - }, - ], -}); -- cgit 1.3.0-6-gf8a5