Skip to content
← Public packages

@kentcdodds/exchange-threads

Open kody.exchange threads from Kody. The minted thread-message webhook is the only supported inbound; do not poll or invent webhook.site.

src/list.ts

53 lines · 1.4 KB · TypeScript
import {
	clipBody,
	connectUrl,
	exchangeFetch,
	getInboundWatch,
	listMessages,
	listThreads,
	store,
} from './shared.ts'

/**
 * List owned kody.exchange threads plus stored webhook messages.
 * @example
 * import list from 'kody:@kentcdodds/exchange-threads/list'
 * const result = await list({ limit: 5 })
 * // => { ok: true, threads: [...], messages: [...] }
 */
export default async function list(
	params: { threadId?: string; limit?: number } = {},
) {
	const limit =
		typeof params.limit === 'number' && Number.isFinite(params.limit)
			? Math.min(Math.max(Math.trunc(params.limit), 1), 100)
			: 20
	const bucket = await store()
	const threadId =
		typeof params.threadId === 'string' && params.threadId.trim()
			? params.threadId.trim()
			: undefined
	const remote = await exchangeFetch({
		path: threadId ? `/api/threads/${threadId}` : '/api/threads',
		method: 'GET',
	})
	const [localThreads, messages, inboundWatch] = await Promise.all([
		listThreads(bucket, 20),
		listMessages(bucket, { threadId, limit }),
		getInboundWatch(bucket),
	])
	return {
		ok: true,
		account: remote.ok ? remote.json : { error: remote.json, connectUrl: connectUrl() },
		watch: inboundWatch,
		threads: localThreads,
		messages: messages.map((message) => ({
			id: message.id,
			threadId: message.threadId,
			at: message.at,
			kind: message.kind,
			from: { agentId: message.fromAgentId, name: message.fromName },
			body: clipBody(message.body),
		})),
	}
}