From 33558828e70e4dd942bec1fbdb8aea3819ed8a19 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 19 Sep 2023 10:16:52 -0300 Subject: data: declare {update} in higher-context locations --- src/data/things/album.js | 9 ++-- src/data/things/composite.js | 92 ++++++++++++++++++++++++++------------ src/data/things/homepage-layout.js | 29 ++++++------ src/data/things/track.js | 33 +++++--------- 4 files changed, 97 insertions(+), 66 deletions(-) (limited to 'src/data/things') diff --git a/src/data/things/album.js b/src/data/things/album.js index c0042ae2..ec133a34 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -53,11 +53,12 @@ export class Album extends Thing { coverArtDate: [ exitWithoutContribs({contribs: 'coverArtistContribs'}), - exposeUpdateValueOrContinue(), - exposeDependency({ - dependency: 'date', - update: {validate: isDate}, + + exposeUpdateValueOrContinue({ + validate: input.value(isDate), }), + + exposeDependency({dependency: 'date'}), ], coverArtFileExtension: [ diff --git a/src/data/things/composite.js b/src/data/things/composite.js index c33fc03c..011f307e 100644 --- a/src/data/things/composite.js +++ b/src/data/things/composite.js @@ -1279,34 +1279,21 @@ export function debugComposite(fn) { // Exposes a dependency exactly as it is; this is typically the base of a // composition which was created to serve as one property's descriptor. -// Since this serves as a base, specify a value for {update} to indicate -// that the property as a whole updates (and some previous compositional -// step works with that update value). Set {update: true} to only enable -// the update flag, or set update to an object to specify a descriptor -// (e.g. for custom value validation). // // Please note that this *doesn't* verify that the dependency exists, so // if you provide the wrong name or it hasn't been set by a previous // compositional step, the property will be exposed as undefined instead // of null. // -export function exposeDependency({ - dependency, - update = false, -}) { +export function exposeDependency({dependency}) { return { annotation: `exposeDependency`, - flags: {expose: true, update: !!update}, + flags: {expose: true}, expose: { mapDependencies: {dependency}, compute: ({dependency}) => dependency, }, - - update: - (typeof update === 'object' - ? update - : null), }; } @@ -1314,25 +1301,16 @@ export function exposeDependency({ // is typically the base of a composition serving as a particular property // descriptor. It generally follows steps which will conditionally early // exit with some other value, with the exposeConstant base serving as the -// fallback default value. Like exposeDependency, set {update} to true or -// an object to indicate that the property as a whole updates. -export function exposeConstant({ - value, - update = false, -}) { +// fallback default value. +export function exposeConstant({value}) { return { annotation: `exposeConstant`, - flags: {expose: true, update: !!update}, + flags: {expose: true}, expose: { options: {value}, compute: ({'#options': {value}}) => value, }, - - update: - (typeof update === 'object' - ? update - : null), }; } @@ -1427,12 +1405,24 @@ export const exposeDependencyOrContinue = templateCompositeFrom({ // Exposes the update value of an {update: true} property as it is, // or continues if it's unavailable. See withResultOfAvailabilityCheck -// for {mode} options! +// for {mode} options! Also provide {validate} here to conveniently +// set a custom validation check for this property's update value. export const exposeUpdateValueOrContinue = templateCompositeFrom({ annotation: `exposeUpdateValueOrContinue`, inputs: { mode: input(availabilityCheckModeInput), + validate: input({type: 'function', null: true}), + }, + + update: { + dependencies: [input.staticValue('validate')], + compute: ({ + [input.staticValue('validate')]: validate, + }) => + (validate + ? {validate} + : {}), }, steps: () => [ @@ -1757,6 +1747,52 @@ export function fillMissingListItems({ } } +// Filters particular values out of a list. Note that this will always +// completely skip over null, but can be used to filter out any other +// primitive or object value. +export const excludeFromList = templateCompositeFrom({ + annotation: `excludeFromList`, + + inputs: { + list: input(), + + item: input({null: true}), + items: input({validate: isArray, null: true}), + }, + + outputs: { + dependencies: [input.staticDependency('list')], + compute: ({ + [input.staticDependency('list')]: list, + }) => [list ?? '#list'], + }, + + steps: [ + { + dependencies: [ + input.staticDependency('list'), + input('list'), + input('item'), + input('items'), + ], + + compute: (continuation, { + [input.staticDependency('list')]: listName, + [input('list')]: listContents, + [input('item')]: excludeItem, + [input('items')]: excludeItems, + }) => continuation({ + [listName ?? '#list']: + listContents.filter(item => { + if (excludeItem !== null && item === excludeItem) return false; + if (!empty(excludeItems) && exclueItems.includes(item)) return false; + return true; + }), + }), + }, + ], +}); + // Flattens an array with one level of nested arrays, providing as dependencies // both the flattened array as well as the original starting indices of each // successive source array. diff --git a/src/data/things/homepage-layout.js b/src/data/things/homepage-layout.js index 007e0236..677a2756 100644 --- a/src/data/things/homepage-layout.js +++ b/src/data/things/homepage-layout.js @@ -109,10 +109,21 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { sourceGroup: compositeFrom(`HomepageLayoutAlbumsRow.sourceGroup`, [ { - transform: (value, continuation) => - (value === 'new-releases' || value === 'new-additions' - ? value - : continuation(value)), + flags: {expose: true, update: true, compose: true}, + + update: { + validate: + oneOf( + is('new-releases', 'new-additions'), + validateReference(Group[Thing.referenceType])), + }, + + expose: { + transform: (value, continuation) => + (value === 'new-releases' || value === 'new-additions' + ? value + : continuation(value)), + }, }, withResolvedReference({ @@ -121,15 +132,7 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { find: input.value(find.group), }), - exposeDependency({ - dependency: '#resolvedReference', - update: input.value({ - validate: - oneOf( - is('new-releases', 'new-additions'), - validateReference(Group[Thing.referenceType])), - }), - }), + exposeDependency({dependency: '#resolvedReference'}), ]), sourceAlbums: referenceList({ diff --git a/src/data/things/track.js b/src/data/things/track.js index 28caf1de..135e6d1f 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -121,15 +121,13 @@ export class Track extends Thing { coverArtFileExtension: [ exitWithoutUniqueCoverArt(), - exposeUpdateValueOrContinue(), + exposeUpdateValueOrContinue({ + validate: input.value(isFileExtension), + }), withPropertyFromAlbum({property: 'trackCoverArtFileExtension'}), exposeDependencyOrContinue({dependency: '#album.trackCoverArtFileExtension'}), - - exposeConstant({ - value: 'jpg', - update: {validate: isFileExtension}, - }), + exposeConstant({value: 'jpg'}), ], // Date of cover art release. Like coverArtFileExtension, this represents @@ -140,13 +138,12 @@ export class Track extends Thing { withHasUniqueCoverArt(), exitWithoutDependency({dependency: '#hasUniqueCoverArt', mode: 'falsy'}), - exposeUpdateValueOrContinue(), + exposeUpdateValueOrContinue({ + validate: input.value(isDate), + }), withPropertyFromAlbum({property: 'trackArtDate'}), - exposeDependency({ - dependency: '#album.trackArtDate', - update: {validate: isDate}, - }), + exposeDependency({dependency: '#album.trackArtDate'}), ], commentary: commentary(), @@ -175,7 +172,7 @@ export class Track extends Thing { inheritFromOriginalRelease({property: 'artistContribs'}), withResolvedContribs({ - from: input.updateValue(), + from: input.updateValue({validate: isContributionList}), }).outputs({ '#resolvedContribs': '#artistContribs', }), @@ -183,10 +180,7 @@ export class Track extends Thing { exposeDependencyOrContinue({dependency: '#artistContribs'}), withPropertyFromAlbum({property: 'artistContribs'}), - exposeDependency({ - dependency: '#album.artistContribs', - update: {validate: isContributionList}, - }), + exposeDependency({dependency: '#album.artistContribs'}), ], contributorContribs: [ @@ -201,7 +195,7 @@ export class Track extends Thing { exitWithoutUniqueCoverArt(), withResolvedContribs({ - from: input.updateValue(), + from: input.updateValue({validate: isContributionList}), }).outputs({ '#resolvedContribs': '#coverArtistContribs', }), @@ -209,10 +203,7 @@ export class Track extends Thing { exposeDependencyOrContinue({dependency: '#coverArtistContribs'}), withPropertyFromAlbum({property: 'trackCoverArtistContribs'}), - exposeDependency({ - dependency: '#album.trackCoverArtistContribs', - update: {validate: isContributionList}, - }), + exposeDependency({dependency: '#album.trackCoverArtistContribs'}), ], referencedTracks: [ -- cgit 1.3.0-6-gf8a5