From cd73f85962f542f9b44feb2a7616bc0d9aac797b Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 21 Sep 2023 11:05:00 -0300 Subject: data: miscellaneous utility updates --- src/data/things/composite.js | 142 ++++++++++++++++++++++++++++++------------- src/data/things/thing.js | 2 +- src/data/things/track.js | 53 ++++++++++++---- 3 files changed, 141 insertions(+), 56 deletions(-) diff --git a/src/data/things/composite.js b/src/data/things/composite.js index cbbe6f8..cfa557d 100644 --- a/src/data/things/composite.js +++ b/src/data/things/composite.js @@ -5,6 +5,7 @@ import {TupleMap} from '#wiki-data'; import { isArray, + isString, isWholeNumber, oneOf, validateArrayItems, @@ -1426,17 +1427,24 @@ export function debugComposite(fn) { // compositional step, the property will be exposed as undefined instead // of null. // -export function exposeDependency({dependency}) { - return { - annotation: `exposeDependency`, - flags: {expose: true}, +export const exposeDependency = templateCompositeFrom({ + annotation: `exposeDependency`, - expose: { - mapDependencies: {dependency}, - compute: ({dependency}) => dependency, + compose: false, + + inputs: { + dependency: input.staticDependency(), + }, + + steps: () => [ + { + dependencies: [input('dependency')], + compute: ({ + [input('dependency')]: dependency + }) => dependency, }, - }; -} + ], +}); // Exposes a constant value exactly as it is; like exposeDependency, this // is typically the base of a composition serving as a particular property @@ -1488,7 +1496,7 @@ export const withResultOfAvailabilityCheck = templateCompositeFrom({ dependencies: [input('from'), input('mode')], compute: (continuation, { - [input('from')]: dependency, + [input('from')]: value, [input('mode')]: mode, }) => { let availability; @@ -1591,7 +1599,7 @@ export const exitWithoutDependency = templateCompositeFrom({ { dependencies: ['#availability', input('value')], - continuation: (continuation, { + compute: (continuation, { ['#availability']: availability, [input('value')]: value, }) => @@ -1628,9 +1636,13 @@ export const raiseOutputWithoutDependency = templateCompositeFrom({ inputs: { dependency: input(), mode: input(availabilityCheckModeInput), - output: input({defaultValue: {}}), + output: input.staticValue({defaultValue: {}}), }, + outputs: ({ + [input.staticValue('output')]: output, + }) => Object.keys(output), + steps: () => [ withResultOfAvailabilityCheck({ from: input('dependency'), @@ -1657,9 +1669,13 @@ export const raiseOutputWithoutUpdateValue = templateCompositeFrom({ inputs: { mode: input(availabilityCheckModeInput), - output: input({defaultValue: {}}), + output: input.staticValue({defaultValue: {}}), }, + outputs: ({ + [input.staticValue('output')]: output, + }) => Object.keys(output), + steps: () => [ withResultOfAvailabilityCheck({ from: input.updateValue(), @@ -1820,41 +1836,81 @@ export function withPropertyFromList({ // Gets the listed properties from each of a list of objects, providing lists // of property values each into a dependency prefixed with the same name as the // list (by default). Like withPropertyFromList, this doesn't alter indices. -export function withPropertiesFromList({ - list, - properties, - prefix = - (list.startsWith('#') - ? list - : `#${list}`), -}) { - return { - annotation: `withPropertiesFromList`, - flags: {expose: true, compose: true}, +export const withPropertiesFromList = templateCompositeFrom({ + annotation: `withPropertiesFromList`, - expose: { - mapDependencies: {list}, - options: {prefix, properties}, + inputs: { + list: input({type: 'array'}), + + properties: input({ + validate: validateArrayItems(isString), + }), - compute(continuation, {list, '#options': {prefix, properties}}) { - const lists = + prefix: input({ + type: 'string', + null: true, + }), + }, + + outputs: ({ + [input.staticDependency('list')]: list, + [input.staticValue('properties')]: properties, + [input.staticValue('prefix')]: prefix, + }) => + (properties + ? properties.map(property => + (prefix + ? `${prefix}.${property}` + : list + ? `${list}.${property}` + : `#list.${property}`)) + : '#lists'), + + steps: () => [ + { + dependencies: [input('list'), input('properties')], + compute: (continuation, { + [input('list')]: list, + [input('properties')]: properties, + }) => continuation({ + ['#lists']: Object.fromEntries( - properties.map(property => [`${prefix}.${property}`, []])); + properties.map(property => [ + property, + list.map(item => item[property] ?? null), + ])), + }), + }, - for (const item of list) { - for (const property of properties) { - lists[`${prefix}.${property}`].push( - (item === null || item === undefined - ? null - : item[property] ?? null)); - } - } + { + dependencies: [ + input.staticDependency('list'), + input.staticValue('properties'), + input.staticValue('prefix'), + '#lists', + ], - return continuation(lists); - } - } - } -} + compute: (continuation, { + [input.staticDependency('list')]: list, + [input.staticValue('properties')]: properties, + [input.staticValue('prefix')]: prefix, + ['#lists']: lists, + }) => + (properties + ? continuation( + Object.fromEntries( + properties.map(property => [ + (prefix + ? `${prefix}.${property}` + : list + ? `${list}.${property}` + : `#list.${property}`), + lists[property], + ]))) + : continuation({'#lists': lists})), + }, + ], +}); // Replaces items of a list, which are null or undefined, with some fallback // value, either a constant (set {value}) or from a dependency ({dependency}). diff --git a/src/data/things/thing.js b/src/data/things/thing.js index 265cfe1..f63a619 100644 --- a/src/data/things/thing.js +++ b/src/data/things/thing.js @@ -363,7 +363,7 @@ export const contribsPresent = templateCompositeFrom({ steps: () => [ withResultOfAvailabilityCheck({ - fromDependency: input('contribs'), + from: input('contribs'), mode: input.value('empty'), }), diff --git a/src/data/things/track.js b/src/data/things/track.js index 05b762b..f31fe3a 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -68,10 +68,18 @@ export class Track extends Thing { }), withContainingTrackSection(), - withPropertyFromObject({object: '#trackSection', property: 'color'}), + + withPropertyFromObject({ + object: '#trackSection', + property: input.value('color'), + }), + exposeDependencyOrContinue({dependency: '#trackSection.color'}), - withPropertyFromAlbum({property: 'color'}), + withPropertyFromAlbum({ + property: input.value('color'), + }), + exposeDependency({dependency: '#album.color'}), ], @@ -127,9 +135,15 @@ export class Track extends Thing { validate: input.value(isFileExtension), }), - withPropertyFromAlbum({property: 'trackCoverArtFileExtension'}), + withPropertyFromAlbum({ + property: input.value('trackCoverArtFileExtension'), + }), + exposeDependencyOrContinue({dependency: '#album.trackCoverArtFileExtension'}), - exposeConstant({value: 'jpg'}), + + exposeConstant({ + value: input.value('jpg'), + }), ], // Date of cover art release. Like coverArtFileExtension, this represents @@ -148,7 +162,10 @@ export class Track extends Thing { validate: input.value(isDate), }), - withPropertyFromAlbum({property: 'trackArtDate'}), + withPropertyFromAlbum({ + property: input.value('trackArtDate'), + }), + exposeDependency({dependency: '#album.trackArtDate'}), ], @@ -185,7 +202,10 @@ export class Track extends Thing { exposeDependencyOrContinue({dependency: '#artistContribs'}), - withPropertyFromAlbum({property: 'artistContribs'}), + withPropertyFromAlbum({ + property: input.value('artistContribs'), + }), + exposeDependency({dependency: '#album.artistContribs'}), ], @@ -208,7 +228,10 @@ export class Track extends Thing { exposeDependencyOrContinue({dependency: '#coverArtistContribs'}), - withPropertyFromAlbum({property: 'trackCoverArtistContribs'}), + withPropertyFromAlbum({ + property: input.value('trackCoverArtistContribs'), + }), + exposeDependency({dependency: '#album.trackCoverArtistContribs'}), ], @@ -257,7 +280,11 @@ export class Track extends Thing { date: [ exposeDependencyOrContinue({dependency: 'dateFirstReleased'}), - withPropertyFromAlbum({property: 'date'}), + + withPropertyFromAlbum({ + property: input.value('date'), + }), + exposeDependency({dependency: '#album.date'}), ], @@ -608,9 +635,7 @@ export const withHasUniqueCoverArt = templateCompositeFrom({ : continuation()), }, - withResolvedContribs({ - from: 'coverArtistContribs', - }), + withResolvedContribs({from: 'coverArtistContribs'}), { dependencies: ['#resolvedContribs'], @@ -625,7 +650,9 @@ export const withHasUniqueCoverArt = templateCompositeFrom({ })), }, - withPropertyFromAlbum({property: 'trackCoverArtistContribs'}), + withPropertyFromAlbum({ + property: input.value('trackCoverArtistContribs'), + }), { dependencies: ['#album.trackCoverArtistContribs'], @@ -663,6 +690,8 @@ export const exitWithoutUniqueCoverArt = templateCompositeFrom({ export const trackReverseReferenceList = templateCompositeFrom({ annotation: `trackReverseReferenceList`, + compose: false, + inputs: { list: input({type: 'string'}), }, -- cgit 1.3.0-6-gf8a5