1 | |
2 |
|
3 | import * as wmill from "windmill-client" |
4 |
|
5 | type Invoice = { id: number; "created-at": string } |
6 |
|
7 | |
8 | * New Invoices |
9 | * Trigger returning invoices created since the last run, tracked by a created-at watermark with id de-duplication. |
10 | */ |
11 | export async function main(auth: RT.Coupa) { |
12 | const base = auth.instance_url.replace(/\/+$/, "") |
13 | const state: { watermark: string; seenIds: number[] } | null = |
14 | await wmill.getState() |
15 |
|
16 | if (!state || !state.watermark) { |
17 | |
18 | const seed = new Date(Date.now() - 60_000) |
19 | .toISOString() |
20 | .replace("Z", "+00:00") |
21 | await wmill.setState({ watermark: seed, seenIds: [] }) |
22 | return [] |
23 | } |
24 |
|
25 | |
26 | const returned: Invoice[] = [] |
27 | let offset = 0 |
28 | while (true) { |
29 | const url = new URL(`${base}/api/invoices`) |
30 | url.searchParams.append("created_at[gt_or_eq]", state.watermark) |
31 | url.searchParams.append("limit", "50") |
32 | url.searchParams.append("offset", String(offset)) |
33 | const response = await fetch(url, { |
34 | headers: { |
35 | Authorization: `Bearer ${auth.token}`, |
36 | Accept: "application/json", |
37 | }, |
38 | }) |
39 | if (!response.ok) { |
40 | throw new Error(`${response.status} ${await response.text()}`) |
41 | } |
42 | const page = (await response.json()) as Invoice[] |
43 | returned.push(...page) |
44 | if (page.length < 50) break |
45 | offset += 50 |
46 | } |
47 |
|
48 | const seen = new Set(state.seenIds) |
49 | const newInvoices = returned.filter((i) => !seen.has(i.id)) |
50 |
|
51 | if (newInvoices.length > 0) { |
52 | |
53 | |
54 | const maxEpoch = Math.max( |
55 | ...returned.map((i) => new Date(i["created-at"]).getTime()) |
56 | ) |
57 | const atMax = returned.filter( |
58 | (i) => new Date(i["created-at"]).getTime() === maxEpoch |
59 | ) |
60 | await wmill.setState({ |
61 | watermark: atMax[0]["created-at"], |
62 | seenIds: atMax.map((i) => i.id), |
63 | }) |
64 | } |
65 | return newInvoices |
66 | } |
67 |
|