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>(raw: unknown, spec: Spec, exportName: string): T & { acct: Account } { const params = parseInput(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>(a: Account, o: ListOptions, wrap: (fn: () => Promise) => Promise = (fn) => fn()) { const result = await paginate( async (cursor, pageSize) => { const res = await wrap(() => granolaRequest>(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) : [] 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 } }