@relayfile/adapter-airtable 0.1.0

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.
Files changed (37) hide show
  1. package/dist/__tests__/airtable-adapter.test.d.ts +2 -0
  2. package/dist/__tests__/airtable-adapter.test.d.ts.map +1 -0
  3. package/dist/__tests__/airtable-adapter.test.js +201 -0
  4. package/dist/__tests__/airtable-adapter.test.js.map +1 -0
  5. package/dist/__tests__/webhook-normalizer.test.d.ts +2 -0
  6. package/dist/__tests__/webhook-normalizer.test.d.ts.map +1 -0
  7. package/dist/__tests__/webhook-normalizer.test.js +102 -0
  8. package/dist/__tests__/webhook-normalizer.test.js.map +1 -0
  9. package/dist/airtable-adapter.d.ts +77 -0
  10. package/dist/airtable-adapter.d.ts.map +1 -0
  11. package/dist/airtable-adapter.js +705 -0
  12. package/dist/airtable-adapter.js.map +1 -0
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +7 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/path-mapper.d.ts +21 -0
  18. package/dist/path-mapper.d.ts.map +1 -0
  19. package/dist/path-mapper.js +116 -0
  20. package/dist/path-mapper.js.map +1 -0
  21. package/dist/queries.d.ts +6 -0
  22. package/dist/queries.d.ts.map +1 -0
  23. package/dist/queries.js +43 -0
  24. package/dist/queries.js.map +1 -0
  25. package/dist/types.d.ts +107 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/types.js +11 -0
  28. package/dist/types.js.map +1 -0
  29. package/dist/webhook-normalizer.d.ts +50 -0
  30. package/dist/webhook-normalizer.d.ts.map +1 -0
  31. package/dist/webhook-normalizer.js +501 -0
  32. package/dist/webhook-normalizer.js.map +1 -0
  33. package/dist/writeback.d.ts +5 -0
  34. package/dist/writeback.d.ts.map +1 -0
  35. package/dist/writeback.js +139 -0
  36. package/dist/writeback.js.map +1 -0
  37. package/package.json +71 -0
@@ -0,0 +1,139 @@
1
+ import { parseAirtablePath } from './path-mapper.js';
2
+ export const AIRTABLE_WRITEBACK_ROUTE_TEMPLATE = '/v0/{baseId}/{tableId}';
3
+ export function resolveAirtableWritebackRequest(path, content) {
4
+ const parsed = parseAirtablePath(path);
5
+ const payload = parseJsonObject(content);
6
+ if (parsed.objectType === 'record') {
7
+ const fields = unwrapFields(payload);
8
+ const endpoint = `/v0/${encodeURIComponent(requireBaseId(parsed.baseId))}/${encodeURIComponent(requireTableId(parsed.tableId))}`;
9
+ return {
10
+ action: 'update_record',
11
+ body: {
12
+ records: [
13
+ {
14
+ id: parsed.objectId,
15
+ fields,
16
+ },
17
+ ],
18
+ },
19
+ endpoint,
20
+ method: 'PATCH',
21
+ routeTemplate: AIRTABLE_WRITEBACK_ROUTE_TEMPLATE,
22
+ };
23
+ }
24
+ if (parsed.objectType === 'table') {
25
+ const records = readRecords(payload);
26
+ return {
27
+ action: 'create_record',
28
+ body: {
29
+ records,
30
+ },
31
+ endpoint: `/v0/${encodeURIComponent(requireBaseId(parsed.baseId))}/${encodeURIComponent(parsed.objectId)}`,
32
+ method: 'POST',
33
+ routeTemplate: AIRTABLE_WRITEBACK_ROUTE_TEMPLATE,
34
+ };
35
+ }
36
+ throw new Error(`No Airtable writeback rule matched ${path}`);
37
+ }
38
+ export function resolveAirtableReplaceRecordRequest(path, content) {
39
+ const parsed = parseAirtablePath(path);
40
+ if (parsed.objectType !== 'record') {
41
+ throw new Error(`Airtable replace writeback requires a record path: ${path}`);
42
+ }
43
+ return {
44
+ action: 'replace_record',
45
+ body: {
46
+ records: [
47
+ {
48
+ id: parsed.objectId,
49
+ fields: unwrapFields(parseJsonObject(content)),
50
+ },
51
+ ],
52
+ },
53
+ endpoint: `/v0/${encodeURIComponent(requireBaseId(parsed.baseId))}/${encodeURIComponent(requireTableId(parsed.tableId))}`,
54
+ method: 'PUT',
55
+ routeTemplate: AIRTABLE_WRITEBACK_ROUTE_TEMPLATE,
56
+ };
57
+ }
58
+ function readRecords(payload) {
59
+ const records = payload.records;
60
+ if (Array.isArray(records)) {
61
+ return records.map((record) => {
62
+ if (!isRecord(record)) {
63
+ throw new Error('Airtable records writeback expects record objects');
64
+ }
65
+ const fields = unwrapFields(record);
66
+ return { fields };
67
+ });
68
+ }
69
+ return [{ fields: unwrapFields(payload) }];
70
+ }
71
+ function unwrapFields(payload) {
72
+ if (isRecord(payload.payload) && looksLikeSyncedEnvelope(payload)) {
73
+ return unwrapFields(payload.payload);
74
+ }
75
+ if (isRecord(payload.fields)) {
76
+ if (Object.keys(payload.fields).length === 0) {
77
+ throw new Error('Airtable writeback requires at least one field');
78
+ }
79
+ return { ...payload.fields };
80
+ }
81
+ const fields = {};
82
+ for (const [key, value] of Object.entries(payload)) {
83
+ if (ENVELOPE_KEYS.has(key)) {
84
+ continue;
85
+ }
86
+ fields[key] = value;
87
+ }
88
+ if (Object.keys(fields).length === 0) {
89
+ throw new Error('Airtable writeback requires at least one field');
90
+ }
91
+ return fields;
92
+ }
93
+ const ENVELOPE_KEYS = new Set([
94
+ 'baseId',
95
+ 'connectionId',
96
+ 'deleted',
97
+ 'eventType',
98
+ 'id',
99
+ 'objectId',
100
+ 'objectType',
101
+ 'provider',
102
+ 'tableId',
103
+ 'workspaceId',
104
+ ]);
105
+ function looksLikeSyncedEnvelope(payload) {
106
+ return ['provider', 'objectType', 'objectId', 'workspaceId'].some((key) => key in payload);
107
+ }
108
+ function parseJsonObject(content) {
109
+ let parsed;
110
+ try {
111
+ parsed = JSON.parse(content);
112
+ }
113
+ catch (error) {
114
+ throw new Error(`Airtable writeback content must be valid JSON: ${toErrorMessage(error)}`);
115
+ }
116
+ if (!isRecord(parsed)) {
117
+ throw new Error('Airtable writeback content must be a JSON object');
118
+ }
119
+ return parsed;
120
+ }
121
+ function requireBaseId(baseId) {
122
+ if (!baseId) {
123
+ throw new Error('Airtable writeback route requires baseId');
124
+ }
125
+ return baseId;
126
+ }
127
+ function requireTableId(tableId) {
128
+ if (!tableId) {
129
+ throw new Error('Airtable writeback route requires tableId');
130
+ }
131
+ return tableId;
132
+ }
133
+ function isRecord(value) {
134
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
135
+ }
136
+ function toErrorMessage(error) {
137
+ return error instanceof Error ? error.message : String(error);
138
+ }
139
+ //# sourceMappingURL=writeback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writeback.js","sourceRoot":"","sources":["../src/writeback.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@relayfile/adapter-airtable",
3
+ "version": "0.1.0",
4
+ "description": "Airtable adapter package for Relayfile",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./path-mapper": {
15
+ "types": "./dist/path-mapper.d.ts",
16
+ "import": "./dist/path-mapper.js",
17
+ "default": "./dist/path-mapper.js"
18
+ },
19
+ "./writeback": {
20
+ "types": "./dist/writeback.d.ts",
21
+ "import": "./dist/writeback.js",
22
+ "default": "./dist/writeback.js"
23
+ },
24
+ "./webhook": {
25
+ "types": "./dist/webhook-normalizer.d.ts",
26
+ "import": "./dist/webhook-normalizer.js",
27
+ "default": "./dist/webhook-normalizer.js"
28
+ },
29
+ "./types": {
30
+ "types": "./dist/types.d.ts",
31
+ "import": "./dist/types.js",
32
+ "default": "./dist/types.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist"
37
+ ],
38
+ "scripts": {
39
+ "typecheck": "tsc --noEmit -p tsconfig.json",
40
+ "test": "node --import tsx --test 'src/**/*.test.ts'",
41
+ "build": "tsc",
42
+ "prepublishOnly": "npm run build"
43
+ },
44
+ "keywords": [
45
+ "relayfile",
46
+ "airtable",
47
+ "adapter"
48
+ ],
49
+ "license": "MIT",
50
+ "engines": {
51
+ "node": ">=18"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ },
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "https://github.com/AgentWorkforce/relayfile-adapters",
59
+ "directory": "packages/airtable"
60
+ },
61
+ "peerDependencies": {
62
+ "@relayfile/sdk": ">=0.6.0 <1"
63
+ },
64
+ "devDependencies": {
65
+ "@agent-relay/sdk": "^6.0.7",
66
+ "@relayfile/sdk": "^0.6.0",
67
+ "@types/node": "^24.6.0",
68
+ "tsx": "^4.20.6",
69
+ "typescript": "^5.9.3"
70
+ }
71
+ }