1 | import * as wmill from "windmill-client" |
2 | import { S3Object } from "windmill-client" |
3 |
|
4 | export type DynSelect_folder_id = string |
5 |
|
6 | |
7 | export async function folder_id(auth: RT.Gdrive) { |
8 | const url = new URL("https://www.googleapis.com/drive/v3/files") |
9 | url.searchParams.append( |
10 | "q", |
11 | "mimeType = 'application/vnd.google-apps.folder' and trashed = false" |
12 | ) |
13 | url.searchParams.append("fields", "files(id, name)") |
14 | url.searchParams.append("orderBy", "name") |
15 | url.searchParams.append("pageSize", "1000") |
16 | url.searchParams.append("supportsAllDrives", "true") |
17 | url.searchParams.append("includeItemsFromAllDrives", "true") |
18 | const response = await fetch(url, { |
19 | headers: { |
20 | Authorization: `Bearer ${auth.token}`, |
21 | Accept: "application/json", |
22 | }, |
23 | }) |
24 | if (!response.ok) { |
25 | throw new Error(`${response.status} ${await response.text()}`) |
26 | } |
27 | const { files } = (await response.json()) as { |
28 | files: { id: string; name: string }[] |
29 | } |
30 | return [ |
31 | { value: "root", label: "My Drive (root)" }, |
32 | ...files.map((f) => ({ value: f.id, label: `${f.name} (${f.id})` })), |
33 | ] |
34 | } |
35 |
|
36 | |
37 | * Upload File |
38 | * Upload a file from Windmill object storage to Google Drive (any size, resumable upload). Leave the folder empty to upload to the root of My Drive. Set `convert_to` to a Google mime type (e.g. application/vnd.google-apps.document) to convert on upload. |
39 | */ |
40 | export async function main( |
41 | auth: RT.Gdrive, |
42 | file: S3Object, |
43 | name: string | undefined, |
44 | folder_id: DynSelect_folder_id | undefined, |
45 | mime_type: string | undefined, |
46 | convert_to: string | undefined |
47 | ) { |
48 | const bytes = await wmill.loadS3File(file) |
49 | if (!bytes) { |
50 | throw new Error("Could not load the file from object storage") |
51 | } |
52 |
|
53 | const metadata: { [key: string]: any } = { |
54 | name: name || file.s3.split("/").pop(), |
55 | } |
56 | if (folder_id !== undefined && folder_id !== "") |
57 | metadata.parents = [folder_id] |
58 | if (convert_to !== undefined && convert_to !== "") |
59 | metadata.mimeType = convert_to |
60 |
|
61 | |
62 | const url = new URL("https://www.googleapis.com/upload/drive/v3/files") |
63 | url.searchParams.append("uploadType", "resumable") |
64 | url.searchParams.append("supportsAllDrives", "true") |
65 | const session = await fetch(url, { |
66 | method: "POST", |
67 | headers: { |
68 | Authorization: `Bearer ${auth.token}`, |
69 | "Content-Type": "application/json; charset=UTF-8", |
70 | ...(mime_type ? { "X-Upload-Content-Type": mime_type } : {}), |
71 | }, |
72 | body: JSON.stringify(metadata), |
73 | }) |
74 | if (!session.ok) { |
75 | throw new Error(`${session.status} ${await session.text()}`) |
76 | } |
77 |
|
78 | |
79 | const response = await fetch(session.headers.get("Location")!, { |
80 | method: "PUT", |
81 | headers: { |
82 | Authorization: `Bearer ${auth.token}`, |
83 | ...(mime_type ? { "Content-Type": mime_type } : {}), |
84 | }, |
85 | body: bytes, |
86 | }) |
87 |
|
88 | if (!response.ok) { |
89 | throw new Error(`${response.status} ${await response.text()}`) |
90 | } |
91 |
|
92 | return await response.json() |
93 | } |
94 |
|