diff options
Diffstat (limited to 'src/thing')
-rw-r--r-- | src/thing/album.js | 62 | ||||
-rw-r--r-- | src/thing/structures.js | 32 | ||||
-rw-r--r-- | src/thing/thing.js | 66 |
3 files changed, 0 insertions, 160 deletions
diff --git a/src/thing/album.js b/src/thing/album.js deleted file mode 100644 index e99cfc3..0000000 --- a/src/thing/album.js +++ /dev/null @@ -1,62 +0,0 @@ -import Thing from './thing.js'; - -import { - validateDirectory, - validateReference -} from './structures.js'; - -import { - showAggregate, - withAggregate -} from '../util/sugar.js'; - -export default class Album extends Thing { - #directory = null; - #tracks = []; - - static updateError = { - directory: Thing.extendPropertyError('directory'), - tracks: Thing.extendPropertyError('tracks') - }; - - update(source) { - const err = this.constructor.updateError; - - withAggregate(({ nest, filter, throws }) => { - - if (source.directory) { - nest(throws(err.directory), ({ call }) => { - if (call(validateDirectory, source.directory)) { - this.#directory = source.directory; - } - }); - } - - if (source.tracks) - this.#tracks = filter(source.tracks, validateReference('track'), throws(err.tracks)); - }); - } - - get directory() { return this.#directory; } - get tracks() { return this.#tracks; } -} - -const album = new Album(); - -console.log('tracks (before):', album.tracks); - -try { - album.update({ - directory: 'oh yes', - tracks: [ - 'lol', - 123, - 'track:oh-yeah', - 'group:what-am-i-doing-here' - ] - }); -} catch (error) { - showAggregate(error); -} - -console.log('tracks (after):', album.tracks); diff --git a/src/thing/structures.js b/src/thing/structures.js deleted file mode 100644 index 89c9bd3..0000000 --- a/src/thing/structures.js +++ /dev/null @@ -1,32 +0,0 @@ -// Generic structure utilities common across various Thing types. - -export function validateDirectory(directory) { - if (typeof directory !== 'string') - throw new TypeError(`Expected a string, got ${directory}`); - - if (directory.length === 0) - throw new TypeError(`Expected directory to be non-zero length`); - - if (directory.match(/[^a-zA-Z0-9\-]/)) - throw new TypeError(`Expected only letters, numbers, and dash, got "${directory}"`); - - return true; -} - -export function validateReference(type = '') { - return ref => { - if (typeof ref !== 'string') - throw new TypeError(`Expected a string, got ${ref}`); - - if (type) { - if (!ref.includes(':')) - throw new TypeError(`Expected ref to begin with "${type}:", but no type specified (ref: ${ref})`); - - const typePart = ref.split(':')[0]; - if (typePart !== type) - throw new TypeError(`Expected ref to begin with "${type}:", got "${typePart}:" (ref: ${ref})`); - } - - return true; - }; -} diff --git a/src/thing/thing.js b/src/thing/thing.js deleted file mode 100644 index c2465e3..0000000 --- a/src/thing/thing.js +++ /dev/null @@ -1,66 +0,0 @@ -// Base class for Things. No, we will not come up with a better name. -// Sorry not sorry! :) -// -// NB: Since these methods all involve processing a variety of input data, some -// of which will pass and some of which may fail, any failures should be thrown -// together as an AggregateError. See util/sugar.js for utility functions to -// make writing code around this easier! - -export default class Thing { - constructor(source, { - wikiData - } = {}) { - if (source) { - this.update(source); - } - - if (wikiData && this.checkComplete()) { - this.postprocess({wikiData}); - } - } - - static PropertyError = class extends AggregateError { - #key = this.constructor.key; - get key() { return this.#key; } - - constructor(errors) { - super(errors, ''); - this.message = `${errors.length} error(s) in property "${this.#key}"`; - } - }; - - static extendPropertyError(key) { - const cls = class extends this.PropertyError { - static #key = key; - static get key() { return this.#key; } - }; - - Object.defineProperty(cls, 'name', {value: `PropertyError:${key}`}); - return cls; - } - - // Called when instantiating a thing, and when its data is updated for any - // reason. (Which currently includes no reasons, but hey, future-proofing!) - // - // Don't expect source to be a complete object, even on the first call - the - // method checkComplete() will prevent incomplete resources from being mixed - // with the rest. - update(source) {} - - // Called when collecting the full list of available things of that type - // for wiki data; this method determine whether or not to include it. - // - // This should return whether or not the object is complete enough to be - // used across the wiki - not whether every optional attribute is provided! - // (That is, attributes required for postprocessing & basic page generation - // are all present.) - checkComplete() {} - - // Called when adding the thing to the wiki data list, and when its source - // data is updated (provided checkComplete() passes). - // - // This should generate any cached object references, across other wiki - // data; for example, building an array of actual track objects - // corresponding to an album's track list ('track:cool-track' strings). - postprocess({wikiData}) {} -} |