//native
import * as wmill from "windmill-client"
export type DynSelect_table = string
function authHeader(auth: RT.Servicenow) {
return auth.token
? `Bearer ${auth.token}`
: `Basic ${btoa(`${auth.username}:${auth.password}`)}`
}
// Dropdown of the instance's tables (sys_db_object).
export async function table(auth: RT.Servicenow) {
const response = await fetch(
`${auth.instance_url}/api/now/table/sys_db_object?sysparm_fields=name,label&sysparm_limit=10000`,
{
headers: {
Authorization: authHeader(auth),
Accept: "application/json",
},
}
)
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { result } = (await response.json()) as {
result: { name: string; label: string }[]
}
return result
.filter((t) => t.name)
.map((t) => ({ value: t.name, label: `${t.label} (${t.name})` }))
.sort((a, b) => a.label.localeCompare(b.label))
}
/**
* New or Updated Record
* 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.
*/
export async function main(
auth: RT.Servicenow,
table: DynSelect_table,
timestamp_field: "sys_updated_on" | "sys_created_on" | undefined,
query: string | undefined
) {
const tsField =
timestamp_field && timestamp_field !== ""
? timestamp_field
: "sys_updated_on"
const lastChecked: string | undefined = await wmill.getState()
// ServiceNow datetimes are 'YYYY-MM-DD HH:MM:SS' in UTC (no trailing Z).
const nowUtc = new Date().toISOString().slice(0, 19).replace("T", " ")
// First run: set the watermark to now and don't emit a backlog.
if (!lastChecked) {
await wmill.setState(nowUtc)
return []
}
let encoded = `${tsField}>${lastChecked}`
if (query !== undefined && query !== "") {
encoded += `^${query}`
}
encoded += `^ORDERBY${tsField}`
const url = new URL(`${auth.instance_url}/api/now/table/${table}`)
url.searchParams.append("sysparm_query", encoded)
url.searchParams.append("sysparm_limit", "200")
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: authHeader(auth),
Accept: "application/json",
},
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { result } = (await response.json()) as {
result: Array<{ [key: string]: any }>
}
if (result.length > 0) {
await wmill.setState(result[result.length - 1][tsField])
}
return result
}
Submitted by hugo989 5 days ago