0

Upload Attachment

by
Published 4 days ago

Attach a file from Windmill object storage to a record via the Attachment API.

Script servicenow Verified

The script

Submitted by hugo989 Bun
Verified 5 days ago
1
import * as wmill from "windmill-client"
2
import { S3Object } from "windmill-client"
3

4
export type DynSelect_table = string
5

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

12
// Dropdown of the instance's tables (sys_db_object).
13
export async function table(auth: RT.Servicenow) {
14
  const response = await fetch(
15
    `${auth.instance_url}/api/now/table/sys_db_object?sysparm_fields=name,label&sysparm_limit=10000`,
16
    {
17
      headers: {
18
        Authorization: authHeader(auth),
19
        Accept: "application/json",
20
      },
21
    }
22
  )
23
  if (!response.ok) {
24
    throw new Error(`${response.status} ${await response.text()}`)
25
  }
26
  const { result } = (await response.json()) as {
27
    result: { name: string; label: string }[]
28
  }
29
  return result
30
    .filter((t) => t.name)
31
    .map((t) => ({ value: t.name, label: `${t.label} (${t.name})` }))
32
    .sort((a, b) => a.label.localeCompare(b.label))
33
}
34

35
/**
36
 * Upload Attachment
37
 * Attach a file from Windmill object storage to a record. Reads the bytes and posts them to the Attachment API (table_name, table_sys_id, file_name in the query string; raw body).
38
 */
39
export async function main(
40
  auth: RT.Servicenow,
41
  table: DynSelect_table,
42
  record_sys_id: string,
43
  file: S3Object,
44
  file_name: string,
45
  content_type: string | undefined
46
) {
47
  const bytes = await wmill.loadS3File(file)
48
  if (!bytes) {
49
    throw new Error("Could not load the file from object storage")
50
  }
51

52
  const url = new URL(`${auth.instance_url}/api/now/attachment/file`)
53
  url.searchParams.append("table_name", table)
54
  url.searchParams.append("table_sys_id", record_sys_id)
55
  url.searchParams.append("file_name", file_name)
56

57
  const response = await fetch(url, {
58
    method: "POST",
59
    headers: {
60
      Authorization: authHeader(auth),
61
      "Content-Type":
62
        content_type && content_type !== ""
63
          ? content_type
64
          : "application/octet-stream",
65
      Accept: "application/json",
66
    },
67
    body: bytes,
68
  })
69

70
  if (!response.ok) {
71
    throw new Error(`${response.status} ${await response.text()}`)
72
  }
73

74
  return await response.json()
75
}
76