From 9c35a7758c9b73db65326c7325611678f540cce1 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 27 Nov 2024 10:26:17 +0000 Subject: [PATCH] Update attachment endpoints to use TS --- .../app/forms/AttachmentField.svelte | 5 +- .../src/components/app/forms/S3Upload.svelte | 7 +- .../app/forms/SignatureField.svelte | 8 +- packages/client/src/utils/buttonActions.js | 7 +- packages/frontend-core/src/api/attachments.js | 78 ------------- packages/frontend-core/src/api/attachments.ts | 109 ++++++++++++++++++ packages/frontend-core/src/api/types.ts | 2 +- 7 files changed, 117 insertions(+), 99 deletions(-) delete mode 100644 packages/frontend-core/src/api/attachments.js create mode 100644 packages/frontend-core/src/api/attachments.ts diff --git a/packages/client/src/components/app/forms/AttachmentField.svelte b/packages/client/src/components/app/forms/AttachmentField.svelte index 27286a8666..d9a91016cb 100644 --- a/packages/client/src/components/app/forms/AttachmentField.svelte +++ b/packages/client/src/components/app/forms/AttachmentField.svelte @@ -49,10 +49,7 @@ data.append("file", fileList[i]) } try { - return await API.uploadAttachment({ - data, - tableId: formContext?.dataSource?.tableId, - }) + return await API.uploadAttachment(formContext?.dataSource?.tableId, data) } catch (error) { return [] } diff --git a/packages/client/src/components/app/forms/S3Upload.svelte b/packages/client/src/components/app/forms/S3Upload.svelte index 0147cbca6e..936eb14f91 100644 --- a/packages/client/src/components/app/forms/S3Upload.svelte +++ b/packages/client/src/components/app/forms/S3Upload.svelte @@ -80,12 +80,7 @@ const upload = async () => { loading = true try { - const res = await API.externalUpload({ - datasourceId, - bucket, - key, - data, - }) + const res = await API.externalUpload(datasourceId, bucket, key, data) notificationStore.actions.success("File uploaded successfully") loading = false return res diff --git a/packages/client/src/components/app/forms/SignatureField.svelte b/packages/client/src/components/app/forms/SignatureField.svelte index bdae148368..a7a7dc3206 100644 --- a/packages/client/src/components/app/forms/SignatureField.svelte +++ b/packages/client/src/components/app/forms/SignatureField.svelte @@ -31,10 +31,10 @@ let attachRequest = new FormData() attachRequest.append("file", signatureFile) - const resp = await API.uploadAttachment({ - data: attachRequest, - tableId: formContext?.dataSource?.tableId, - }) + const resp = await API.uploadAttachment( + formContext?.dataSource?.tableId, + attachRequest + ) const [signatureAttachment] = resp updateValue = signatureAttachment } else { diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index e2b0071042..63354d3119 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -454,12 +454,7 @@ const downloadFileHandler = async action => { const { type } = action.parameters if (type === "attachment") { const { tableId, rowId, attachmentColumn } = action.parameters - const res = await API.downloadAttachment( - tableId, - rowId, - attachmentColumn, - { suppressErrors: true } - ) + const res = await API.downloadAttachment(tableId, rowId, attachmentColumn) await downloadStream(res) return } diff --git a/packages/frontend-core/src/api/attachments.js b/packages/frontend-core/src/api/attachments.js deleted file mode 100644 index 72f280d99d..0000000000 --- a/packages/frontend-core/src/api/attachments.js +++ /dev/null @@ -1,78 +0,0 @@ -export const buildAttachmentEndpoints = API => { - /** - * Generates a signed URL to upload a file to an external datasource. - * @param datasourceId the ID of the datasource to upload to - * @param bucket the name of the bucket to upload to - * @param key the name of the file to upload to - */ - const getSignedDatasourceURL = async ({ datasourceId, bucket, key }) => { - return await API.post({ - url: `/api/attachments/${datasourceId}/url`, - body: { bucket, key }, - }) - } - - return { - getSignedDatasourceURL, - - /** - * Uploads an attachment to the server. - * @param data the attachment to upload - * @param tableId the table ID to upload to - */ - uploadAttachment: async ({ data, tableId }) => { - return await API.post({ - url: `/api/attachments/${tableId}/upload`, - body: data, - json: false, - }) - }, - - /** - * Uploads an attachment to the server as a builder user from the builder. - * @param data the data to upload - */ - uploadBuilderAttachment: async data => { - return await API.post({ - url: "/api/attachments/process", - body: data, - json: false, - }) - }, - - /** - * Uploads a file to an external datasource. - * @param datasourceId the ID of the datasource to upload to - * @param bucket the name of the bucket to upload to - * @param key the name of the file to upload to - * @param data the file to upload - */ - externalUpload: async ({ datasourceId, bucket, key, data }) => { - const { signedUrl, publicUrl } = await getSignedDatasourceURL({ - datasourceId, - bucket, - key, - }) - await API.put({ - url: signedUrl, - body: data, - json: false, - external: true, - }) - return { publicUrl } - }, - /** - * Download an attachment from a row given its column name. - * @param datasourceId the ID of the datasource to download from - * @param rowId the ID of the row to download from - * @param columnName the column name to download - */ - downloadAttachment: async (datasourceId, rowId, columnName, options) => { - return await API.get({ - url: `/api/${datasourceId}/rows/${rowId}/attachment/${columnName}`, - parseResponse: response => response, - suppressErrors: options?.suppressErrors, - }) - }, - } -} diff --git a/packages/frontend-core/src/api/attachments.ts b/packages/frontend-core/src/api/attachments.ts new file mode 100644 index 0000000000..a57e545111 --- /dev/null +++ b/packages/frontend-core/src/api/attachments.ts @@ -0,0 +1,109 @@ +import { ProcessAttachmentResponse } from "@budibase/types" +import { BaseAPIClient } from "./types" + +export interface AttachmentEndpoints { + getSignedDatasourceURL: ( + datasourceId: string, + bucket: string, + key: string + ) => Promise<{ signedUrl: string; publicUrl: string }> + uploadAttachment: ( + tableId: string, + data: any + ) => Promise + uploadBuilderAttachment: (data: any) => Promise + externalUpload: ( + datasourceId: string, + bucket: string, + key: string, + data: any + ) => Promise<{ publicUrl: string }> + downloadAttachment: ( + datasourceId: string, + rowId: string, + columnName: string + ) => Promise +} + +export const buildAttachmentEndpoints = ( + API: BaseAPIClient +): AttachmentEndpoints => { + const endpoints: Pick = { + /** + * Generates a signed URL to upload a file to an external datasource. + * @param datasourceId the ID of the datasource to upload to + * @param bucket the name of the bucket to upload to + * @param key the name of the file to upload to + */ + getSignedDatasourceURL: async (datasourceId, bucket, key) => { + return await API.post({ + url: `/api/attachments/${datasourceId}/url`, + body: { bucket, key }, + }) + }, + } + + return { + ...endpoints, + + /** + * Uploads an attachment to the server. + * @param data the attachment to upload + * @param tableId the table ID to upload to + */ + uploadAttachment: async (tableId, data) => { + return await API.post({ + url: `/api/attachments/${tableId}/upload`, + body: data, + json: false, + }) + }, + + /** + * Uploads an attachment to the server as a builder user from the builder. + * @param data the data to upload + */ + uploadBuilderAttachment: async data => { + return await API.post({ + url: "/api/attachments/process", + body: data, + json: false, + }) + }, + + /** + * Uploads a file to an external datasource. + * @param datasourceId the ID of the datasource to upload to + * @param bucket the name of the bucket to upload to + * @param key the name of the file to upload to + * @param data the file to upload + */ + externalUpload: async (datasourceId, bucket, key, data) => { + const { signedUrl, publicUrl } = await endpoints.getSignedDatasourceURL( + datasourceId, + bucket, + key + ) + await API.put({ + url: signedUrl, + body: data, + json: false, + external: true, + }) + return { publicUrl } + }, + /** + * Download an attachment from a row given its column name. + * @param datasourceId the ID of the datasource to download from + * @param rowId the ID of the row to download from + * @param columnName the column name to download + */ + downloadAttachment: async (datasourceId, rowId, columnName) => { + return await API.get({ + url: `/api/${datasourceId}/rows/${rowId}/attachment/${columnName}`, + parseResponse: response => response as any, + suppressErrors: true, + }) + }, + } +} diff --git a/packages/frontend-core/src/api/types.ts b/packages/frontend-core/src/api/types.ts index 257e34d3a3..350deb4e90 100644 --- a/packages/frontend-core/src/api/types.ts +++ b/packages/frontend-core/src/api/types.ts @@ -27,7 +27,7 @@ export type APICallConfig = { suppressErrors: boolean cache: boolean body?: any - parseResponse?: (response: Response) => Promise + parseResponse?: (response: Response) => Promise | T } export type APICallParams = Pick & Partial