import { assertEndpointId, fetchSessionizeView } from './client.ts'
import { flattenSessionGroups, matchSession } from './project.ts'
import type {
EndpointInput,
SessionizeListedSession,
SessionizeSessionGroup,
SlimSession,
} from './types.ts'
export type FindSessionInput = EndpointInput & {
/** Session id, exact title, or a case-insensitive title/speaker fragment. */
query: string
}
export type FoundSession = SlimSession & {
description: string | null
}
/**
* Find one Sessionize session by id, title, or speaker name.
*
* @example
* import findSession from 'kody:@kody/sessionize/find-session'
* const result = await findSession({ endpointId: 'jl4ktls0', query: 'Aiden' })
* // => { matchCount: 1, session: { title: "Aiden's Keynote", description: '...' } }
*/
export default async function findSession(input: FindSessionInput): Promise<{
endpointId: string
query: string
matchCount: number
session: FoundSession | null
matches: Array<SlimSession>
}> {
const endpointId = assertEndpointId(input.endpointId)
const query = input.query.trim()
if (!query) {
throw new Error('findSession requires a non-empty query.')
}
const groups = await fetchSessionizeView<Array<SessionizeSessionGroup>>({
endpointId,
view: 'Sessions',
})
const listedById = new Map<string, SessionizeListedSession>()
for (const group of groups) {
for (const session of group.sessions) {
listedById.set(String(session.id), session)
}
}
const items = flattenSessionGroups(groups)
const matches = items.filter((session) => matchSession(session, query))
const top = matches[0] ?? null
const listed = top ? listedById.get(top.id) : null
return {
endpointId,
query,
matchCount: matches.length,
session: top
? { ...top, description: listed?.description ?? null }
: null,
matches,
}
}