1 | |
2 |
|
3 | import * as wmill from "windmill-client" |
4 |
|
5 | export type DynSelect_sheet_name = string |
6 |
|
7 | |
8 | export async function sheet_name(auth: RT.Gsheets, spreadsheet_id: string) { |
9 | const response = await fetch( |
10 | `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheet_id}?fields=sheets.properties.title`, |
11 | { |
12 | headers: { |
13 | Authorization: `Bearer ${auth.token}`, |
14 | Accept: "application/json", |
15 | }, |
16 | } |
17 | ) |
18 | if (!response.ok) { |
19 | throw new Error(`${response.status} ${await response.text()}`) |
20 | } |
21 | const { sheets } = (await response.json()) as { |
22 | sheets: { properties: { title: string } }[] |
23 | } |
24 | return sheets.map((s) => ({ |
25 | value: s.properties.title, |
26 | label: s.properties.title, |
27 | })) |
28 | } |
29 |
|
30 | |
31 | * New Row |
32 | * Polls for rows appended below the last row seen on the previous poll (polling because Google has no row-level push: Drive's push notification for a spreadsheet only says the file changed). Emits each new row with its 1-based `row_number` and values keyed by the header row (row 1). The first run records the current row count and emits nothing. |
33 | */ |
34 | export async function main( |
35 | auth: RT.Gsheets, |
36 | spreadsheet_id: string, |
37 | sheet_name: DynSelect_sheet_name |
38 | ) { |
39 | |
40 | const range = encodeURIComponent(`'${sheet_name.replaceAll("'", "''")}'`) |
41 | const response = await fetch( |
42 | `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheet_id}/values/${range}`, |
43 | { |
44 | headers: { |
45 | Authorization: `Bearer ${auth.token}`, |
46 | Accept: "application/json", |
47 | }, |
48 | } |
49 | ) |
50 |
|
51 | if (!response.ok) { |
52 | throw new Error(`${response.status} ${await response.text()}`) |
53 | } |
54 |
|
55 | |
56 | const { values = [] } = (await response.json()) as { values?: string[][] } |
57 | const seen: number | undefined = await wmill.getState() |
58 | await wmill.setState(values.length) |
59 |
|
60 | |
61 | if (seen === undefined || seen === null || values.length <= seen) return [] |
62 |
|
63 | const headers = values[0] ?? [] |
64 | return values.slice(Math.max(seen, 1)).map((row, i) => ({ |
65 | row_number: Math.max(seen, 1) + i + 1, |
66 | values: Object.fromEntries(headers.map((h, j) => [h, row[j] ?? ""])), |
67 | })) |
68 | } |
69 |
|