From cc4bf401f4d1df63ce33191ae82af6327c7da568 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 20 Sep 2023 17:33:50 -0300 Subject: data: fix many validation errors --- src/data/things/album.js | 70 +++++++++++++---------- src/data/things/artist.js | 5 +- src/data/things/composite.js | 113 +++++++++++++++++++++++-------------- src/data/things/flash.js | 9 +-- src/data/things/group.js | 9 +-- src/data/things/homepage-layout.js | 8 +-- src/data/things/index.js | 7 ++- src/data/things/thing.js | 8 +-- src/data/things/track.js | 52 ++++++++++------- src/data/things/wiki-info.js | 5 +- 10 files changed, 172 insertions(+), 114 deletions(-) diff --git a/src/data/things/album.js b/src/data/things/album.js index ec133a3..44af5cb 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -10,9 +10,9 @@ import { exposeUpdateValueOrContinue, input, fillMissingListItems, - withFlattenedArray, + withFlattenedList, withPropertiesFromList, - withUnflattenedArray, + withUnflattenedList, } from '#composite'; import Thing, { @@ -101,8 +101,15 @@ export class Album extends Thing { additionalFiles: additionalFiles(), trackSections: [ - exitWithoutDependency({dependency: 'trackData', value: []}), - exitWithoutUpdateValue({value: [], mode: 'empty'}), + exitWithoutDependency({ + dependency: 'trackData', + value: input.value([]), + }), + + exitWithoutUpdateValue({ + mode: input.value('empty'), + value: input.value([]), + }), withPropertiesFromList({ list: input.updateValue(), @@ -119,32 +126,27 @@ export class Album extends Thing { fillMissingListItems({list: '#sections.isDefaultTrackSection', value: false}), fillMissingListItems({list: '#sections.color', dependency: 'color'}), - withFlattenedArray({ - from: '#sections.tracks', - into: '#trackRefs', - intoIndices: '#sections.startIndex', + withFlattenedList({ + list: '#sections.tracks', + }).outputs({ + ['#flattenedList']: '#trackRefs', + ['#flattenedIndices']: '#sections.startIndex', }), - { - dependencies: ['#trackRefs'], - compute: ({'#trackRefs': tracks}, continuation) => { - console.log(tracks); - return continuation(); - } - }, - withResolvedReferenceList({ list: '#trackRefs', data: 'trackData', - notFoundMode: 'null', - find: find.track, - into: '#tracks', + notFoundMode: input.value('null'), + find: input.value(find.track), + }).outputs({ + ['#resolvedReferenceList']: '#tracks', }), - withUnflattenedArray({ - from: '#tracks', - fromIndices: '#sections.startIndex', - into: '#sections.tracks', + withUnflattenedList({ + list: '#tracks', + indices: '#sections.startIndex', + }).outputs({ + ['#unflattenedList']: '#sections.tracks', }), { @@ -191,14 +193,14 @@ export class Album extends Thing { bannerArtistContribs: contributionList(), groups: referenceList({ - class: Group, - find: find.group, + class: input.value(Group), + find: input.value(find.group), data: 'groupData', }), artTags: referenceList({ - class: ArtTag, - find: find.artTag, + class: input.value(ArtTag), + find: input.value(find.artTag), data: 'artTagData', }), @@ -218,8 +220,16 @@ export class Album extends Thing { hasBannerArt: contribsPresent({contribs: 'bannerArtistContribs'}), tracks: [ - exitWithoutDependency({dependency: 'trackData', value: []}), - exitWithoutDependency({dependency: 'trackSections', mode: 'empty', value: []}), + exitWithoutDependency({ + dependency: 'trackData', + value: input.value([]), + }), + + exitWithoutDependency({ + dependency: 'trackSections', + mode: input.value('empty'), + value: input.value([]), + }), { dependencies: ['trackSections'], @@ -233,7 +243,7 @@ export class Album extends Thing { withResolvedReferenceList({ list: '#trackRefs', data: 'trackData', - find: find.track, + find: input.value(find.track), }), exposeDependency({dependency: '#resolvedReferenceList'}), diff --git a/src/data/things/artist.js b/src/data/things/artist.js index 7a9dbd3..085e566 100644 --- a/src/data/things/artist.js +++ b/src/data/things/artist.js @@ -1,3 +1,4 @@ +import {input} from '#composite'; import find from '#find'; import {isName, validateArrayItems} from '#validators'; @@ -35,8 +36,8 @@ export class Artist extends Thing { isAlias: flag(), aliasedArtist: singleReference({ - class: Artist, - find: find.artist, + class: input.value(Artist), + find: input.value(find.artist), data: 'artistData', }), diff --git a/src/data/things/composite.js b/src/data/things/composite.js index fbdc52f..83879c5 100644 --- a/src/data/things/composite.js +++ b/src/data/things/composite.js @@ -1,9 +1,15 @@ import {inspect} from 'node:util'; import {colors} from '#cli'; -import {isArray, oneOf} from '#validators'; import {TupleMap} from '#wiki-data'; +import { + isArray, + isWholeNumber, + oneOf, + validateArrayItems, +} from '#validators'; + import { decorateErrorWithIndex, empty, @@ -1876,72 +1882,93 @@ export const excludeFromList = templateCompositeFrom({ // 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. -export function withFlattenedArray({ - from, - into = '#flattenedArray', - intoIndices = '#flattenedIndices', -}) { - return { - annotation: `withFlattenedArray`, - flags: {expose: true, compose: true}, +export const withFlattenedList = templateCompositeFrom({ + annotation: `withFlattenedList`, - expose: { - mapDependencies: {from}, - mapContinuation: {into, intoIndices}, + inputs: { + list: input({type: 'array'}), + }, - compute({from: sourceArray}, continuation) { - const into = sourceArray.flat(); - const intoIndices = []; + outputs: ['#flattenedList', '#flattenedIndices'], + steps: () => [ + { + dependencies: [input('list')], + compute(continuation, { + [input('list')]: sourceList, + }) { + const flattenedList = sourceList.flat(); + const indices = []; let lastEndIndex = 0; for (const {length} of sourceArray) { - intoIndices.push(lastEndIndex); + indices.push(lastEndIndex); lastEndIndex += length; } - return continuation({into, intoIndices}); + return continuation({ + ['#flattenedList']: flattenedList, + ['#flattenedIndices']: indices, + }); }, }, - }; -} + ], +}); // After mapping the contents of a flattened array in-place (being careful to // retain the original indices by replacing unmatched results with null instead // of filtering them out), this function allows for recombining them. It will // filter out null and undefined items by default (pass {filter: false} to // disable this). -export function withUnflattenedArray({ - from, - fromIndices = '#flattenedIndices', - into = '#unflattenedArray', - filter = true, -}) { - return { - annotation: `withUnflattenedArray`, - flags: {expose: true, compose: true}, +export const withUnflattenedList = templateCompositeFrom({ + annotation: `withUnflattenedList`, - expose: { - mapDependencies: {from, fromIndices}, - mapContinuation: {into}, - compute({from, fromIndices}, continuation) { - const arrays = []; + inputs: { + list: input({ + type: 'array', + defaultDependency: '#flattenedList', + }), + + indices: input({ + validate: validateArrayItems(isWholeNumber), + defaultDependency: '#flattenedIndices', + }), + + filter: input({ + type: 'boolean', + defaultValue: true, + }), + }, - for (let i = 0; i < fromIndices.length; i++) { - const startIndex = fromIndices[i]; + outputs: ['#unflattenedList'], + + steps: () => [ + { + dependencies: [input('list'), input('indices')], + compute({ + [input('list')]: list, + [input('indices')]: indices, + [input('filter')]: filter, + }) { + const unflattenedList = []; + + for (let i = 0; i < indices.length; i++) { + const startIndex = indices[i]; const endIndex = - (i === fromIndices.length - 1 - ? from.length - : fromIndices[i + 1]); + (i === indices.length - 1 + ? list.length + : indices[i + 1]); - const values = from.slice(startIndex, endIndex); - arrays.push( + const values = list.slice(startIndex, endIndex); + unflattenedList.push( (filter ? values.filter(value => value !== null && value !== undefined) : values)); } - return continuation({into: arrays}); + return continuation({ + ['#unflattenedList']: unflattenedList, + }); }, }, - }; -} + ], +}); diff --git a/src/data/things/flash.js b/src/data/things/flash.js index eb16d29..c3f9026 100644 --- a/src/data/things/flash.js +++ b/src/data/things/flash.js @@ -1,3 +1,4 @@ +import {input} from '#composite'; import find from '#find'; import { @@ -61,8 +62,8 @@ export class Flash extends Thing { contributorContribs: contributionList(), featuredTracks: referenceList({ - class: Track, - find: find.track, + class: input.value(Track), + find: input.value(find.track), data: 'trackData', }), @@ -133,9 +134,9 @@ export class FlashAct extends Thing { }, flashes: referenceList({ - class: Flash, + class: input.value(Flash), + find: input.value(find.flash), data: 'flashData', - find: find.flash, }), // Update only diff --git a/src/data/things/group.js b/src/data/things/group.js index f53fa48..0b11780 100644 --- a/src/data/things/group.js +++ b/src/data/things/group.js @@ -1,3 +1,4 @@ +import {input} from '#composite'; import find from '#find'; import Thing, { @@ -24,8 +25,8 @@ export class Group extends Thing { urls: urls(), featuredAlbums: referenceList({ - class: Album, - find: find.album, + class: input.value(Album), + find: input.value(find.album), data: 'albumData', }), @@ -87,8 +88,8 @@ export class GroupCategory extends Thing { color: color(), groups: referenceList({ - class: Group, - find: find.group, + class: input.value(Group), + find: input.value(find.group), data: 'groupData', }), diff --git a/src/data/things/homepage-layout.js b/src/data/things/homepage-layout.js index 677a275..bade280 100644 --- a/src/data/things/homepage-layout.js +++ b/src/data/things/homepage-layout.js @@ -107,7 +107,7 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { }, }, - sourceGroup: compositeFrom(`HomepageLayoutAlbumsRow.sourceGroup`, [ + sourceGroup: [ { flags: {expose: true, update: true, compose: true}, @@ -133,11 +133,11 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { }), exposeDependency({dependency: '#resolvedReference'}), - ]), + ], sourceAlbums: referenceList({ - class: Album, - find: find.album, + class: input.value(Album), + find: input.value(find.album), data: 'albumData', }), diff --git a/src/data/things/index.js b/src/data/things/index.js index 4d8d9d1..f908653 100644 --- a/src/data/things/index.js +++ b/src/data/things/index.js @@ -135,7 +135,12 @@ function evaluatePropertyDescriptors() { for (const [key, value] of Object.entries(results)) { if (Array.isArray(value)) { - results[key] = compositeFrom(`${constructor.name}.${key}`, value); + results[key] = compositeFrom({ + annotation: `${constructor.name}.${key}`, + compose: false, + steps: value, + }); + continue; } } diff --git a/src/data/things/thing.js b/src/data/things/thing.js index cff2f49..a75ff3e 100644 --- a/src/data/things/thing.js +++ b/src/data/things/thing.js @@ -211,7 +211,7 @@ export function contributionList() { update: {validate: isContributionList}, - steps: () => [ + steps: [ withResolvedContribs({from: input.updateValue()}), exposeDependencyOrContinue({dependency: '#resolvedContribs'}), exposeConstant({value: []}), @@ -468,8 +468,6 @@ export const withResolvedContribs = templateCompositeFrom({ // todo: validate from: input(), - findFunction: input({type: 'function'}), - notFoundMode: input({ validate: oneOf('exit', 'filter', 'null'), defaultValue: 'null', @@ -496,7 +494,7 @@ export const withResolvedContribs = templateCompositeFrom({ withResolvedReferenceList({ list: '#contribs.who', data: 'artistData', - find: input('find'), + find: input.value(find.artist), notFoundMode: input('notFoundMode'), }).outputs({ ['#resolvedReferenceList']: '#contribs.who', @@ -728,7 +726,7 @@ export const withReverseReferenceList = templateCompositeFrom({ steps: () => [ exitWithoutDependency({ dependency: input('data'), - value: [], + value: input.value([]), }), { diff --git a/src/data/things/track.js b/src/data/things/track.js index 37b3628..05b762b 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -6,6 +6,7 @@ import {empty} from '#sugar'; import { exitWithoutDependency, + excludeFromList, exposeConstant, exposeDependency, exposeDependencyOrContinue, @@ -17,6 +18,7 @@ import { } from '#composite'; import { + isBoolean, isColor, isContributionList, isDate, @@ -136,7 +138,11 @@ export class Track extends Thing { // is specified, this value is null. coverArtDate: [ withHasUniqueCoverArt(), - exitWithoutDependency({dependency: '#hasUniqueCoverArt', mode: 'falsy'}), + + exitWithoutDependency({ + dependency: '#hasUniqueCoverArt', + mode: input.value('falsy'), + }), exposeUpdateValueOrContinue({ validate: input.value(isDate), @@ -154,8 +160,8 @@ export class Track extends Thing { midiProjectFiles: additionalFiles(), originalReleaseTrack: singleReference({ - class: Track, - find: find.track, + class: input.value(Track), + find: input.value(find.track), data: 'trackData', }), @@ -163,8 +169,8 @@ export class Track extends Thing { // util.inspect display, if it isn't indirectly available (by way of being // included in an album's track list). dataSourceAlbum: singleReference({ - class: Album, - find: find.album, + class: input.value(Album), + find: input.value(find.album), data: 'albumData', }), @@ -208,25 +214,27 @@ export class Track extends Thing { referencedTracks: [ inheritFromOriginalRelease({property: 'referencedTracks'}), + referenceList({ - class: Track, - find: find.track, + class: input.value(Track), + find: input.value(find.track), data: 'trackData', }), ], sampledTracks: [ inheritFromOriginalRelease({property: 'sampledTracks'}), + referenceList({ - class: Track, - find: find.track, + class: input.value(Track), + find: input.value(find.track), data: 'trackData', }), ], artTags: referenceList({ - class: ArtTag, - find: find.artTag, + class: input.value(ArtTag), + find: input.value(find.artTag), data: 'artTagData', }), @@ -266,8 +274,14 @@ export class Track extends Thing { ], otherReleases: [ - exitWithoutDependency({dependency: 'trackData', mode: 'empty'}), - withOriginalRelease({selfIfOriginal: true}), + exitWithoutDependency({ + dependency: 'trackData', + mode: input.value('empty'), + }), + + withOriginalRelease({ + selfIfOriginal: input.value(true), + }), { flags: {expose: true}, @@ -594,14 +608,14 @@ export const withHasUniqueCoverArt = templateCompositeFrom({ : continuation()), }, - withResolvedContribs - .inputs({from: 'coverArtistContribs'}) - .outputs({into: '#coverArtistContribs'}), + withResolvedContribs({ + from: 'coverArtistContribs', + }), { - dependencies: ['#coverArtistContribs'], + dependencies: ['#resolvedContribs'], compute: (continuation, { - ['#coverArtistContribs']: contribsFromTrack, + ['#resolvedContribs']: contribsFromTrack, }) => (empty(contribsFromTrack) ? continuation() @@ -640,7 +654,7 @@ export const exitWithoutUniqueCoverArt = templateCompositeFrom({ exitWithoutDependency({ dependency: '#hasUniqueCoverArt', - mode: 'falsy', + mode: input.value('falsy'), value: input('value'), }), ], diff --git a/src/data/things/wiki-info.js b/src/data/things/wiki-info.js index 7c2de32..c764b52 100644 --- a/src/data/things/wiki-info.js +++ b/src/data/things/wiki-info.js @@ -1,3 +1,4 @@ +import {input} from '#composite'; import find from '#find'; import {isLanguageCode, isName, isURL} from '#validators'; @@ -45,8 +46,8 @@ export class WikiInfo extends Thing { }, divideTrackListsByGroups: referenceList({ - class: Group, - find: find.group, + class: input.value(Group), + find: input.value(find.group), data: 'groupData', }), -- cgit 1.3.0-6-gf8a5