1 | import * as wmill from "windmill-client" |
2 | import { S3Object } from "windmill-client" |
3 |
|
4 | |
5 | * Upload File |
6 | * Upload a file from Windmill object storage to Salesforce as a ContentVersion (Salesforce Files), optionally linking it to a record. |
7 | */ |
8 | export async function main( |
9 | auth: RT.Salesforce, |
10 | file: S3Object, |
11 | title: string, |
12 | linked_record_id: string | undefined |
13 | ) { |
14 | const apiVersion = auth.api_version || "v60.0" |
15 |
|
16 | |
17 | const bytes = await wmill.loadS3File(file) |
18 | if (!bytes) { |
19 | throw new Error("Could not load the file from object storage") |
20 | } |
21 | const versionData = Buffer.from(bytes).toString("base64") |
22 |
|
23 | |
24 | const cvResponse = await fetch( |
25 | `${auth.instance_url}/services/data/${apiVersion}/sobjects/ContentVersion`, |
26 | { |
27 | method: "POST", |
28 | headers: { |
29 | Authorization: `Bearer ${auth.token}`, |
30 | "Content-Type": "application/json", |
31 | Accept: "application/json", |
32 | }, |
33 | body: JSON.stringify({ |
34 | Title: title, |
35 | PathOnClient: title, |
36 | VersionData: versionData, |
37 | }), |
38 | } |
39 | ) |
40 | if (!cvResponse.ok) { |
41 | throw new Error(`${cvResponse.status} ${await cvResponse.text()}`) |
42 | } |
43 | const contentVersion = (await cvResponse.json()) as { id: string } |
44 |
|
45 | if (linked_record_id === undefined || linked_record_id === "") { |
46 | return contentVersion |
47 | } |
48 |
|
49 | |
50 | const queryUrl = new URL( |
51 | `${auth.instance_url}/services/data/${apiVersion}/query` |
52 | ) |
53 | queryUrl.searchParams.append( |
54 | "q", |
55 | `SELECT ContentDocumentId FROM ContentVersion WHERE Id = '${contentVersion.id}'` |
56 | ) |
57 | const queryResponse = await fetch(queryUrl, { |
58 | headers: { |
59 | Authorization: `Bearer ${auth.token}`, |
60 | Accept: "application/json", |
61 | }, |
62 | }) |
63 | if (!queryResponse.ok) { |
64 | throw new Error(`${queryResponse.status} ${await queryResponse.text()}`) |
65 | } |
66 | const contentDocumentId = ( |
67 | (await queryResponse.json()) as { |
68 | records: { ContentDocumentId: string }[] |
69 | } |
70 | ).records[0].ContentDocumentId |
71 |
|
72 | |
73 | const linkResponse = await fetch( |
74 | `${auth.instance_url}/services/data/${apiVersion}/sobjects/ContentDocumentLink`, |
75 | { |
76 | method: "POST", |
77 | headers: { |
78 | Authorization: `Bearer ${auth.token}`, |
79 | "Content-Type": "application/json", |
80 | Accept: "application/json", |
81 | }, |
82 | body: JSON.stringify({ |
83 | ContentDocumentId: contentDocumentId, |
84 | LinkedEntityId: linked_record_id, |
85 | ShareType: "V", |
86 | }), |
87 | } |
88 | ) |
89 | if (!linkResponse.ok) { |
90 | throw new Error(`${linkResponse.status} ${await linkResponse.text()}`) |
91 | } |
92 |
|
93 | return { |
94 | contentVersionId: contentVersion.id, |
95 | contentDocumentId, |
96 | linkedEntityId: linked_record_id, |
97 | success: true, |
98 | } |
99 | } |
100 |
|