{"id":21569433,"url":"https://github.com/naturalcycles/airtable-lib","last_synced_at":"2025-04-10T14:06:44.468Z","repository":{"id":34881754,"uuid":"186057711","full_name":"NaturalCycles/airtable-lib","owner":"NaturalCycles","description":"High-level API and CLI for Airtable","archived":false,"fork":false,"pushed_at":"2025-04-05T17:56:34.000Z","size":1898,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-04-05T18:33:42.392Z","etag":null,"topics":["airtable","api","cli","nodejs","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NaturalCycles.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-05-10T21:42:18.000Z","updated_at":"2025-04-05T17:55:53.000Z","dependencies_parsed_at":"2024-01-19T13:29:49.732Z","dependency_job_id":"3503179f-a978-4c4e-b488-7f3b28431f98","html_url":"https://github.com/NaturalCycles/airtable-lib","commit_stats":{"total_commits":209,"total_committers":2,"mean_commits":104.5,"dds":0.4019138755980861,"last_synced_commit":"83d65783b2ebf880dc31994bfa08f8518a8a19cc"},"previous_names":[],"tags_count":105,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NaturalCycles%2Fairtable-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NaturalCycles%2Fairtable-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NaturalCycles%2Fairtable-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NaturalCycles%2Fairtable-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NaturalCycles","download_url":"https://codeload.github.com/NaturalCycles/airtable-lib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248231899,"owners_count":21069424,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["airtable","api","cli","nodejs","typescript"],"created_at":"2024-11-24T11:09:29.657Z","updated_at":"2025-04-10T14:06:44.437Z","avatar_url":"https://github.com/NaturalCycles.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## @naturalcycles/airtable-lib\n\n\u003e High-level API and CLI for Airtable.\n\n[![npm](https://img.shields.io/npm/v/@naturalcycles/airtable-lib/latest.svg)](https://www.npmjs.com/package/@naturalcycles/airtable-lib)\n[![](https://circleci.com/gh/NaturalCycles/airtable-lib.svg?style=shield\u0026circle-token=123)](https://circleci.com/gh/NaturalCycles/airtable-lib)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\n# Features\n\n- Allows high level API access to Airtable contents\n- Allows to download Airtable data to json (backup), upload it back with all links and order\n  preserved (not trivial if using stock low-level api)\n- Allows optional validation and transformation (mostly stripping and setting defaults) of data via\n  Joi schemas.\n\n# API\n\n- `AirtableLib`: high-level access object\n  - `fetchBase` ...\n- `AirtableDao`: access object for Airtable Table\n- `AirtableCache`: indexed contents of Airtable Base (indexed by airtableId)\n\n# Concept\n\n## Entities\n\nEntities are preferrably named without \"Airtable\" in their name, e.g `Coupon`, not `AirtableCoupon`.\n\nEntities extend `AirtableRecord` to have `airtableId` required property. Idea is to not strip it\nunless absolutely needed. Currently `airtable-lib` doesn't do any stripping. Keeping `airtableId` is\nuseful to be able to resolve links in runtime. `AirtableCache` always keeps and index of all records\nof Base by `airtableId`. `airtableId` is unique within your Base (not just within Table), that's why\nindex is built as `airtableId \u003e record`, not `airtableId \u003e Table \u003e record`.\n\n## Linking\n\nAny linked field in Airtable creates link in both directions (between 2 tables). Convention is to\n\"hide\" one link (typically \"back-link\") in Airtable UI to indicate that it's not used (if it's\nindeed not used and stripped from data by joi schema).\n\nThere was an idea to have a \"resolve step\" when downloading Airtable Base as json, to be able to\nreplace `airtableId`s in links to whole objects. The problem there is that it creates a circular\ndependency in javascript which is a very bad thing (e.g you cannot `console.log` such object, or\nsend it over the wire). Decision was made to NOT have a resolve step but instead have a\n`AirtableCache` with the index of all base records (from `airtableId` to Record), so it's possible\nto quickly resolve links in runtime. This is a design decision.\n\n## Backup / restore\n\nBacking up Airtable base to json file stores all `airtableId`s that are used to resolve links.\n\nWhen restoring from json to Airtable Base `airtableId`s cannot be preserved, that's Airtable\nlimitation, it needs to generate an `airtableId` every time an \"insert\" is made. Restore still works\nthough, with some extra logic. It relies on existing links in json file, builds a map from\n\"oldAirtableId\" to \"newlyGeneratedAirtableId\" and this way preserves the linking. Next time backup\nto json is made from Airtable base - `airtableId`s will be different (non-deterministic), something\nto be aware of.\n\nBacking up (as per current Airtable API) **does not** preserve order of rows. Restoring from json -\n**does** preserve order (but requires to upload records sequentially one-by-one, which is slower\nthan concurrent uploading). To overcome this limitation it's recommended to specify \"sort order\" in\n`AirtableTableSchema`, which allows order to be deterministic. Same order needs to be applied in the\nUI, to be consistent between UI and json export.\n\n# Packaging\n\n- `engines.node \u003e= 10.13`: Latest Node.js LTS\n- `main: dist/index.js`: commonjs, es2018\n- `types: dist/index.d.ts`: typescript types\n- `/src` folder with source `*.ts` files included\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaturalcycles%2Fairtable-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnaturalcycles%2Fairtable-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaturalcycles%2Fairtable-lib/lists"}