diff options
Diffstat (limited to 'src/data/composite/wiki-properties')
24 files changed, 558 insertions, 0 deletions
diff --git a/src/data/composite/wiki-properties/additionalFiles.js b/src/data/composite/wiki-properties/additionalFiles.js new file mode 100644 index 0000000..6760527 --- /dev/null +++ b/src/data/composite/wiki-properties/additionalFiles.js @@ -0,0 +1,30 @@ +// This is a somewhat more involved data structure - it's for additional +// or "bonus" files associated with albums or tracks (or anything else). +// It's got this form: +// +// [ +// {title: 'Booklet', files: ['Booklet.pdf']}, +// { +// title: 'Wallpaper', +// description: 'Cool Wallpaper!', +// files: ['1440x900.png', '1920x1080.png'] +// }, +// {title: 'Alternate Covers', description: null, files: [...]}, +// ... +// ] +// + +import {isAdditionalFileList} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isAdditionalFileList}, + expose: { + transform: (additionalFiles) => + additionalFiles ?? [], + }, + }; +} diff --git a/src/data/composite/wiki-properties/additionalNameList.js b/src/data/composite/wiki-properties/additionalNameList.js new file mode 100644 index 0000000..c5971d4 --- /dev/null +++ b/src/data/composite/wiki-properties/additionalNameList.js @@ -0,0 +1,14 @@ +// A list of additional names! These can be used for a variety of purposes, +// e.g. providing extra searchable titles, localizations, romanizations or +// original titles, and so on. Each item has a name and, optionally, a +// descriptive annotation. + +import {isAdditionalNameList} from '#validators'; + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isAdditionalNameList}, + expose: {transform: value => value ?? []}, + }; +} diff --git a/src/data/composite/wiki-properties/color.js b/src/data/composite/wiki-properties/color.js new file mode 100644 index 0000000..1bc9888 --- /dev/null +++ b/src/data/composite/wiki-properties/color.js @@ -0,0 +1,12 @@ +// A color! This'll be some CSS-ready value. + +import {isColor} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isColor}, + }; +} diff --git a/src/data/composite/wiki-properties/commentary.js b/src/data/composite/wiki-properties/commentary.js new file mode 100644 index 0000000..cd6b7ac --- /dev/null +++ b/src/data/composite/wiki-properties/commentary.js @@ -0,0 +1,30 @@ +// Artist commentary! Generally present on tracks and albums. + +import {input, templateCompositeFrom} from '#composite'; +import {isCommentary} from '#validators'; + +import {exitWithoutDependency, exposeDependency} + from '#composite/control-flow'; +import {withParsedCommentaryEntries} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `commentary`, + + compose: false, + + steps: () => [ + exitWithoutDependency({ + dependency: input.updateValue({validate: isCommentary}), + mode: input.value('falsy'), + value: input.value(null), + }), + + withParsedCommentaryEntries({ + from: input.updateValue(), + }), + + exposeDependency({ + dependency: '#parsedCommentaryEntries', + }), + ], +}); diff --git a/src/data/composite/wiki-properties/commentatorArtists.js b/src/data/composite/wiki-properties/commentatorArtists.js new file mode 100644 index 0000000..c5c1476 --- /dev/null +++ b/src/data/composite/wiki-properties/commentatorArtists.js @@ -0,0 +1,49 @@ +// List of artists referenced in commentary entries. +// This is mostly useful for credits and listings on artist pages. + +import {input, templateCompositeFrom} from '#composite'; + +import {exitWithoutDependency, exposeDependency} + from '#composite/control-flow'; +import {withFlattenedList, withPropertyFromList, withUniqueItemsOnly} + from '#composite/data'; +import {withParsedCommentaryEntries} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `commentatorArtists`, + + compose: false, + + steps: () => [ + exitWithoutDependency({ + dependency: 'commentary', + mode: input.value('falsy'), + value: input.value([]), + }), + + withParsedCommentaryEntries({ + from: 'commentary', + }), + + withPropertyFromList({ + list: '#parsedCommentaryEntries', + property: input.value('artists'), + }).outputs({ + '#parsedCommentaryEntries.artists': '#artistLists', + }), + + withFlattenedList({ + list: '#artistLists', + }).outputs({ + '#flattenedList': '#artists', + }), + + withUniqueItemsOnly({ + list: '#artists', + }), + + exposeDependency({ + dependency: '#artists', + }), + ], +}); diff --git a/src/data/composite/wiki-properties/contentString.js b/src/data/composite/wiki-properties/contentString.js new file mode 100644 index 0000000..b0e8244 --- /dev/null +++ b/src/data/composite/wiki-properties/contentString.js @@ -0,0 +1,15 @@ +// String type that's slightly more specific than simpleString. If the +// property is a generic piece of human-reading content, this adds some +// useful valiation on top of simpleString - but still check if more +// particular properties like `name` are more appropriate. +// +// This type adapts validation for single- and multiline content. + +import {isContentString} from '#validators'; + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isContentString}, + }; +} diff --git a/src/data/composite/wiki-properties/contribsPresent.js b/src/data/composite/wiki-properties/contribsPresent.js new file mode 100644 index 0000000..24f302a --- /dev/null +++ b/src/data/composite/wiki-properties/contribsPresent.js @@ -0,0 +1,30 @@ +// Nice 'n simple shorthand for an exposed-only flag which is true when any +// contributions are present in the specified property. + +import {input, templateCompositeFrom} from '#composite'; +import {isContributionList} from '#validators'; + +import {exposeDependency, withResultOfAvailabilityCheck} + from '#composite/control-flow'; + +export default templateCompositeFrom({ + annotation: `contribsPresent`, + + compose: false, + + inputs: { + contribs: input.staticDependency({ + validate: isContributionList, + acceptsNull: true, + }), + }, + + steps: () => [ + withResultOfAvailabilityCheck({ + from: input('contribs'), + mode: input.value('empty'), + }), + + exposeDependency({dependency: '#availability'}), + ], +}); diff --git a/src/data/composite/wiki-properties/contributionList.js b/src/data/composite/wiki-properties/contributionList.js new file mode 100644 index 0000000..8fde2ca --- /dev/null +++ b/src/data/composite/wiki-properties/contributionList.js @@ -0,0 +1,35 @@ +// Strong 'n sturdy contribution list, rolling a list of references (provided +// as this property's update value) and the resolved results (as get exposed) +// into one property. Update value will look something like this: +// +// [ +// {who: 'Artist Name', what: 'Viola'}, +// {who: 'artist:john-cena', what: null}, +// ... +// ] +// +// ...typically as processed from YAML, spreadsheet, or elsewhere. +// Exposes as the same, but with the "who" replaced with matches found in +// artistData - which means this always depends on an `artistData` property +// also existing on this object! +// + +import {input, templateCompositeFrom} from '#composite'; +import {isContributionList} from '#validators'; + +import {exposeConstant, exposeDependencyOrContinue} from '#composite/control-flow'; +import {withResolvedContribs} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `contributionList`, + + compose: false, + + update: {validate: isContributionList}, + + steps: () => [ + withResolvedContribs({from: input.updateValue()}), + exposeDependencyOrContinue({dependency: '#resolvedContribs'}), + exposeConstant({value: input.value([])}), + ], +}); diff --git a/src/data/composite/wiki-properties/dimensions.js b/src/data/composite/wiki-properties/dimensions.js new file mode 100644 index 0000000..57a0127 --- /dev/null +++ b/src/data/composite/wiki-properties/dimensions.js @@ -0,0 +1,13 @@ +// Plain ol' image dimensions. This is a two-item array of positive integers, +// corresponding to width and height respectively. + +import {isDimensions} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isDimensions}, + }; +} diff --git a/src/data/composite/wiki-properties/directory.js b/src/data/composite/wiki-properties/directory.js new file mode 100644 index 0000000..0b2181c --- /dev/null +++ b/src/data/composite/wiki-properties/directory.js @@ -0,0 +1,23 @@ +// The all-encompassing "directory" property, used as the unique identifier for +// almost any data object. Also corresponds to a part of the URL which pages of +// such objects are visited at. + +import {isDirectory} from '#validators'; +import {getKebabCase} from '#wiki-data'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isDirectory}, + expose: { + dependencies: ['name'], + transform(directory, {name}) { + if (directory === null && name === null) return null; + else if (directory === null) return getKebabCase(name); + else return directory; + }, + }, + }; +} diff --git a/src/data/composite/wiki-properties/duration.js b/src/data/composite/wiki-properties/duration.js new file mode 100644 index 0000000..827f282 --- /dev/null +++ b/src/data/composite/wiki-properties/duration.js @@ -0,0 +1,13 @@ +// Duration! This is a number of seconds, possibly floating point, always +// at minimum zero. + +import {isDuration} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isDuration}, + }; +} diff --git a/src/data/composite/wiki-properties/externalFunction.js b/src/data/composite/wiki-properties/externalFunction.js new file mode 100644 index 0000000..c388da6 --- /dev/null +++ b/src/data/composite/wiki-properties/externalFunction.js @@ -0,0 +1,11 @@ +// External function. These should only be used as dependencies for other +// properties, so they're left unexposed. + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true}, + update: {validate: (t) => typeof t === 'function'}, + }; +} diff --git a/src/data/composite/wiki-properties/fileExtension.js b/src/data/composite/wiki-properties/fileExtension.js new file mode 100644 index 0000000..c926fa8 --- /dev/null +++ b/src/data/composite/wiki-properties/fileExtension.js @@ -0,0 +1,13 @@ +// A file extension! Or the default, if provided when calling this. + +import {isFileExtension} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function(defaultFileExtension = null) { + return { + flags: {update: true, expose: true}, + update: {validate: isFileExtension}, + expose: {transform: (value) => value ?? defaultFileExtension}, + }; +} diff --git a/src/data/composite/wiki-properties/flag.js b/src/data/composite/wiki-properties/flag.js new file mode 100644 index 0000000..076e663 --- /dev/null +++ b/src/data/composite/wiki-properties/flag.js @@ -0,0 +1,19 @@ +// Straightforward flag descriptor for a variety of property purposes. +// Provide a default value, true or false! + +import {isBoolean} from '#validators'; + +// TODO: Not templateCompositeFrom. + +// TODO: The description is a lie. This defaults to false. Bad. + +export default function(defaultValue = false) { + if (typeof defaultValue !== 'boolean') { + throw new TypeError(`Always set explicit defaults for flags!`); + } + + return { + flags: {update: true, expose: true}, + update: {validate: isBoolean, default: defaultValue}, + }; +} diff --git a/src/data/composite/wiki-properties/index.js b/src/data/composite/wiki-properties/index.js new file mode 100644 index 0000000..89cb683 --- /dev/null +++ b/src/data/composite/wiki-properties/index.js @@ -0,0 +1,28 @@ +// #composite/wiki-properties +// +// Entries here may depend on entries in #composite/control-flow, +// #composite/data, and #composite/wiki-data. + +export {default as additionalFiles} from './additionalFiles.js'; +export {default as additionalNameList} from './additionalNameList.js'; +export {default as color} from './color.js'; +export {default as commentary} from './commentary.js'; +export {default as commentatorArtists} from './commentatorArtists.js'; +export {default as contentString} from './contentString.js'; +export {default as contribsPresent} from './contribsPresent.js'; +export {default as contributionList} from './contributionList.js'; +export {default as dimensions} from './dimensions.js'; +export {default as directory} from './directory.js'; +export {default as duration} from './duration.js'; +export {default as externalFunction} from './externalFunction.js'; +export {default as fileExtension} from './fileExtension.js'; +export {default as flag} from './flag.js'; +export {default as name} from './name.js'; +export {default as referenceList} from './referenceList.js'; +export {default as reverseContributionList} from './reverseContributionList.js'; +export {default as reverseReferenceList} from './reverseReferenceList.js'; +export {default as simpleDate} from './simpleDate.js'; +export {default as simpleString} from './simpleString.js'; +export {default as singleReference} from './singleReference.js'; +export {default as urls} from './urls.js'; +export {default as wikiData} from './wikiData.js'; diff --git a/src/data/composite/wiki-properties/name.js b/src/data/composite/wiki-properties/name.js new file mode 100644 index 0000000..5146488 --- /dev/null +++ b/src/data/composite/wiki-properties/name.js @@ -0,0 +1,11 @@ +// A wiki data object's name! Its directory (i.e. unique identifier) will be +// computed based on this value if not otherwise specified. + +import {isName} from '#validators'; + +export default function(defaultName) { + return { + flags: {update: true, expose: true}, + update: {validate: isName, default: defaultName}, + }; +} diff --git a/src/data/composite/wiki-properties/referenceList.js b/src/data/composite/wiki-properties/referenceList.js new file mode 100644 index 0000000..af634a6 --- /dev/null +++ b/src/data/composite/wiki-properties/referenceList.js @@ -0,0 +1,45 @@ +// Stores and exposes a list of references to other data objects; all items +// must be references to the same type, which is specified on the class input. +// +// See also: +// - singleReference +// - withResolvedReferenceList +// + +import {input, templateCompositeFrom} from '#composite'; +import {isThingClass, validateReferenceList} from '#validators'; + +import {exposeDependency} from '#composite/control-flow'; +import {inputWikiData, withResolvedReferenceList} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `referenceList`, + + compose: false, + + inputs: { + class: input.staticValue({validate: isThingClass}), + + data: inputWikiData({allowMixedTypes: false}), + + find: input({type: 'function'}), + }, + + update: ({ + [input.staticValue('class')]: thingClass, + }) => ({ + validate: + validateReferenceList( + thingClass[Symbol.for('Thing.referenceType')]), + }), + + steps: () => [ + withResolvedReferenceList({ + list: input.updateValue(), + data: input('data'), + find: input('find'), + }), + + exposeDependency({dependency: '#resolvedReferenceList'}), + ], +}); diff --git a/src/data/composite/wiki-properties/reverseContributionList.js b/src/data/composite/wiki-properties/reverseContributionList.js new file mode 100644 index 0000000..7f3f9c8 --- /dev/null +++ b/src/data/composite/wiki-properties/reverseContributionList.js @@ -0,0 +1,24 @@ +import {input, templateCompositeFrom} from '#composite'; + +import {exposeDependency} from '#composite/control-flow'; +import {inputWikiData, withReverseContributionList} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `reverseContributionList`, + + compose: false, + + inputs: { + data: inputWikiData({allowMixedTypes: false}), + list: input({type: 'string'}), + }, + + steps: () => [ + withReverseContributionList({ + data: input('data'), + list: input('list'), + }), + + exposeDependency({dependency: '#reverseContributionList'}), + ], +}); diff --git a/src/data/composite/wiki-properties/reverseReferenceList.js b/src/data/composite/wiki-properties/reverseReferenceList.js new file mode 100644 index 0000000..84ba67d --- /dev/null +++ b/src/data/composite/wiki-properties/reverseReferenceList.js @@ -0,0 +1,30 @@ +// Neat little shortcut for "reversing" the reference lists stored on other +// things - for example, tracks specify a "referenced tracks" property, and +// you would use this to compute a corresponding "referenced *by* tracks" +// property. Naturally, the passed ref list property is of the things in the +// wiki data provided, not the requesting Thing itself. + +import {input, templateCompositeFrom} from '#composite'; + +import {exposeDependency} from '#composite/control-flow'; +import {inputWikiData, withReverseReferenceList} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `reverseReferenceList`, + + compose: false, + + inputs: { + data: inputWikiData({allowMixedTypes: false}), + list: input({type: 'string'}), + }, + + steps: () => [ + withReverseReferenceList({ + data: input('data'), + list: input('list'), + }), + + exposeDependency({dependency: '#reverseReferenceList'}), + ], +}); diff --git a/src/data/composite/wiki-properties/simpleDate.js b/src/data/composite/wiki-properties/simpleDate.js new file mode 100644 index 0000000..f08d832 --- /dev/null +++ b/src/data/composite/wiki-properties/simpleDate.js @@ -0,0 +1,14 @@ +// General date type, used as the descriptor for a bunch of properties. +// This isn't dynamic though - it won't inherit from a date stored on +// another object, for example. + +import {isDate} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isDate}, + }; +} diff --git a/src/data/composite/wiki-properties/simpleString.js b/src/data/composite/wiki-properties/simpleString.js new file mode 100644 index 0000000..7bf317a --- /dev/null +++ b/src/data/composite/wiki-properties/simpleString.js @@ -0,0 +1,12 @@ +// General string type. This should probably generally be avoided in favor +// of more specific validation, but using it makes it easy to find where we +// might want to improve later, and it's a useful shorthand meanwhile. + +import {isString} from '#validators'; + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: isString}, + }; +} diff --git a/src/data/composite/wiki-properties/singleReference.js b/src/data/composite/wiki-properties/singleReference.js new file mode 100644 index 0000000..db4fc9f --- /dev/null +++ b/src/data/composite/wiki-properties/singleReference.js @@ -0,0 +1,46 @@ +// Stores and exposes one connection, or reference, to another data object. +// The reference must be to a specific type, which is specified on the class +// input. +// +// See also: +// - referenceList +// - withResolvedReference +// + +import {input, templateCompositeFrom} from '#composite'; +import {isThingClass, validateReference} from '#validators'; + +import {exposeDependency} from '#composite/control-flow'; +import {inputWikiData, withResolvedReference} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `singleReference`, + + compose: false, + + inputs: { + class: input.staticValue({validate: isThingClass}), + + find: input({type: 'function'}), + + data: inputWikiData({allowMixedTypes: false}), + }, + + update: ({ + [input.staticValue('class')]: thingClass, + }) => ({ + validate: + validateReference( + thingClass[Symbol.for('Thing.referenceType')]), + }), + + steps: () => [ + withResolvedReference({ + ref: input.updateValue(), + data: input('data'), + find: input('find'), + }), + + exposeDependency({dependency: '#resolvedReference'}), + ], +}); diff --git a/src/data/composite/wiki-properties/urls.js b/src/data/composite/wiki-properties/urls.js new file mode 100644 index 0000000..3160a0b --- /dev/null +++ b/src/data/composite/wiki-properties/urls.js @@ -0,0 +1,14 @@ +// A list of URLs! This will always be present on the data object, even if set +// to an empty array or null. + +import {isURL, validateArrayItems} from '#validators'; + +// TODO: Not templateCompositeFrom. + +export default function() { + return { + flags: {update: true, expose: true}, + update: {validate: validateArrayItems(isURL)}, + expose: {transform: value => value ?? []}, + }; +} diff --git a/src/data/composite/wiki-properties/wikiData.js b/src/data/composite/wiki-properties/wikiData.js new file mode 100644 index 0000000..3bebed3 --- /dev/null +++ b/src/data/composite/wiki-properties/wikiData.js @@ -0,0 +1,27 @@ +// General purpose wiki data constructor, for properties like artistData, +// trackData, etc. + +import {input, templateCompositeFrom} from '#composite'; +import {isThingClass, validateWikiData} from '#validators'; + +export default templateCompositeFrom({ + annotation: `wikiData`, + + compose: false, + + inputs: { + class: input.staticValue({validate: isThingClass}), + }, + + update: ({ + [input.staticValue('class')]: thingClass, + }) => ({ + validate: + validateWikiData({ + referenceType: + thingClass[Symbol.for('Thing.referenceType')], + }), + }), + + steps: () => [], +}); |