import { assertEndpointId, fetchSessionizeView } from './client.ts'
import { matchSpeaker, slimSpeakerFromListed } from './project.ts'
import type {
EndpointInput,
SessionizeListedSpeaker,
SlimSpeaker,
} from './types.ts'
export type FindSpeakerInput = EndpointInput & {
/** Speaker id, name, tag line, or a session title fragment. */
query: string
}
export type FoundSpeaker = SlimSpeaker & {
bio: string | null
}
/**
* Find one Sessionize speaker by id, name, tag line, or session title.
*
* @example
* import findSpeaker from 'kody:@kody/sessionize/find-speaker'
* const result = await findSpeaker({ endpointId: 'jl4ktls0', query: 'Sophia' })
* // => { matchCount: 1, speaker: { fullName: 'Sophia Test', bio: '...' } }
*/
export default async function findSpeaker(input: FindSpeakerInput): Promise<{
endpointId: string
query: string
matchCount: number
speaker: FoundSpeaker | null
matches: Array<SlimSpeaker>
}> {
const endpointId = assertEndpointId(input.endpointId)
const query = input.query.trim()
if (!query) {
throw new Error('findSpeaker requires a non-empty query.')
}
const speakers = await fetchSessionizeView<Array<SessionizeListedSpeaker>>({
endpointId,
view: 'Speakers',
})
const items = speakers.map((speaker) => slimSpeakerFromListed(speaker))
const matches = items.filter((speaker) => matchSpeaker(speaker, query))
const top = matches[0] ?? null
const listed = top
? speakers.find((speaker) => String(speaker.id) === top.id)
: null
return {
endpointId,
query,
matchCount: matches.length,
speaker: top ? { ...top, bio: listed?.bio ?? null } : null,
matches,
}
}