« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/data/serialize.js38
-rw-r--r--src/data/things.js78
-rw-r--r--src/static/client.js6
-rwxr-xr-xsrc/upd8.js99
-rw-r--r--src/util/wiki-data.js2
5 files changed, 128 insertions, 95 deletions
diff --git a/src/data/serialize.js b/src/data/serialize.js
new file mode 100644
index 00000000..9d4e8885
--- /dev/null
+++ b/src/data/serialize.js
@@ -0,0 +1,38 @@
+// serialize-util.js: simple interface and utility functions for converting
+// Things into a directly serializeable format
+
+// Utility functions
+
+export function id(x) {
+    return x;
+}
+
+export function toRef(thing) {
+    return thing?.constructor.getReference(thing);
+}
+
+export function toRefs(things) {
+    return things?.map(toRef);
+}
+
+export function toContribRefs(contribs) {
+    return contribs?.map(({ who, what }) => ({who: toRef(who), what}));
+}
+
+// Interface
+
+export const serializeDescriptors = Symbol();
+
+export function serializeThing(thing) {
+    const descriptors = thing.constructor[serializeDescriptors];
+    if (!descriptors) {
+        throw new Error(`Constructor ${thing.constructor.name} does not provide serialize descriptors`);
+    }
+
+    return Object.fromEntries(Object.entries(descriptors)
+        .map(([ property, transform ]) => [property, transform(thing[property])]));
+}
+
+export function serializeThings(things) {
+    return things.map(serializeThing);
+}
diff --git a/src/data/things.js b/src/data/things.js
index 5889b119..2d199c10 100644
--- a/src/data/things.js
+++ b/src/data/things.js
@@ -28,6 +28,8 @@ import {
     validateReferenceList,
 } from './validators.js';
 
+import * as S from './serialize.js';
+
 import {
     getKebabCase,
 } from '../util/wiki-data.js';
@@ -508,6 +510,43 @@ Album.propertyDescriptors = {
     artTags: Thing.common.dynamicThingsFromReferenceList('artTagsByRef', 'artTagData', find.artTag),
 };
 
+Album[S.serializeDescriptors] = {
+    name: S.id,
+    color: S.id,
+    directory: S.id,
+    urls: S.id,
+
+    date: S.id,
+    coverArtDate: S.id,
+    trackArtDate: S.id,
+    dateAddedToWiki: S.id,
+
+    artistContribs: S.toContribRefs,
+    coverArtistContribs: S.toContribRefs,
+    trackCoverArtistContribs: S.toContribRefs,
+    wallpaperArtistContribs: S.toContribRefs,
+    bannerArtistContribs: S.toContribRefs,
+
+    coverArtFileExtension: S.id,
+    trackCoverArtFileExtension: S.id,
+    wallpaperStyle: S.id,
+    wallpaperFileExtension: S.id,
+    bannerStyle: S.id,
+    bannerFileExtension: S.id,
+    bannerDimensions: S.id,
+
+    hasTrackArt: S.id,
+    isMajorRelease: S.id,
+    isListedOnHomepage: S.id,
+
+    commentary: S.id,
+
+    tracks: S.toRefs,
+    groups: S.toRefs,
+    artTags: S.toRefs,
+    commentatorArtists: S.toRefs,
+};
+
 TrackGroup.propertyDescriptors = {
     // Update & expose
 
@@ -781,7 +820,7 @@ Track.prototype[inspect.custom] = function() {
     return (albumName
         ? base + ` (${color.yellow(trackNum)} in ${color.green(albumName)})`
         : base);
-}
+};
 
 // -> Artist
 
@@ -871,6 +910,7 @@ Artist.propertyDescriptors = {
         }
     },
 
+    albumsAsAlbumArtist: Artist.filterByContrib('albumData', 'artistContribs'),
     albumsAsCoverArtist: Artist.filterByContrib('albumData', 'coverArtistContribs'),
     albumsAsWallpaperArtist: Artist.filterByContrib('albumData', 'wallpaperArtistContribs'),
     albumsAsBannerArtist: Artist.filterByContrib('albumData', 'bannerArtistContribs'),
@@ -889,6 +929,31 @@ Artist.propertyDescriptors = {
     flashesAsContributor: Artist.filterByContrib('flashData', 'contributorContribs'),
 };
 
+Artist[S.serializeDescriptors] = {
+    name: S.id,
+    directory: S.id,
+    urls: S.id,
+    contextNotes: S.id,
+
+    hasAvatar: S.id,
+    avatarFileExtension: S.id,
+
+    aliasNames: S.id,
+
+    tracksAsArtist: S.toRefs,
+    tracksAsContributor: S.toRefs,
+    tracksAsCoverArtist: S.toRefs,
+    tracksAsCommentator: S.toRefs,
+
+    albumsAsAlbumArtist: S.toRefs,
+    albumsAsCoverArtist: S.toRefs,
+    albumsAsWallpaperArtist: S.toRefs,
+    albumsAsBannerArtist: S.toRefs,
+    albumsAsCommentator: S.toRefs,
+
+    flashesAsContributor: S.toRefs,
+};
+
 // -> Group
 
 Group.propertyDescriptors = {
@@ -1202,6 +1267,17 @@ Flash.propertyDescriptors = {
     },
 };
 
+Flash[S.serializeDescriptors] = {
+    name: S.id,
+    page: S.id,
+    directory: S.id,
+    date: S.id,
+    contributors: S.toContribRefs,
+    tracks: S.toRefs,
+    urls: S.id,
+    color: S.id,
+};
+
 FlashAct.propertyDescriptors = {
     // Update & expose
 
diff --git a/src/static/client.js b/src/static/client.js
index c12ff355..7397735c 100644
--- a/src/static/client.js
+++ b/src/static/client.js
@@ -9,6 +9,10 @@ import {
     getColors
 } from '../util/colors.js';
 
+import {
+    getArtistNumContributions
+} from '../util/wiki-data.js';
+
 let albumData, artistData, flashData;
 let officialAlbumData, fandomAlbumData, artistNames;
 
@@ -137,7 +141,7 @@ for (const a of document.body.querySelectorAll('[data-random]')) {
             case 'track-in-fandom': return a.href = openTrack(getRefDirectory(pick(fandomAlbumData.reduce((acc, album) => acc.concat(album.tracks), []))));
             case 'track-in-official': return a.href = openTrack(getRefDirectory(pick(officialAlbumData.reduce((acc, album) => acc.concat(album.tracks), []))));
             case 'artist': return a.href = openArtist(pick(artistData).directory);
-            case 'artist-more-than-one-contrib': return a.href = openArtist(pick(artistData.filter(artist => C.getArtistNumContributions(artist) > 1)).directory);
+            case 'artist-more-than-one-contrib': return a.href = openArtist(pick(artistData.filter(artist => getArtistNumContributions(artist) > 1)).directory);
         }
     });
 }
diff --git a/src/upd8.js b/src/upd8.js
index 0d5a3ecb..34e0466e 100755
--- a/src/upd8.js
+++ b/src/upd8.js
@@ -112,6 +112,8 @@ import {
     WikiInfo,
 } from './data/things.js';
 
+import { serializeThings } from './data/serialize.js';
+
 import {
     fancifyFlashURL,
     fancifyURL,
@@ -1273,95 +1275,10 @@ function getDurationInSeconds(string) {
     }
 }
 
-/*
-const stringifyIndent = 0;
-
-const toRefs = (label, objectOrArray) => {
-    if (Array.isArray(objectOrArray)) {
-        return objectOrArray.filter(Boolean).map(x => `${label}:${x.directory}`);
-    } else if (objectOrArray.directory) {
-        throw new Error('toRefs should not be passed a single object with directory');
-    } else if (typeof objectOrArray === 'object') {
-        return Object.fromEntries(Object.entries(objectOrArray)
-            .map(([ key, value ]) => [key, toRefs(key, value)]));
-    } else {
-        throw new Error('toRefs should be passed an array or object of arrays');
-    }
-};
-
-function stringifyRefs(key, value) {
-    switch (key) {
-        case 'tracks':
-        case 'references':
-        case 'referencedBy':
-            return toRefs('track', value);
-        case 'artists':
-        case 'contributors':
-        case 'coverArtists':
-        case 'trackCoverArtists':
-            return value && value.map(({ who, what }) => ({who: `artist:${who.directory}`, what}));
-        case 'albums': return toRefs('album', value);
-        case 'flashes': return toRefs('flash', value);
-        case 'groups': return toRefs('group', value);
-        case 'artTags': return toRefs('tag', value);
-        case 'aka': return value && `track:${value.directory}`;
-        default:
-            return value;
-    }
-}
-
-function stringifyAlbumData({wikiData}) {
-    return JSON.stringify(wikiData.albumData, (key, value) => {
-        switch (key) {
-            case 'commentary':
-                return '';
-            default:
-                return stringifyRefs(key, value);
-        }
-    }, stringifyIndent);
-}
-
-function stringifyTrackData({wikiData}) {
-    return JSON.stringify(wikiData.trackData, (key, value) => {
-        switch (key) {
-            case 'album':
-            case 'commentary':
-            case 'otherReleases':
-                return undefined;
-            default:
-                return stringifyRefs(key, value);
-        }
-    }, stringifyIndent);
-}
-
-function stringifyFlashData({wikiData}) {
-    return JSON.stringify(wikiData.flashData, (key, value) => {
-        switch (key) {
-            case 'act':
-            case 'commentary':
-                return undefined;
-            default:
-                return stringifyRefs(key, value);
-        }
-    }, stringifyIndent);
+function stringifyThings(thingData) {
+    return JSON.stringify(serializeThings(thingData));
 }
 
-function stringifyArtistData({wikiData}) {
-    return JSON.stringify(wikiData.artistData, (key, value) => {
-        switch (key) {
-            case 'asAny':
-                return;
-            case 'asArtist':
-            case 'asContributor':
-            case 'asCoverArtist':
-                return toRefs('track', value);
-            default:
-                return stringifyRefs(key, value);
-        }
-    }, stringifyIndent);
-}
-*/
-
 function img({
     src,
     alt,
@@ -1933,15 +1850,13 @@ function writeSharedFilesAndPages({strings, wikiData}) {
         wikiInfo.enableListings &&
         redirect('Album Commentary', 'list/all-commentary', 'localized.commentaryIndex', ''),
 
-        /*
         writeFile(path.join(outputPath, 'data.json'), fixWS`
             {
-                "albumData": ${stringifyAlbumData({wikiData})},
-                ${wikiInfo.enableFlashesAndGames && `"flashData": ${stringifyFlashData({wikiData})},`}
-                "artistData": ${stringifyArtistData({wikiData})}
+                "albumData": ${stringifyThings(wikiData.albumData)},
+                ${wikiInfo.enableFlashesAndGames && `"flashData": ${stringifyThings(wikiData.flashData)},`}
+                "artistData": ${stringifyThings(wikiData.artistData)}
             }
         `)
-        */
     ].filter(Boolean));
 }
 
diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js
index 870c0b0e..76018313 100644
--- a/src/util/wiki-data.js
+++ b/src/util/wiki-data.js
@@ -2,7 +2,7 @@
 
 import {
     UNRELEASED_TRACKS_DIRECTORY
-} from '../util/magic-constants.js';
+} from './magic-constants.js';
 
 // Generic value operations