@emulates/airtable 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog — @emulates/airtable
2
+
3
+ ## 0.1.1 (2026-10-06)
4
+
5
+ Initial release.
6
+
7
+ ### Dependencies
8
+
9
+ - `@emulates/sqlite`
package/DISCOVERY.md ADDED
@@ -0,0 +1,55 @@
1
+ # @emulates/airtable discovery
2
+
3
+ This is the installed-package index for coding agents and tooling. All relative links resolve
4
+ inside `node_modules/@emulates/airtable/`; no repository checkout is needed to discover the emulator's
5
+ supported surface or documented behavior.
6
+
7
+ ## Capability and behavior sources
8
+
9
+ | Question | Authoritative file | What it contains |
10
+ | --- | --- | --- |
11
+ | Behaviour and integration | [`README.md`](README.md) | Routes, state transitions, auth, webhooks, controls, presets and deliberate omissions. |
12
+ | Exact capabilities | [`SUPPORT.md`](SUPPORT.md) | Supported, unsupported and parity-covered operations or commands, including reasons for gaps. |
13
+ | Wire contract | [`openapi.yaml`](openapi.yaml) | Machine-readable paths, methods, schemas, responses and parity annotations. |
14
+ | Public API | [`dist/index.d.ts`](dist/index.d.ts) | The installed package's exact TypeScript exports and signatures. |
15
+ | Package metadata | [`package.json`](package.json) | Runtime/entry-point claims, vendor links, parity scope/tier and `emulates.discovery`. |
16
+
17
+ Read these together: the contract/capability matrix says *what* is available, while the README
18
+ defines stateful behavior, lifecycle rules, test controls, and intentional oracle differences.
19
+ If prose and an executable surface disagree, report a parity mismatch instead of adding a
20
+ consumer-side workaround.
21
+
22
+ ## Parity and oracle
23
+
24
+ - Declared parity surface: **OAuth, base metadata, fields and record creation**.
25
+ - Parity tier: **cold** (the repository controls when live checks run).
26
+ - Oracle: **Live vendor API or sandbox**.
27
+ - Repository command: `bun run parity:service -- airtable`.
28
+ - Evidence model: Run from an Emulates checkout; credentials come only from .env.local or GitHub Actions secrets. Missing credentials exit 2.
29
+
30
+ The npm package contains evidence summaries and the exact contract, not credentials or the
31
+ repository-only parity harness. Self-parity/property and acceptance tests run in the Emulates
32
+ repository; live parity is an additional oracle check, not a substitute for the packaged matrix.
33
+
34
+ ## Runtime introspection
35
+
36
+ - `GET /__admin/health`
37
+ - `GET /__admin`
38
+ - `GET /__admin/state`
39
+ - `GET /__admin/requests`
40
+ - `GET /__admin/metrics`
41
+ - `GET /__admin/faults/presets`
42
+ - `GET /__admin/ui`
43
+
44
+ For HTTP services, use `x-emulates-namespace` (or the documented credential/path carrier) so
45
+ parallel tests do not share state. Admin state, journal, metrics and fault-preset endpoints are
46
+ designed for assertions and diagnosis by consuming test suites.
47
+
48
+ ## Report a mismatch or missing capability
49
+
50
+ Follow the [agent reporting contract](https://github.com/crvouga/emulators/blob/main/docs/REPORTING_ISSUES.md). Include package version,
51
+ operation/command, a minimal redacted request, actual emulator result, expected oracle result or vendor
52
+ documentation, and whether the mismatch appears in the matrix. Never include keys, tokens,
53
+ customer data, prompts, PHI, card data, or unredacted recordings.
54
+
55
+ Service key: `airtable`.
package/README.md CHANGED
@@ -1,3 +1,54 @@
1
- # Temporary Holding Version
1
+ # @emulates/airtable
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Part of [Emulates](https://github.com/crvouga/emulators): high-fidelity, in-process emulators for APIs and databases.
4
+
5
+ WIP Airtable OAuth and forms-integration emulator. Only synthetic fixtures belong here.
6
+
7
+ ## Install
8
+
9
+ `bun add @emulates/airtable`
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { createRuntime } from "@emulates/airtable"
15
+ const runtime = createRuntime()
16
+ const response = await runtime.fetch(new Request("http://airtable.test/v0/meta/bases", {
17
+ headers: { authorization: "Bearer mock_airtable_token" },
18
+ }))
19
+ ```
20
+
21
+ Run `emulates-airtable serve --port 12130`. Inject its origin for both the API and OAuth origin in the optional integration; consumer endpoint wiring is separate.
22
+
23
+ ## Surface and state
24
+
25
+ - POST `/oauth2/v1/token`: form-encoded authorization-code and refresh grants. Confidential clients require Basic credentials; public clients use body client_id. Codes require S256 PKCE and exact redirect/client binding, expire by clock, and are consumed before verifier checks so even a rejected verifier cannot replay them. Refresh rotates both tokens; access lasts 60 minutes and refresh 60 days. Scope reduction is allowed. The documented trailing space in `token_type: "Bearer "` is retained.
26
+ - GET `/v0/meta/whoami`: user id and scopes, plus email only with `user.email:read`.
27
+ - GET `/v0/meta/bases`: accessible bases/permission levels and opaque offset pages (`pageSize`, default 1000).
28
+ - GET `/v0/meta/bases/{baseId}/tables`: table schemas/fields/views for accessible bases.
29
+ - POST `/v0/meta/bases/{baseId}/tables/{tableId}/fields`: add supported form-field schemas and retain options.
30
+ - POST `/v0/{baseId}/{tableId}`: up to ten records, or one top-level fields object. Accept field ids or names; persist only after every input record validates. Empty cells are omitted. `returnFieldsByFieldId` controls response keys. Table name aliases work.
31
+
32
+ Default bearer `mock_airtable_token`, refresh `mock_airtable_refresh`, client `mock_client` / `mock_client_secret`; base `appMockBase`, table `tblMockTable`, field `fldMockName` named Name. Default scopes permit schema reads/writes, record writes, and synthetic email. Grant scopes and base roles gate operations independently. Missing/inaccessible bases yield 403; invalid/expired access yields 401; invalid cells yield 422 without partial records.
33
+
34
+ Seed `bases`, `tables`, `grants`, `clients`, `codes`, and `records` using constructor options or standard admin state. Fields supported for typed form writes: singleLineText, multilineText, richText, email, url, phoneNumber, number, percent, currency, duration, rating, checkbox, date, dateTime, singleSelect and multipleSelects. Options for choices, precision and checkbox appearance are retained; select values must name a seeded choice. Scalar validation covers wire types rather than every vendor presentation constraint. Unknown field types fail instead of silently accepting arbitrary values.
35
+
36
+ ## Test controls
37
+
38
+ Standard relocatable `/__admin` health, state, reset, clock, Timeline checkpoints, request journal, metrics and faults. Header namespaces, `/__admin/ns/<name>` paths and bearer mappings isolate records/grants. Journals contain metadata only, not OAuth bodies or submitted form values. Presets: `unauthorized`, `rate_limited` (429, retry-after 30), `invalid_schema` (422), `server_error`, `connection_drop`. Generic fault rules add latency. No webhooks required.
39
+
40
+ ## Oracle and tests
41
+
42
+ Follows official Airtable [OAuth](https://airtable.com/developers/web/api/oauth-reference), [identity](https://airtable.com/developers/web/api/get-user-id-scopes), [bases](https://airtable.com/developers/web/api/list-bases), [schema](https://airtable.com/developers/web/api/get-base-schema), [field creation](https://airtable.com/developers/web/api/create-field), [record creation](https://airtable.com/developers/web/api/create-records) and [errors](https://airtable.com/developers/web/api/errors) references. No successful live OAuth or SaaS writes were performed; no credentials used.
43
+
44
+ `bun test` runs raw-fetch acceptance, every-operation self-parity and divergence detection. The consumer is a faithful wire-surface port, not inaccessible private source. `bun run parity` requires `AIRTABLE_ACCESS_TOKEN`; it performs only a read-only identity-envelope probe, never printing identifiers.
45
+
46
+ ## Deliberately not modelled
47
+
48
+ No actual SaaS writes, formulas/computed columns, linked records, attachments, collaborators, views editing, collaboration UI or production-integration activation. No typecast conversion, complete field-option/presentation validation, real quota accounting, exact error prose or internal offset format. Schema seeding may contain additional metadata; writes validate only the listed form-field types. OAuth retry grace/conflict timing, authorization UI and enterprise policy discovery are not simulated; fault controls can script these errors. Tokens/ids are local deterministic stand-ins.
49
+
50
+ ## API
51
+
52
+ Root runtime exports: `AirtableAPI`, `AIRTABLE_NAMESPACE`, `createRuntime`, `AIRTABLE_PRESETS`, `document`, `operationIds`, `supportedOperationIds`. Types: `AirtableAPIOptions`, `Field`, `Table`, `Base`, `Grant`, `Client`, `OAuthCode`, `StoredRecord`, `AirtableRuntimeOptions`, `AirtableRuntime`, `OperationId`, `SupportedOperationId`.
53
+
54
+ `/server` exports `createServer`, `serveTarget`, `DEFAULT_PORT`; types `AirtableServerOptions`, `AirtableServer`.
package/SUPPORT.md ADDED
@@ -0,0 +1,16 @@
1
+ # Airtable mock — operation support
2
+
3
+ Generated from `openapi.yaml`; do not edit by hand.
4
+
5
+ - operations in spec: **6**
6
+ - supported by the emulator: **6**
7
+ - parity enabled: **6**
8
+
9
+ | operationId | route | emulator | parity | notes |
10
+ | --- | --- | --- | --- | --- |
11
+ | `Whoami` | `GET /v0/meta/whoami` | ✅ supported | ✅ | |
12
+ | `ListBases` | `GET /v0/meta/bases` | ✅ supported | ✅ | |
13
+ | `ListTables` | `GET /v0/meta/bases/{baseId}/tables` | ✅ supported | ✅ | |
14
+ | `CreateField` | `POST /v0/meta/bases/{baseId}/tables/{tableId}/fields` | ✅ supported | ⚠️ unsafe (opt-in) | |
15
+ | `CreateRecords` | `POST /v0/{baseId}/{tableId}` | ✅ supported | ⚠️ unsafe (opt-in) | |
16
+ | `OAuthToken` | `POST /oauth2/v1/token` | ✅ supported | ⚠️ unsafe (opt-in) | |