81 lines
2 KiB
TypeScript
81 lines
2 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
// shared
|
|
export const Identifiable = z.object({
|
|
id: z.string().ulid(),
|
|
})
|
|
export type TIdentifiable = z.infer<typeof Identifiable>
|
|
|
|
export const Creatable = z.object({
|
|
createdAt: z.date(),
|
|
})
|
|
export type TCreatable = z.infer<typeof Creatable>
|
|
|
|
export const Updatable = z.object({
|
|
updatedAt: z.date(),
|
|
})
|
|
export type TUpdatable = z.infer<typeof Updatable>
|
|
|
|
// 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<typeof Role>
|
|
|
|
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<typeof Team>
|
|
|
|
export const User = Identifiable.merge(Creatable).merge(z.object({
|
|
username: z.string(),
|
|
}))
|
|
export type TUser = z.infer<typeof User>
|
|
|
|
export const AuthUser = User.merge(z.object({
|
|
passwordDigest: z.string(),
|
|
}))
|
|
export type TAuthUser = z.infer<typeof AuthUser>
|
|
|
|
export function toUser({ passwordDigest: _, ...user }: TAuthUser): TUser {
|
|
return user
|
|
}
|
|
|
|
export const Verse = z.object({
|
|
content: z.string(),
|
|
})
|
|
export type TVerse = z.infer<typeof Verse>
|
|
|
|
export const Map = z.object({
|
|
verseKeys: z.array(z.string()),
|
|
})
|
|
export type TMap = z.infer<typeof Map>
|
|
|
|
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<typeof Song>
|
|
|
|
export const PlaylistEntry = z.object({
|
|
songId: z.string().ulid(),
|
|
mapKey: z.string(),
|
|
})
|
|
export type TPlaylistEntry = z.infer<typeof PlaylistEntry>
|
|
|
|
export const Playlist = Identifiable.merge(z.object({
|
|
name: z.string(),
|
|
entries: z.array(PlaylistEntry),
|
|
}))
|
|
export type TPlaylist = z.infer<typeof Playlist>
|
|
|
|
export const Display = Identifiable.merge(z.object({
|
|
name: z.string(),
|
|
playlistId: z.string().ulid(),
|
|
songIndex: z.number(),
|
|
}))
|
|
export type TDisplay = z.infer<typeof Display>
|