diff options
Diffstat (limited to 'src/data/composite/things/track')
7 files changed, 159 insertions, 170 deletions
diff --git a/src/data/composite/things/track/index.js b/src/data/composite/things/track/index.js index cc723a2..8959de9 100644 --- a/src/data/composite/things/track/index.js +++ b/src/data/composite/things/track/index.js @@ -9,3 +9,4 @@ export {default as withContainingTrackSection} from './withContainingTrackSectio export {default as withHasUniqueCoverArt} from './withHasUniqueCoverArt.js'; export {default as withOtherReleases} from './withOtherReleases.js'; export {default as withPropertyFromAlbum} from './withPropertyFromAlbum.js'; +export {default as withPropertyFromOriginalRelease} from './withPropertyFromOriginalRelease.js'; diff --git a/src/data/composite/things/track/inheritFromOriginalRelease.js b/src/data/composite/things/track/inheritFromOriginalRelease.js index 27ed138..38ab06b 100644 --- a/src/data/composite/things/track/inheritFromOriginalRelease.js +++ b/src/data/composite/things/track/inheritFromOriginalRelease.js @@ -1,8 +1,6 @@ -// 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. +// Early exits with the value for the same property as specified on the +// original release, if this track is a rerelease, and otherwise continues +// without providing any further dependencies. // // Like withOriginalRelease, this will early exit (with notFoundValue) if the // original release is specified by reference and that reference doesn't @@ -10,41 +8,34 @@ import {input, templateCompositeFrom} from '#composite'; -import withOriginalRelease from './withOriginalRelease.js'; +import {exposeDependency, raiseOutputWithoutDependency} + from '#composite/control-flow'; + +import withPropertyFromOriginalRelease + from './withPropertyFromOriginalRelease.js'; export default templateCompositeFrom({ annotation: `inheritFromOriginalRelease`, inputs: { - property: input({type: 'string'}), - allowOverride: input({type: 'boolean', defaultValue: false}), - notFoundValue: input({defaultValue: null}), + notFoundValue: input({ + defaultValue: null, + }), }, steps: () => [ - withOriginalRelease({ + withPropertyFromOriginalRelease({ + property: input.thisProperty(), notFoundValue: input('notFoundValue'), }), - { - 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); - }, - }, + raiseOutputWithoutDependency({ + dependency: '#isRerelease', + mode: input.value('falsy'), + }), + + exposeDependency({ + dependency: '#originalValue', + }), ], }); diff --git a/src/data/composite/things/track/withAlbum.js b/src/data/composite/things/track/withAlbum.js index cbd16dc..03b840d 100644 --- a/src/data/composite/things/track/withAlbum.js +++ b/src/data/composite/things/track/withAlbum.js @@ -1,108 +1,22 @@ // 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. -// -// This step models with Flash.withFlashAct. +// If there's no album whose list of tracks includes this track, the output +// dependency will be null. import {input, templateCompositeFrom} from '#composite'; -import {is} from '#validators'; -import {exitWithoutDependency, withResultOfAvailabilityCheck} - from '#composite/control-flow'; -import {withPropertyFromList} from '#composite/data'; +import {withUniqueReferencingThing} from '#composite/wiki-data'; export default templateCompositeFrom({ annotation: `withAlbum`, - inputs: { - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), - }, - outputs: ['#album'], steps: () => [ - // null albumData is always an early exit. - - exitWithoutDependency({ - dependency: 'albumData', - mode: input.value('null'), - }), - - // empty albumData conditionally exits early or outputs null. - - withResultOfAvailabilityCheck({ - from: 'albumData', - mode: input.value('empty'), - }).outputs({ - '#availability': '#albumDataAvailability', - }), - - { - dependencies: [input('notFoundMode'), '#albumDataAvailability'], - compute(continuation, { - [input('notFoundMode')]: notFoundMode, - ['#albumDataAvailability']: albumDataIsAvailable, - }) { - if (albumDataIsAvailable) return continuation(); - switch (notFoundMode) { - case 'exit': return continuation.exit(null); - case 'null': return continuation.raiseOutput({'#album': null}); - } - }, - }, - - withPropertyFromList({ - list: 'albumData', - property: input.value('tracks'), - }), - - { - dependencies: [input.myself(), '#albumData.tracks'], - compute: (continuation, { - [input.myself()]: track, - ['#albumData.tracks']: trackLists, - }) => continuation({ - ['#albumIndex']: - trackLists.findIndex(tracks => tracks.includes(track)), - }), - }, - - // album not found conditionally exits or outputs null. - - withResultOfAvailabilityCheck({ - from: '#albumIndex', - mode: input.value('index'), + withUniqueReferencingThing({ + data: 'albumData', + list: input.value('tracks'), }).outputs({ - '#availability': '#albumAvailability', + ['#uniqueReferencingThing']: '#album', }), - - { - dependencies: [input('notFoundMode'), '#albumAvailability'], - compute(continuation, { - [input('notFoundMode')]: notFoundMode, - ['#albumAvailability']: albumIsAvailable, - }) { - if (albumIsAvailable) return continuation(); - switch (notFoundMode) { - case 'exit': return continuation.exit(null); - case 'null': return continuation.raiseOutput({'#album': null}); - } - }, - }, - - { - dependencies: ['albumData', '#albumIndex'], - compute: (continuation, { - ['albumData']: albumData, - ['#albumIndex']: albumIndex, - }) => continuation.raiseOutput({ - ['#album']: - albumData[albumIndex], - }), - }, ], }); diff --git a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js index fac8e21..e01720b 100644 --- a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js +++ b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js @@ -7,11 +7,15 @@ import {input, templateCompositeFrom} from '#composite'; import find from '#find'; import {isBoolean} from '#validators'; -import {exitWithoutDependency, exposeUpdateValueOrContinue} - from '#composite/control-flow'; import {withPropertyFromObject} from '#composite/data'; import {withResolvedReference} from '#composite/wiki-data'; +import { + exitWithoutDependency, + exposeDependencyOrContinue, + exposeUpdateValueOrContinue, +} from '#composite/control-flow'; + export default templateCompositeFrom({ annotation: `withAlwaysReferenceByDirectory`, @@ -22,6 +26,29 @@ export default templateCompositeFrom({ validate: input.value(isBoolean), }), + // withAlwaysReferenceByDirectory is sort of a fragile area - we can't + // find the track's album the normal way because albums' track lists + // recurse back into alwaysReferenceByDirectory! + withResolvedReference({ + ref: 'dataSourceAlbum', + data: 'albumData', + find: input.value(find.album), + }).outputs({ + '#resolvedReference': '#album', + }), + + withPropertyFromObject({ + object: '#album', + property: input.value('alwaysReferenceTracksByDirectory'), + }), + + // Falsy mode means this exposes true if the album's property is true, + // but continues if the property is false (which is also the default). + exposeDependencyOrContinue({ + dependency: '#album.alwaysReferenceTracksByDirectory', + mode: input.value('falsy'), + }), + // Remaining code is for defaulting to true if this track is a rerelease of // another with the same name, so everything further depends on access to // trackData as well as originalReleaseTrack. diff --git a/src/data/composite/things/track/withContainingTrackSection.js b/src/data/composite/things/track/withContainingTrackSection.js index b2e5f2b..eaac14d 100644 --- a/src/data/composite/things/track/withContainingTrackSection.js +++ b/src/data/composite/things/track/withContainingTrackSection.js @@ -1,63 +1,42 @@ // 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. import {input, templateCompositeFrom} from '#composite'; import {is} from '#validators'; +import {raiseOutputWithoutDependency} from '#composite/control-flow'; + import withPropertyFromAlbum from './withPropertyFromAlbum.js'; export default templateCompositeFrom({ annotation: `withContainingTrackSection`, - inputs: { - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), - }, - outputs: ['#trackSection'], steps: () => [ withPropertyFromAlbum({ property: input.value('trackSections'), - notFoundMode: input('notFoundMode'), + }), + + raiseOutputWithoutDependency({ + dependency: '#album.trackSections', + output: input.value({'#trackSection': null}), }), { dependencies: [ input.myself(), - input('notFoundMode'), '#album.trackSections', ], - compute(continuation, { + 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, - }); - } - }, + }) => continuation({ + ['#trackSection']: + trackSections.find(({tracks}) => tracks.includes(track)) + ?? null, + }), }, ], }); diff --git a/src/data/composite/things/track/withPropertyFromAlbum.js b/src/data/composite/things/track/withPropertyFromAlbum.js index b236a6e..d41390f 100644 --- a/src/data/composite/things/track/withPropertyFromAlbum.js +++ b/src/data/composite/things/track/withPropertyFromAlbum.js @@ -1,7 +1,5 @@ // 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. +// property name prefixed with '#album.' (by default). import {input, templateCompositeFrom} from '#composite'; import {is} from '#validators'; @@ -15,11 +13,6 @@ export default templateCompositeFrom({ inputs: { property: input.staticValue({type: 'string'}), - - notFoundMode: input({ - validate: is('exit', 'null'), - defaultValue: 'null', - }), }, outputs: ({ @@ -27,9 +20,7 @@ export default templateCompositeFrom({ }) => ['#album.' + property], steps: () => [ - withAlbum({ - notFoundMode: input('notFoundMode'), - }), + withAlbum(), withPropertyFromObject({ object: '#album', diff --git a/src/data/composite/things/track/withPropertyFromOriginalRelease.js b/src/data/composite/things/track/withPropertyFromOriginalRelease.js new file mode 100644 index 0000000..fd37f6d --- /dev/null +++ b/src/data/composite/things/track/withPropertyFromOriginalRelease.js @@ -0,0 +1,86 @@ +// Provides a value inherited from the original release, if applicable, and a +// flag indicating if this track is a rerelase or not. +// +// Like withOriginalRelease, this will early exit (with notFoundValue) if the +// original release is specified by reference and that reference doesn't +// resolve to anything. + +import {input, templateCompositeFrom} from '#composite'; + +import {withResultOfAvailabilityCheck} from '#composite/control-flow'; +import {withPropertyFromObject} from '#composite/data'; + +import withOriginalRelease from './withOriginalRelease.js'; + +export default templateCompositeFrom({ + annotation: `inheritFromOriginalRelease`, + + inputs: { + property: input({type: 'string'}), + + notFoundValue: input({ + defaultValue: null, + }), + }, + + outputs: ({ + [input.staticValue('property')]: property, + }) => + ['#isRerelease'].concat( + (property + ? ['#original.' + property] + : ['#originalValue'])), + + steps: () => [ + withOriginalRelease({ + notFoundValue: input('notFoundValue'), + }), + + withResultOfAvailabilityCheck({ + from: '#originalRelease', + }), + + { + dependencies: [ + '#availability', + input.staticValue('property'), + ], + + compute: (continuation, { + ['#availability']: availability, + [input.staticValue('property')]: property, + }) => + (availability + ? continuation() + : continuation.raiseOutput( + Object.assign( + {'#isRerelease': false}, + (property + ? {['#original.' + property]: null} + : {'#originalValue': null})))), + }, + + withPropertyFromObject({ + object: '#originalRelease', + property: input('property'), + }), + + { + dependencies: [ + '#value', + input.staticValue('property'), + ], + + compute: (continuation, { + ['#value']: value, + [input.staticValue('property')]: property, + }) => + continuation.raiseOutput( + Object.assign( + {'#isRerelease': true}, + (property + ? {['#original.' + property]: value} + : {'#originalValue': value}))), + }, + ], +}); |