Skip to content

feat: add Airtable integration - database operations#69

Open
jackulau wants to merge 1 commit into
wespreadjam:mainfrom
jackulau:29
Open

feat: add Airtable integration - database operations#69
jackulau wants to merge 1 commit into
wespreadjam:mainfrom
jackulau:29

Conversation

@jackulau

@jackulau jackulau commented Apr 9, 2026

Copy link
Copy Markdown

Summary

Adds Airtable integration for database operations per Issue #29 (P1 priority). Implements a bearer token credential and 4 CRUD operation nodes following the
existing Slack/DevTo integration patterns.

Credential

  • Uses defineBearerCredential from @jam-nodes/core
  • Name: airtable, type: bearer
  • Authentication via Authorization: Bearer {{accessToken}} header
  • Added airtable?: { accessToken: string } to NodeCredentials interface in core

Operations

airtableCreateRecord

  • Input: { baseId, tableId, fields }
  • API: POST https://api.airtable.com/v0/{baseId}/{tableId}
  • Body: { fields: {...} }
  • Output: { id, fields, createdTime }

airtableGetRecords

  • Input: { baseId, tableId, filterByFormula?, sort?, maxRecords? }
  • API: GET https://api.airtable.com/v0/{baseId}/{tableId} with query params
  • Features:
    • filterByFormula — URL-encoded, supports special characters (e.g. AND({Name}="O'Brien", {Age}>30))
    • sort — Airtable bracket notation (sort[0][field]=Name&sort[0][direction]=asc), supports multiple sort fields
    • maxRecords — integer limit
    • Pagination — returns offset token from Airtable response for subsequent requests
  • Output: { records: [{ id, fields, createdTime }], offset? }

airtableUpdateRecord

  • Input: { baseId, tableId, recordId, fields }
  • API: PATCH https://api.airtable.com/v0/{baseId}/{tableId}/{recordId}
  • Body: { fields: {...} } (partial update — only specified fields are changed)
  • Output: { id, fields, createdTime }

airtableDeleteRecord

  • Input: { baseId, tableId, recordId }
  • API: DELETE https://api.airtable.com/v0/{baseId}/{tableId}/{recordId}
  • Output: { id, deleted }

Architecture

  • Each operation is a separate file following the Slack pattern (slack-send-message.ts, etc.)
  • All nodes use defineNode from @jam-nodes/core with category integration
  • HTTP calls use the shared fetchWithRetry utility which handles rate limiting (429), retries with exponential backoff, and timeouts
  • Credentials flow through context.credentials.airtable.accessToken matching the NodeCredentials pattern
  • tableId is URL-encoded via encodeURIComponent to handle table names with spaces
  • Zod schemas for all inputs/outputs with inferred TypeScript types
  • All error paths return { success: false, error } — no thrown exceptions

Files Changed

New files (8)

  • packages/nodes/src/integrations/airtable/credentials.ts — bearer credential definition
  • packages/nodes/src/integrations/airtable/schemas.ts — Zod input/output schemas + inferred types
  • packages/nodes/src/integrations/airtable/airtable-create-record.ts — create operation
  • packages/nodes/src/integrations/airtable/airtable-get-records.ts — get/list operation with filtering, sorting, pagination
  • packages/nodes/src/integrations/airtable/airtable-update-record.ts — update operation (PATCH)
  • packages/nodes/src/integrations/airtable/airtable-delete-record.ts — delete operation
  • packages/nodes/src/integrations/airtable/index.ts — barrel exports
  • packages/nodes/src/integrations/airtable/__tests__/airtable.test.ts — 36 unit tests

Modified files (3)

  • packages/core/src/types/node.ts — added airtable to NodeCredentials interface
  • packages/nodes/src/integrations/index.ts — added airtable exports
  • packages/nodes/src/index.ts — added airtable exports + registered 4 nodes in builtInNodes

Test Plan

36 tests covering:

  • Credential metadata (2): verifies name, type, and authenticate config
  • Schema validation (7): accepts valid inputs, rejects missing required fields for all operations
  • airtableCreateRecord (7): missing credentials, success response, auth header, request body, API errors (404, 422), empty fields
  • airtableGetRecords (10): missing credentials, multi-record response, filterByFormula encoding, single sort, multi-sort bracket notation, maxRecords,
    special character formula encoding, pagination offset, empty table, API error
  • airtableUpdateRecord (5): missing credentials, success with updated fields, PATCH method + URL verification, partial update body, API error
  • airtableDeleteRecord (4): missing credentials, success confirmation, DELETE method + URL verification, API error
  • Full CRUD integration flow (1): create → get → update → delete sequence with mocked responses

Results: 36/36 passing, 0 regressions (231 total suite, baseline 195)

Add Airtable database integration (Issue wespreadjam#29) with bearer token
credential and 4 nodes: createRecord, getRecords, updateRecord,
deleteRecord. Includes formula filtering, multi-sort, pagination
offset support, and 36 unit tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant