import { z } from 'zod' // shared export const Identifiable = z.object({ id: z.string().ulid(), }) export type TIdentifiable = z.infer export const Creatable = z.object({ createdAt: z.date(), }) export type TCreatable = z.infer export const Updatable = z.object({ updatedAt: z.date(), }) export type TUpdatable = z.infer // lyrics export const Role = z.enum([ 'admin', // full permissions 'editor', // edit songs, verses, displays, playlists, etc. 'viewer', // cannot change anything, but can view everything ]) export type TRole = z.infer export const Team = Identifiable.merge(Creatable).merge(z.object({ name: z.string(), members: z.record(z.string().ulid(), z.set(Role)), })) export type TTeam = z.infer export const User = Identifiable.merge(Creatable).merge(z.object({ username: z.string(), })) export type TUser = z.infer export const AuthUser = User.merge(z.object({ passwordDigest: z.string(), })) export type TAuthUser = z.infer export function toUser({ passwordDigest: _, ...user }: TAuthUser): TUser { return user } export const Verse = z.object({ content: z.string(), }) export type TVerse = z.infer export const Map = z.object({ verseKeys: z.array(z.string()), }) export type TMap = z.infer export const Song = Identifiable.merge(z.object({ name: z.string(), verses: z.record(z.string(), Verse), maps: z.record(z.string(), Map), })) export type TSong = z.infer export const PlaylistEntry = z.object({ songId: z.string().ulid(), mapKey: z.string(), }) export type TPlaylistEntry = z.infer export const Playlist = Identifiable.merge(z.object({ name: z.string(), entries: z.array(PlaylistEntry), })) export type TPlaylist = z.infer export const Display = Identifiable.merge(z.object({ name: z.string(), playlistId: z.string().ulid(), songIndex: z.number(), })) export type TDisplay = z.infer