airtypes
v0.1.0
Published
Generate Zod schemas and TypeScript types from Airtable bases.
Readme
airtypes
Generate Zod schemas and TypeScript types from Airtable bases. Built for terminals, CI, and codegen workflows.
Features
- Zod schemas and TypeScript types per table
*Tabledefinitions with Airtable field mappings- Optional
recordSchema+parseRecordhelper requiredFieldssupport for stricter list queries- Config discovery + CLI flags
Requirements
- Node.js >= 24
Install
pnpm add -D airtypesUsage
# Generate with config discovery
npx airtypes generate
# Explicit config path
npx airtypes generate --config ./config.toml
# Override output path
npx airtypes generate --out ./types/airtable-types.ts
# Validate config only
npx airtypes validate
# Print effective config (secrets redacted)
npx airtypes print-config --jsonConfiguration
Discovery
airtypes uses cosmiconfig. It searches (in order) from the current working directory for:
package.json(underairtypeskey).airtypesrc,.airtypesrc.json,.airtypesrc.yaml,.airtypesrc.yml,.airtypesrc.js,.airtypesrc.cjsairtypes.config.js,airtypes.config.cjs,airtypes.config.mjs,airtypes.config.json,airtypes.config.yaml,airtypes.config.yml,airtypes.config.tomlconfig.toml
You can also force a config path:
npx airtypes generate --config ./config.tomlExample config.toml
api_key_env = "AIRTABLE_API_KEY"
output = "airtable-types.ts"
[[bases]]
name = "my-base"
base_id = "app1234"
# table_ids = ["tbl123", "tbl456"]
# view_ids = ["viw123", "viw456"]
# required_fields = { "My Table" = ["Primary Field", "Status"] }API key
Provide an API key via one of:
api_keyin configapi_key_envin config (recommended)AIRTABLE_API_KEYenv var
Output
The generated file exports:
*SchemaZod objects per tabletypealiases viaz.infer*Tabledefinitions (mappings + schema)- optional
recordSchemaandparseRecord linksmetadata for linked record fields
Example table snippet:
export const myTableTable = {
name: 'My Table',
baseId: 'app...',
tableId: 'tbl...',
mappings: { relatedItems: 'fld...' },
requiredFields: ['name', 'status'],
schema: MyTableSchema,
recordSchema: MyTableRecordSchema,
links: {
relatedItems: { tableId: 'tblLinked' },
},
} satisfies AirtableTableDefinition<MyTable>;Use parseRecord to validate Airtable API records once and get typed fields:
import { parseRecord, myTableTable } from './airtable-types.js';
const parsed = parseRecord(myTableTable, { id: record.id, fields: record.fields });
const fields = parsed.fields; // fully typedUsing with airtool
airtool consumes the generated table definitions directly:
import { createAirtableClient, pickFields } from 'airtool';
import { myTableTable } from './airtable-types.js';
const client = createAirtableClient({
apiKey: process.env.AIRTABLE_API_KEY!,
baseId: myTableTable.baseId!,
});
const table = client.table(myTableTable);
const records = await table.fetchAllRecords({
fields: pickFields(myTableTable, 'primaryField', 'status'),
});If you set required_fields in the config, airtypes adds a requiredFields list per table, and airtool automatically
includes those fields in typed list queries.
Flags
-c, --config <path>config file path--config-file <path>alias for--config-o, --out <path>override output path--no-linksskip linked-record metadata--no-record-schemaskip recordSchema helpers-n, --dry-runrender output without writing--jsonmachine output--plaincompact JSON-q, --quietsuppress non-error output-v, --verboseverbose output--no-colordisable color
Exit codes
0success1runtime or API error2CLI usage error
License
MIT
