https://github.com/nadhifikbarw/airtable-ofetch
JS Client for Airtable Web API built on top @unjs/ofetch Fetch API
https://github.com/nadhifikbarw/airtable-ofetch
airtable ofetch typescript
Last synced: 14 days ago
JSON representation
JS Client for Airtable Web API built on top @unjs/ofetch Fetch API
- Host: GitHub
- URL: https://github.com/nadhifikbarw/airtable-ofetch
- Owner: nadhifikbarw
- License: mit
- Created: 2024-12-13T14:52:21.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2026-05-15T17:55:54.000Z (15 days ago)
- Last Synced: 2026-05-15T20:25:11.481Z (15 days ago)
- Topics: airtable, ofetch, typescript
- Language: TypeScript
- Homepage:
- Size: 398 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# airtable-ofetch
[](https://www.npmjs.com/package/airtable-ofetch)
[](https://codecov.io/gh/nadhifikbarw/airtable-ofetch)
[](https://opensource.org/licenses/MIT)
[](https://www.jsdocs.io/package/airtable-ofetch)
Modern JS client for [Airtable Web API](https://airtable.com/developers/web/api/introduction)
* [airtable-ofetch](#airtable-ofetch)
* [🚀 Quick Start](#-quick-start)
* [✔️ Works on node, browser, and workers](#-works-on-node-browser-and-workers)
* [🔧 Configuration](#-configuration)
* [🔁 Pagination](#-pagination)
* [📘 Type Friendly](#-type-friendly)
* [📦 Bundler Notes](#-bundler-notes)
* [💻 Development](#-development)
* [License](#license)
## 🚀 Quick Start
Install:
```bash
pnpm install airtable-ofetch
```
Import:
```js
// CommonJS
const { Airtable } = require('airtable-ofetch');
// ESM / TypeScript
import { Airtable } from 'airtable-ofetch';
const airtable = new Airtable(); // Will read process.env.AIRTABLE_API_KEY
```
## ✔️ Works on node, browser, and workers
This client is implemented on top of [unjs/ofetch](https://github.com/unjs/ofetch) to provide better cross-runtime compatibility.
## 🔧 Configuration
You can provide custom configuration during client initialization:
```js
const airtable = new Airtable({
/**
* As of February 1st 2024, Airtable Web API has ended deprecation period
* of Airtable API Key and has prompted all users to migrate to use personal
* access token (PAT) or OAuth access token
*
* @see https://airtable.com/developers/web/api/authentication
*/
apiKey: 'YOUR_PERSONAL_ACCESS_TOKEN', // Otherwise default to process.env.AIRTABLE_API_KEY
/**
* API Endpoint URL target, users may override this if they need
* to pass requests through an API proxy. Don't include trailing slash
* for consistency.
*
* @optional
*/
endpointURL: 'https://api.airtable.internal', // Also configurable via AIRTABLE_ENDPOINT_URL
/**
* Content Endpoint URL target, users may override this if they need
* to pass requests through an API proxy. Don't include trailing slash
* for consistency.
*
* @see https://airtable.com/developers/web/api/upload-attachment
* @optional
*/
contentEndpointURL: 'https://content.airtable.internal', // Also configurable via AIRTABLE_CONTENT_ENDPOINT_URL
/**
* How long in ms before aborting a request attempt.
* Default to 5 minutes.
*
* @optional
*/
requestTimeout: 180 * 1000,
/**
* Disable / configure exponential backoff with jitter retry
* whenever API request receive 429 status code response
*
* @see https://airtable.com/developers/web/api/rate-limits
* @optional
*/
noRetryIfRateLimited: true, // This disable retry
/**
* Disable automatic reset when server response with Iteration Timeout error
* when calling `.all()` on List Records query
*
* @see {@link https://airtable.com/developers/web/api/list-records#:~:text=LIST_RECORDS_ITERATOR_NOT_AVAILABLE}
* @optional
*/
noIterationReset: true, // Throws when iteration timeout
/**
* Custom headers to be included when requesting to API endpoint
*
* @optional
*/
customHeaders: {
'X-Custom-Header': 'Custom Value',
}
})
```
You can customize maximum retries and its backoff behavior:
```js
const airtable = new Airtable({
noRetryIfRateLimited: {
maxRetries: 5, // Maximum retry attempts. Default to Infinity
initialDelayMs: 500, // Initial retry delay in ms. Default to 1000ms
maxDelayMs: 2000, // Maximum retry delay in ms. Default to 45_000ms
},
})
```
You can create a new client that inherit previous configuration and replace some of it:
```js
const airtable = new Airtable({ apiKey: 'custom-api-key' });
// New client will inherit manually passed apiKey
const newAirtable = airtable.create({ customHeaders: { 'X-Custom-Header': 'Custom Value' } });
```
## 🔁 Pagination
This client implement similar pagination control as [airtable.js](https://github.com/Airtable/airtable.js) using `eachPage()` that you can control whenever possible:
```typescript
const table = new Airtable().base('appEpvhkjHcG8OvKu').table('tblc7ieWKVQM9eequ');
// List records endpoint exposes pagination
// https://airtable.com/developers/web/api/list-records
const query = table.list({ pageSize: 50 });
// Async callback is supported
await query.eachPage(async (records: AirtableRecord[]) => {
// Do something with records
console.log(records);
// Return false to stop pagination early, otherwise pagination will continue until all records are exhausted
return false;
});
```
> [!NOTE]
> `eachPage()` API need you to handle [Iteration Timeout scenario](https://airtable.com/developers/web/api/list-records#:~:text=LIST_RECORDS_ITERATOR_NOT_AVAILABLE) yourself
For convenient usage, you also have `firstPage()` or `all()` method:
```typescript
const table = new Airtable().base('appEpvhkjHcG8OvKu').table('tblc7ieWKVQM9eequ');
// List comments also exposes pagination
// https://airtable.com/developers/web/api/list-comments
const query = table.comments('recPaibwSLDbZr80V', { pageSize: 50 });
const firstPageComments: AirtableComment[] = await query.firstPage();
const allComments: AirtableComment[] = await query.all();
```
Some endpoint doesn't expose pagination control, in this case we always return all records:
```typescript
const airtable = new Airtable();
// It uses pagination but doesn't provide much control
// https://airtable.com/developers/web/api/list-bases
const bases: BaseInfo[] = await airtable.bases();
```
## 📘 Type Friendly
Specify your own data:
```typescript
import { Airtable, type FieldSet } from "airtable-ofetch";
interface TableData extends FieldSet {
Name: string;
Notes: string;
}
// Type-assisted table
const table = new Airtable().base('appEpvhkjHcG8OvKu').table('tblc7ieWKVQM9eequ');
// Return typed records
const records: AirtableRecord[] = await table.list().all();
console.log(records[0].get('Name')) // Field name will be type assisted
```
Consult [here](https://github.com/nadhifikbarw/airtable-ofetch/blob/main/src/types.ts#L860) to see interface shape. Adjusted in accordance to [Web API docs](https://airtable.com/developers/web/api/field-model).
## 📦 Bundler Notes
Since this client implemented on top of [unjs/ofetch](https://github.com/unjs/ofetch#-bundler-notes), please consult [ofetch's Bundler Notes](https://github.com/unjs/ofetch#-bundler-notes) to ensure compatibility with your project.
## 💻 Development
* Clone this repository
* Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
* Install dependencies using `pnpm install`
* Run interactive tests using `pnpm dev`
## License
[MIT](./LICENSE)