diff options
Diffstat (limited to 'src/data/composite/things/track/withAlwaysReferenceByDirectory.js')
-rw-r--r-- | src/data/composite/things/track/withAlwaysReferenceByDirectory.js | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/data/composite/things/track/withAlwaysReferenceByDirectory.js b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js new file mode 100644 index 00000000..d27f7b23 --- /dev/null +++ b/src/data/composite/things/track/withAlwaysReferenceByDirectory.js @@ -0,0 +1,91 @@ +// 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. +// +// See the implementation for an important caveat about matching the original +// track against other tracks, which uses a custom implementation pulling (and +// duplicating) details from #find instead of using withOriginalRelease and the +// usual withResolvedReference / find.track() utilities. +// + +import {input, templateCompositeFrom} from '#composite'; +import {isBoolean} from '#validators'; + +import {exitWithoutDependency, exposeUpdateValueOrContinue} + from '#composite/control-flow'; +import {withPropertyFromObject} from '#composite/data'; + +// TODO: Kludge. (The usage of this, not so much the import.) +import CacheableObject from '../../../things/cacheable-object.js'; + +export default templateCompositeFrom({ + annotation: `withAlwaysReferenceByDirectory`, + + outputs: ['#alwaysReferenceByDirectory'], + + steps: () => [ + exposeUpdateValueOrContinue({ + validate: input.value(isBoolean), + }), + + // 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. + + exitWithoutDependency({ + dependency: 'trackData', + mode: input.value('empty'), + value: input.value(false), + }), + + exitWithoutDependency({ + dependency: 'originalReleaseTrack', + value: input.value(false), + }), + + // "Slow" / uncached, manual search from trackData (with this track + // excluded). Otherwise there end up being pretty bad recursion issues + // (track1.alwaysReferencedByDirectory depends on searching through data + // including track2, which depends on evaluating track2.alwaysReferenced- + // ByDirectory, which depends on searcing through data including track1...) + // That said, this is 100% a kludge, since it involves duplicating find + // logic on a completely unrelated context. + { + dependencies: [input.myself(), 'trackData', 'originalReleaseTrack'], + compute: (continuation, { + [input.myself()]: thisTrack, + ['trackData']: trackData, + ['originalReleaseTrack']: ref, + }) => continuation({ + ['#originalRelease']: + (ref.startsWith('track:') + ? trackData.find(track => track.directory === ref.slice('track:'.length)) + : trackData.find(track => + track !== thisTrack && + !CacheableObject.getUpdateValue(track, 'originalReleaseTrack') && + track.name.toLowerCase() === ref.toLowerCase())), + }) + }, + + exitWithoutDependency({ + dependency: '#originalRelease', + value: input.value(false), + }), + + withPropertyFromObject({ + object: '#originalRelease', + property: input.value('name'), + }), + + { + dependencies: ['name', '#originalRelease.name'], + compute: (continuation, { + name, + ['#originalRelease.name']: originalName, + }) => continuation({ + ['#alwaysReferenceByDirectory']: name === originalName, + }), + }, + ], +}); |