0

New or Updated Record

by
Published 4 days ago

Emits records whose timestamp is newer than the last poll, tracked via Windmill state. Defaults to sys_updated_on.

Scriptยท trigger servicenow Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 5 days ago
1
//native
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
// Dropdown of the instance's tables (sys_db_object).
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
  // ServiceNow datetimes are 'YYYY-MM-DD HH:MM:SS' in UTC (no trailing Z).
53
  const nowUtc = new Date().toISOString().slice(0, 19).replace("T", " ")
54

55
  // First run: set the watermark to now and don't emit a backlog.
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