0

Get change next states

by
Published today

List the states a change request can move to next, with transition conditions for model-driven changes, through the Change Management API.

Script servicenow Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 6 hours ago
1
//native
2

3
function authHeader(auth: RT.Servicenow) {
4
  return auth.token
5
    ? `Bearer ${auth.token}`
6
    : `Basic ${btoa(`${auth.username}:${auth.password}`)}`
7
}
8

9
/**
10
 * Get Change Next States
11
 * List the states a change request can move to next, including its current state, through the Change Management API (GET /api/sn_chg_rest/change/{sys_id}/nextstates, documented in the Yokohama and Brazil API references). For changes driven by a change model, each transition also says whether it is available and which conditions passed or failed; type-driven (legacy) changes only return the state list.
12
 */
13
export async function main(auth: RT.Servicenow, sys_id: string) {
14
  const url = new URL(
15
    `${auth.instance_url}/api/sn_chg_rest/change/${encodeURIComponent(sys_id)}/nextstates`
16
  )
17

18
  const response = await fetch(url, {
19
    headers: {
20
      Authorization: authHeader(auth),
21
      Accept: "application/json",
22
    },
23
  })
24

25
  if (!response.ok) {
26
    throw new Error(`${response.status} ${await response.text()}`)
27
  }
28

29
  const { result } = (await response.json()) as {
30
    result: {
31
      available_states?: string[]
32
      state_label?: { [state: string]: string }
33
      state_transitions?: any[]
34
    }
35
  }
36

37
  // The schema documents state_transitions as an array of transitions, but the
38
  // documented example nests one array per target state: accept both.
39
  const transitions = (result.state_transitions ?? []).flat().map((t: any) => ({
40
    from_state: t.from_state,
41
    to_state: t.to_state,
42
    to_state_label: result.state_label?.[t.to_state],
43
    display_value: t.display_value,
44
    transition_available: t.transition_available,
45
    automatic_transition: t.automatic_transition,
46
    conditions: (t.conditions ?? []).map((c: any) => ({
47
      name: c.condition?.name,
48
      description: c.condition?.description,
49
      passed: c.passed,
50
    })),
51
  }))
52

53
  return {
54
    available_states: (result.available_states ?? []).map((state) => ({
55
      state,
56
      label: result.state_label?.[state],
57
    })),
58
    transitions,
59
    result,
60
  }
61
}
62