Skip to content
← Public packages

@charlesmatte/granola

Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.

src/lib/api.ts

28 lines · 1.8 KB · TypeScript
Raw
import { resolveAccount, type Account } from './account.ts'
import { granolaRequest, type Query } from './client.ts'
import { paginate } from './paginate.ts'
import { authSpec, mutationSpec, pageSpec, parseInput, type Spec } from './validate.ts'

/** Parse input with the shared `account` / `secretName` fields plus export-specific fields. */
export function parseWithAccount<T extends Record<string, unknown>>(raw: unknown, spec: Spec, exportName: string): T & { acct: Account } {
	const params = parseInput<T & { account: string; secretName?: string }>(raw, { ...authSpec, ...spec }, exportName)
	return { ...params, acct: resolveAccount(params) }
}

export { mutationSpec, pageSpec }

type ListOptions = { path: string; itemsKey: string; query?: Query; limit: number; maxPageSize: number; cursor?: string; paginate: boolean }

/** Run a cursor-paginated Granola list endpoint and return `{ items, count, hasMore, cursor, pages, truncated }`. */
export async function listEndpoint<T = Record<string, unknown>>(a: Account, o: ListOptions, wrap: <R>(fn: () => Promise<R>) => Promise<R> = (fn) => fn()) {
	const result = await paginate<T>(
		async (cursor, pageSize) => {
			const res = await wrap(() => granolaRequest<Record<string, unknown>>(a, { path: o.path, query: { ...o.query, cursor, page_size: pageSize } }))
			const data = res.data ?? {}
			const items = Array.isArray(data[o.itemsKey]) ? (data[o.itemsKey] as Array<T>) : []
			return { items, hasMore: Boolean(data.hasMore), cursor: typeof data.cursor === 'string' ? data.cursor : null }
		},
		{ limit: o.limit, maxPageSize: o.maxPageSize, cursor: o.cursor, paginate: o.paginate },
	)
	return { count: result.items.length, items: result.items, hasMore: result.hasMore, cursor: result.cursor, pages: result.pages, truncated: result.truncated }
}