1 | |
2 |
|
3 | import * as wmill from "windmill-client" |
4 |
|
5 | export type DynSelect_table = string |
6 |
|
7 | function authHeader(auth: RT.Servicenow) { |
8 | return auth.token |
9 | ? `Bearer ${auth.token}` |
10 | : `Basic ${btoa(`${auth.username}:${auth.password}`)}` |
11 | } |
12 |
|
13 | |
14 | export async function table(auth: RT.Servicenow) { |
15 | const response = await fetch( |
16 | `${auth.instance_url}/api/now/table/sys_db_object?sysparm_fields=name,label&sysparm_limit=10000`, |
17 | { |
18 | headers: { |
19 | Authorization: authHeader(auth), |
20 | Accept: "application/json", |
21 | }, |
22 | } |
23 | ) |
24 | if (!response.ok) { |
25 | throw new Error(`${response.status} ${await response.text()}`) |
26 | } |
27 | const { result } = (await response.json()) as { |
28 | result: { name: string; label: string }[] |
29 | } |
30 | return result |
31 | .filter((t) => t.name) |
32 | .map((t) => ({ value: t.name, label: `${t.label} (${t.name})` })) |
33 | .sort((a, b) => a.label.localeCompare(b.label)) |
34 | } |
35 |
|
36 | |
37 | * New or Updated Record |
38 | * Emits records from a table whose timestamp is newer than the last poll, tracked via Windmill state. Defaults to sys_updated_on (set timestamp_field to sys_created_on for new-only). Optionally narrow with an extra encoded query. |
39 | */ |
40 | export async function main( |
41 | auth: RT.Servicenow, |
42 | table: DynSelect_table, |
43 | timestamp_field: "sys_updated_on" | "sys_created_on" | undefined, |
44 | query: string | undefined |
45 | ) { |
46 | const tsField = |
47 | timestamp_field && timestamp_field !== "" |
48 | ? timestamp_field |
49 | : "sys_updated_on" |
50 | const lastChecked: string | undefined = await wmill.getState() |
51 |
|
52 | |
53 | const nowUtc = new Date().toISOString().slice(0, 19).replace("T", " ") |
54 |
|
55 | |
56 | if (!lastChecked) { |
57 | await wmill.setState(nowUtc) |
58 | return [] |
59 | } |
60 |
|
61 | let encoded = `${tsField}>${lastChecked}` |
62 | if (query !== undefined && query !== "") { |
63 | encoded += `^${query}` |
64 | } |
65 | encoded += `^ORDERBY${tsField}` |
66 |
|
67 | const url = new URL(`${auth.instance_url}/api/now/table/${table}`) |
68 | url.searchParams.append("sysparm_query", encoded) |
69 | url.searchParams.append("sysparm_limit", "200") |
70 |
|
71 | const response = await fetch(url, { |
72 | method: "GET", |
73 | headers: { |
74 | Authorization: authHeader(auth), |
75 | Accept: "application/json", |
76 | }, |
77 | }) |
78 |
|
79 | if (!response.ok) { |
80 | throw new Error(`${response.status} ${await response.text()}`) |
81 | } |
82 |
|
83 | const { result } = (await response.json()) as { |
84 | result: Array<{ [key: string]: any }> |
85 | } |
86 |
|
87 | if (result.length > 0) { |
88 | await wmill.setState(result[result.length - 1][tsField]) |
89 | } |
90 |
|
91 | return result |
92 | } |
93 |
|