jevstrudel.git / website / src / jev / pitches.mjs

Pitches (song ideas for Jev songs, worker/src/content.ts) and the songs that answer them. The maker of a song says which pitch it answers: a site song in its SPEC.md (pitch: <id>, read at build time by songs.mjs), a listener's song by its author (setSongPitch, in listeners.mjs). A pitch's author cannot mark it answered: only the song's maker can vouch for that.

8const PITCH_ID = /^[A-Za-z0-9_-]{22}$/;

A spec's pitch:, a pitch's id, or null; a malformed one fails the build (songs.mjs) rather than silently never matching.

12export function pitchOf(value, where = 'a song') {
13  if (value === undefined || value === null) return null;
14  if (typeof value === 'string' && PITCH_ID.test(value)) return value;
15  throw new Error(`${where}: pitch must be a pitch's id (22 characters), not ${JSON.stringify(value)}`);
16}

Every song answering pitch: the site's (from this build) and the listeners' the Worker listed with it, site songs first.

20export function answersOf(pitch, siteSongs) {
21  return [
22    ...siteSongs.filter((s) => s.pitch === pitch.id).map((s) => ({ site: s.id, title: s.title })),
23    ...(pitch.answers ?? []).map((a) => ({ listener: a.id, title: a.title })),
24  ];
25}

How the pitches list may be sorted, and what each is called.

28export const PITCH_SORTS = { votes: 'most voted', new: 'newest' };