1 | |
2 |
|
3 | export type DynSelect_base_id = string |
4 | export type DynSelect_table_id = string |
5 |
|
6 | |
7 | export async function base_id(auth: RT.Airtable) { |
8 | const options: { value: string; label: string }[] = [] |
9 | let offset: string | undefined = undefined |
10 | do { |
11 | const url = new URL("https://api.airtable.com/v0/meta/bases") |
12 | if (offset) { |
13 | url.searchParams.append("offset", offset) |
14 | } |
15 | const response = await fetch(url, { |
16 | headers: { |
17 | Authorization: `Bearer ${auth.apiKey}`, |
18 | Accept: "application/json", |
19 | }, |
20 | }) |
21 | if (!response.ok) { |
22 | throw new Error(`${response.status} ${await response.text()}`) |
23 | } |
24 | const page = (await response.json()) as { |
25 | bases: { id: string; name: string }[] |
26 | offset?: string |
27 | } |
28 | options.push(...page.bases.map((b) => ({ value: b.id, label: b.name }))) |
29 | offset = page.offset |
30 | } while (offset) |
31 | return options |
32 | } |
33 |
|
34 | async function listTables(auth: RT.Airtable, base_id: string) { |
35 | if (!base_id) { |
36 | return [] |
37 | } |
38 | const response = await fetch( |
39 | `https://api.airtable.com/v0/meta/bases/${base_id}/tables`, |
40 | { |
41 | headers: { |
42 | Authorization: `Bearer ${auth.apiKey}`, |
43 | Accept: "application/json", |
44 | }, |
45 | } |
46 | ) |
47 | if (!response.ok) { |
48 | throw new Error(`${response.status} ${await response.text()}`) |
49 | } |
50 | const { tables } = (await response.json()) as { |
51 | tables: { |
52 | id: string |
53 | name: string |
54 | fields: { id: string; name: string; type: string }[] |
55 | views: { id: string; name: string }[] |
56 | }[] |
57 | } |
58 | return tables |
59 | } |
60 |
|
61 | |
62 | export async function table_id(auth: RT.Airtable, base_id: DynSelect_base_id) { |
63 | return (await listTables(auth, base_id)).map((t) => ({ |
64 | value: t.id, |
65 | label: t.name, |
66 | })) |
67 | } |
68 |
|
69 | |
70 | * Create Field |
71 | * Add a field (column) to a table. `type` is an Airtable field type such as singleLineText, multilineText, number, checkbox, singleSelect, multipleSelects, date, dateTime, email, url, currency, percent, rating or multipleRecordLinks; most types other than plain text need `options` (e.g. { "precision": 0 } for number, { "choices": [{ "name": "Todo" }] } for singleSelect). Requires the schema.bases:write scope. |
72 | */ |
73 | export async function main( |
74 | auth: RT.Airtable, |
75 | base_id: DynSelect_base_id, |
76 | table_id: DynSelect_table_id, |
77 | name: string, |
78 | type: string, |
79 | description: string | undefined, |
80 | options: { [key: string]: any } | undefined |
81 | ) { |
82 | const body: { [key: string]: any } = { name, type } |
83 | if (description != null && description !== "") { |
84 | body.description = description |
85 | } |
86 | if (options != null && Object.keys(options).length > 0) { |
87 | body.options = options |
88 | } |
89 |
|
90 | const response = await fetch( |
91 | `https://api.airtable.com/v0/meta/bases/${base_id}/tables/${table_id}/fields`, |
92 | { |
93 | method: "POST", |
94 | headers: { |
95 | Authorization: `Bearer ${auth.apiKey}`, |
96 | "Content-Type": "application/json", |
97 | Accept: "application/json", |
98 | }, |
99 | body: JSON.stringify(body), |
100 | } |
101 | ) |
102 | if (!response.ok) { |
103 | throw new Error(`${response.status} ${await response.text()}`) |
104 | } |
105 |
|
106 | return await response.json() |
107 | } |
108 |
|