Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/sessionize

src/find-speaker.ts

57 lines · 1.6 KB · TypeScript
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,
	}
}