57 lines
3.7 KiB
TypeScript
57 lines
3.7 KiB
TypeScript
import { requireCampaignAccess, requireStageTwoUser, stageTwoApiError, stageTwoDatabase, stageTwoUuid } from '~/server/utils/stage-two-supabase'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
try {
|
|
const user = await requireStageTwoUser(event)
|
|
const campaignId = stageTwoUuid(getRouterParam(event, 'id'), 'campaign id')
|
|
const access = await requireCampaignAccess(campaignId, user.id)
|
|
const campaign = access.campaign
|
|
const worldId = String(campaign.world_id)
|
|
const [worlds, members, characters, openRounds, rounds] = await Promise.all([
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`worlds?select=id,title,genre,tone,premise,content_boundaries,hook,opening_scene&id=eq.${worldId}&limit=1`,
|
|
),
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`campaign_members?select=id,user_id,role,active,ai_takeover_allowed,joined_at&campaign_id=eq.${campaignId}&order=joined_at.asc`,
|
|
),
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`characters?select=id,campaign_id,user_id,name,concept,controller,abilities,hp,max_hp,defense,proficiency,inventory,statuses,persona,created_at&campaign_id=eq.${campaignId}&order=created_at.asc`,
|
|
),
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`rounds?select=id,campaign_id,number,status,forced_by,narration,next_prompt,queued_at,resolved_at,error,created_at&campaign_id=eq.${campaignId}&status=eq.open&order=number.desc&limit=1`,
|
|
),
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`rounds?select=id,campaign_id,number,status,forced_by,narration,next_prompt,queued_at,resolved_at,error,created_at&campaign_id=eq.${campaignId}&order=number.desc&limit=30`,
|
|
),
|
|
])
|
|
const fallbackRounds = openRounds.length ? [] : await stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`rounds?select=id,campaign_id,number,status,forced_by,narration,next_prompt,queued_at,resolved_at,error,created_at&campaign_id=eq.${campaignId}&order=number.desc&limit=1`,
|
|
)
|
|
const round = openRounds[0] ?? fallbackRounds[0] ?? null
|
|
const userIds = [...new Set(members.map(member => String(member.user_id)))]
|
|
const profiles = userIds.length
|
|
? await stageTwoDatabase<Array<{ id: string; display_name: string }>>(
|
|
`profiles?select=id,display_name&id=in.(${userIds.join(',')})`,
|
|
)
|
|
: []
|
|
const profileById = new Map(profiles.map(profile => [profile.id, profile]))
|
|
const visibleMembers = members.map(member => ({ ...member, profile: profileById.get(String(member.user_id)) ?? null }))
|
|
const visibleRounds = rounds.slice().reverse()
|
|
const visibleRoundIds = visibleRounds.map(item => String(item.id))
|
|
const [intents, events, diceRolls] = await Promise.all([
|
|
round ? stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`player_intents?select=id,round_id,member_id,character_id,action,ready,created_at,updated_at&round_id=eq.${String(round.id)}&order=created_at.asc`,
|
|
) : Promise.resolve([]),
|
|
stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`game_events?select=id,campaign_id,round_id,event_type,payload,created_at&campaign_id=eq.${campaignId}&order=created_at.desc&limit=50`,
|
|
),
|
|
visibleRoundIds.length ? stageTwoDatabase<Array<Record<string, unknown>>>(
|
|
`dice_rolls?select=id,round_id,actor_id,target_id,check_kind,formula,rolls,kept,modifier,total,difficulty,success,created_at&round_id=in.(${visibleRoundIds.join(',')})&order=created_at.asc`,
|
|
) : Promise.resolve([]),
|
|
])
|
|
return { campaign, world: worlds[0] ?? null, members: visibleMembers, characters, round, rounds: visibleRounds, intents, events: events.slice().reverse(), diceRolls }
|
|
} catch (error) {
|
|
stageTwoApiError(error)
|
|
}
|
|
})
|