Skip to content

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

Package listing

@kody/airtable

src/list-records.ts

110 lines · 3.2 KB · TypeScript
import { pickAuthInput } from './auth.ts'
import { airtableRequest } from './client.ts'
import { mapRecord } from './models.ts'
import { recordsPath } from './setup.ts'
import type {
	AirtableAuthInput,
	AirtablePageInfo,
	AirtableRecordSummary,
	JsonRecord,
} from './types.ts'
import {
	clampInt,
	compactRecord,
	optionalBoolean,
	optionalString,
	optionalStringArray,
	requireRecord,
	requireString,
} from './types.ts'

export type ListRecordsInput = AirtableAuthInput & {
	baseId: string
	/** Table id (`tbl…`) or table name. */
	tableIdOrName: string
	fields?: Array<string>
	filterByFormula?: string
	view?: string
	maxRecords?: number
	pageSize?: number
	offset?: string
	returnFieldsByFieldId?: boolean
}

export type ListRecordsResult = {
	items: Array<AirtableRecordSummary>
	pageInfo: AirtablePageInfo
}

/**
 * List records in an Airtable table. Needs `data.records:read`.
 * @example
 * import listRecords from 'kody:@kody/airtable/list-records'
 * const { items } = await listRecords({
 *   baseId: 'appXXXXXXXXXXXXXX',
 *   tableIdOrName: 'tblXXXXXXXXXXXXXX',
 *   pageSize: 25,
 * })
 */
export async function listRecords(input: ListRecordsInput): Promise<ListRecordsResult> {
	const baseId = requireString(input.baseId, 'baseId')
	const tableIdOrName = requireString(input.tableIdOrName, 'tableIdOrName')
	const pageSize = clampInt(input.pageSize, 1, 100, 25, 'pageSize')
	const maxRecords =
		input.maxRecords === undefined
			? undefined
			: clampInt(input.maxRecords, 1, 1000, 100, 'maxRecords')
	const query = compactRecord({
		pageSize,
		maxRecords,
		offset: optionalString(input.offset, 'offset'),
		view: optionalString(input.view, 'view'),
		filterByFormula: optionalString(input.filterByFormula, 'filterByFormula'),
		returnFieldsByFieldId: optionalBoolean(
			input.returnFieldsByFieldId,
			'returnFieldsByFieldId',
		),
		'fields[]': optionalStringArray(input.fields, 'fields'),
	}) as JsonRecord
	const result = await airtableRequest<{ records?: Array<unknown> }>({
		...input,
		operation: 'records.read',
		path: recordsPath(baseId, tableIdOrName),
		query,
	})
	const body = result.data && typeof result.data === 'object' ? result.data : {}
	return {
		items: (Array.isArray(body.records) ? body.records : []).map(mapRecord),
		pageInfo: result.pageInfo,
	}
}

/**
 * List records in an Airtable table.
 * @example
 * import listRecords from 'kody:@kody/airtable/list-records'
 * const result = await listRecords({
 *   baseId: 'appXXXXXXXXXXXXXX',
 *   tableIdOrName: 'Tasks',
 * })
 */
export default async function listRecordsEntrypoint(
	params: Partial<ListRecordsInput> & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'list-records')
	return listRecords({
		baseId: requireString(input.baseId, 'baseId'),
		tableIdOrName: requireString(input.tableIdOrName, 'tableIdOrName'),
		fields: optionalStringArray(input.fields, 'fields'),
		filterByFormula: optionalString(input.filterByFormula, 'filterByFormula'),
		view: optionalString(input.view, 'view'),
		maxRecords: input.maxRecords as number | undefined,
		pageSize: input.pageSize as number | undefined,
		offset: optionalString(input.offset, 'offset'),
		returnFieldsByFieldId: optionalBoolean(
			input.returnFieldsByFieldId,
			'returnFieldsByFieldId',
		),
		...pickAuthInput(input),
	})
}