Build API v2
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
// Canonical solfeggio id <- Hz, mirroring the kiosk's `frequencyIdForHz()`
|
||||
// map (radiantwave-rebuild src/audio/audio_downloader.cpp). v2 must emit these
|
||||
// canonical ids (1-9), never the portal DB autoincrement ids, because
|
||||
// proclamations and color palettes on the kiosk are keyed by them.
|
||||
export const CANONICAL_ID_FOR_HZ: Record<number, number> = {
|
||||
174: 1,
|
||||
285: 1,
|
||||
396: 2,
|
||||
417: 3,
|
||||
432: 4,
|
||||
528: 5,
|
||||
639: 6,
|
||||
741: 7,
|
||||
852: 8,
|
||||
963: 9
|
||||
};
|
||||
|
||||
// The 9 canonical frequencies exactly as the kiosk expects from
|
||||
// GET /frequencies (id 1-9, non-zero, `value` recognized by frequencyIdForHz).
|
||||
export const CANONICAL_FREQUENCIES: { id: number; name: string; value: number }[] = [
|
||||
{ id: 1, name: 'Grounding / Relief', value: 174 },
|
||||
{ id: 2, name: 'Root', value: 396 },
|
||||
{ id: 3, name: 'Sacral', value: 417 },
|
||||
{ id: 4, name: 'Clarity / Wellbeing', value: 432 },
|
||||
{ id: 5, name: 'Solar Plexus', value: 528 },
|
||||
{ id: 6, name: 'Heart', value: 639 },
|
||||
{ id: 7, name: 'Throat', value: 741 },
|
||||
{ id: 8, name: '3rd Eye', value: 852 },
|
||||
{ id: 9, name: 'Crown', value: 963 }
|
||||
];
|
||||
|
||||
// Seed palettes per canonical id, matching the kiosk's
|
||||
// DatabaseManager::seedColorPalettes(). Used to backfill /color-palettes
|
||||
// when the DB has not been seeded for an id yet.
|
||||
export const CANONICAL_PALETTES: Record<number, string[]> = {
|
||||
1: ['#8B6914', '#B8860B', '#DAA520', '#E8B64C', '#FFD700', '#FFE9A8', '#FFF4CC'],
|
||||
2: ['#8B0000', '#B22222', '#DC143C', '#FF6347', '#FF8C69', '#FFA500', '#FFDAB9'],
|
||||
3: ['#FF4500', '#FF7F50', '#FF8C00', '#FFA500', '#FFC87F', '#FFDFBA', '#FFEBCD'],
|
||||
4: ['#8B2252', '#CD3278', '#DB7093', '#FF69B4', '#FFB6C1', '#FFC0CB', '#FFE4E1'],
|
||||
5: ['#32CD32', '#3CB371', '#90EE90', '#98FB98', '#ADFFA9', '#C8FFD2', '#F0FFF0'],
|
||||
6: ['#00FF7F', '#00CED1', '#40E0D0', '#5F9EA0', '#7FFFD4', '#AFEEEE', '#E0FFFF'],
|
||||
7: ['#00BFFF', '#1E90FF', '#4169E1', '#6495ED', '#87CEEB', '#ADD8E6', '#F0F8FF'],
|
||||
8: ['#4B0082', '#9370DB', '#8A2BE2', '#7B68EE', '#DA70D6', '#D8BFD8', '#E6E6FA'],
|
||||
9: ['#9400D3', '#BA55D3', '#C71585', '#DDA0DD', '#EE82EE', '#FFF0F5', '#FAF0FA']
|
||||
};
|
||||
|
||||
/** Map a SolfeggioFrequency row to its canonical id, or null if it has no
|
||||
* canonical id (e.g. 936 Hz). */
|
||||
export function canonicalIdForFrequency(freq: { value: number }): number | null {
|
||||
return CANONICAL_ID_FOR_HZ[freq.value] ?? null;
|
||||
}
|
||||
|
||||
export type V2Proclamation = {
|
||||
id: string;
|
||||
name: string;
|
||||
content: string;
|
||||
categoryId: number;
|
||||
solfeggioFrequencyId: number;
|
||||
subscriptionLevelId: number | null;
|
||||
colorPalette?: string[];
|
||||
};
|
||||
|
||||
export type ProclamationWithFrequency = {
|
||||
id: string;
|
||||
name: string;
|
||||
content: string;
|
||||
categoryId: number;
|
||||
subscriptionLevelId: number | null;
|
||||
solfeggioFrequency: { value: number };
|
||||
};
|
||||
|
||||
/** Serialize a DB proclamation row to the v2 wire format. Returns null when
|
||||
* the proclamation's frequency has no canonical id (dropped from v2). */
|
||||
export function serializeProclamation(
|
||||
p: ProclamationWithFrequency,
|
||||
palette?: string[]
|
||||
): V2Proclamation | null {
|
||||
const solfeggioFrequencyId = CANONICAL_ID_FOR_HZ[p.solfeggioFrequency.value];
|
||||
if (!solfeggioFrequencyId) return null;
|
||||
|
||||
const record: V2Proclamation = {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
content: p.content,
|
||||
categoryId: p.categoryId,
|
||||
solfeggioFrequencyId,
|
||||
subscriptionLevelId: p.subscriptionLevelId
|
||||
};
|
||||
|
||||
if (palette && palette.length > 0) {
|
||||
record.colorPalette = palette;
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
export type V2Category = {
|
||||
id: number;
|
||||
name: string;
|
||||
sortOrder: number;
|
||||
parentId: number | null;
|
||||
};
|
||||
|
||||
export function serializeCategory(c: {
|
||||
id: number;
|
||||
name: string;
|
||||
sortOrder: number;
|
||||
parentId: number | null;
|
||||
}): V2Category {
|
||||
return { id: c.id, name: c.name, sortOrder: c.sortOrder, parentId: c.parentId };
|
||||
}
|
||||
|
||||
export type V2SubscriptionLevel = {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string | null;
|
||||
};
|
||||
|
||||
export function serializeSubscriptionLevel(level: {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string | null;
|
||||
}): V2SubscriptionLevel {
|
||||
return { id: level.id, name: level.name, description: level.description };
|
||||
}
|
||||
|
||||
export type V2License = {
|
||||
key: string;
|
||||
email_address: string;
|
||||
subscription_level: { id: number | null; name: string; description: string | null };
|
||||
};
|
||||
|
||||
/** Build the POST /license response. `subscription_level` is always an object;
|
||||
* when no SubscriptionLevel row matches the license's level name, fall back to
|
||||
* a structurally consistent object with a null id/description. */
|
||||
export function serializeLicense(opts: {
|
||||
key: string;
|
||||
emailAddress: string;
|
||||
levelName: string;
|
||||
level: { id: number; name: string; description: string | null } | null;
|
||||
}): V2License {
|
||||
return {
|
||||
key: opts.key,
|
||||
email_address: opts.emailAddress,
|
||||
subscription_level: opts.level
|
||||
? { id: opts.level.id, name: opts.level.name, description: opts.level.description }
|
||||
: { id: null, name: opts.levelName, description: null }
|
||||
};
|
||||
}
|
||||
|
||||
export type V2ColorPalette = {
|
||||
solfeggioFrequencyId: number;
|
||||
colors: string[];
|
||||
};
|
||||
|
||||
export function serializeColorPalette(palette: {
|
||||
solfeggioFrequencyId: number;
|
||||
colors: string[];
|
||||
}): V2ColorPalette {
|
||||
return { solfeggioFrequencyId: palette.solfeggioFrequencyId, colors: palette.colors };
|
||||
}
|
||||
Reference in New Issue
Block a user