diff --git a/.changeset/deep-knives-tie.md b/.changeset/deep-knives-tie.md new file mode 100644 index 000000000..5adf33e8f --- /dev/null +++ b/.changeset/deep-knives-tie.md @@ -0,0 +1,19 @@ +--- +"@slack/web-api": minor +--- + +feat: add `highlight_type` to [`files.completeUploadExternal`](https://docs.slack.dev/reference/methods/files.completeUploadExternal) and [`filesUploadV2`](https://docs.slack.dev/tools/node-slack-sdk/web-api#upload-a-file) for optimistic rendering + +```js +import { WebClient } from "@slack/web-api"; + +const client = new WebClient(process.env.SLACK_BOT_TOKEN); + +await client.filesUploadV2({ + channel_id: "C0123456789", + file: "./image.png", + filename: "image.png", + title: "Image Upload", + highlight_type: "png", +}); +``` diff --git a/packages/web-api/src/file-upload.test.ts b/packages/web-api/src/file-upload.test.ts index bc14885d5..e9902e333 100644 --- a/packages/web-api/src/file-upload.test.ts +++ b/packages/web-api/src/file-upload.test.ts @@ -316,6 +316,28 @@ describe('file-upload', () => { }); }); describe('getAllFileUploadsToComplete', () => { + it('should pass all expected properties through to the completion job', () => { + const fileUploadJob1 = { + file: Buffer.from('test'), + filename: 'image.png', + file_id: 'id1', + title: 'test1', + channel_id: 'C123', + thread_ts: '1.0', + initial_comment: 'Here is an image', + highlight_type: 'png', + blocks: [{ type: 'section', text: { type: 'plain_text', text: 'hello' } }], + }; + const toComplete = getAllFileUploadsToComplete([fileUploadJob1]); + const job = Object.values(toComplete)[0]; + assert.strictEqual(job.files[0].id, 'id1'); + assert.strictEqual(job.files[0].title, 'test1'); + assert.strictEqual(job.channel_id, 'C123'); + assert.strictEqual(job.thread_ts, '1.0'); + assert.strictEqual(job.initial_comment, 'Here is an image'); + assert.strictEqual(job.files[0].highlight_type, 'png'); + assert.deepStrictEqual(job.blocks, fileUploadJob1.blocks); + }); describe('when channel_id is the same', () => { it('should group uploads with matching thread_ts and initial_comment together', () => { const fileUploadJob1 = { diff --git a/packages/web-api/src/file-upload.ts b/packages/web-api/src/file-upload.ts index b8b44e424..b6beade2d 100644 --- a/packages/web-api/src/file-upload.ts +++ b/packages/web-api/src/file-upload.ts @@ -30,6 +30,7 @@ export async function getFileUploadJob( blocks: options.blocks, channel_id: options.channels ?? options.channel_id, filename: options.filename ?? fileName, + highlight_type: options.highlight_type, initial_comment: options.initial_comment, snippet_type: options.snippet_type, title: options.title ?? options.filename ?? fileName, // default title to filename unless otherwise specified @@ -234,13 +235,13 @@ export function getAllFileUploadsToComplete( ): Record { const toComplete: Record = {}; for (const upload of fileUploads) { - const { blocks, channel_id, thread_ts, initial_comment, file_id, title } = upload; + const { blocks, channel_id, thread_ts, highlight_type, initial_comment, file_id, title } = upload; if (file_id) { const compareString = `:::${channel_id}:::${thread_ts}:::${initial_comment}:::${JSON.stringify(blocks)}`; // biome-ignore lint/suspicious/noPrototypeBuiltins: TODO use hasOwn instead of hasOwnProperty if (!Object.prototype.hasOwnProperty.call(toComplete, compareString)) { toComplete[compareString] = { - files: [{ id: file_id, title }], + files: [{ id: file_id, title, highlight_type }], channel_id, blocks, initial_comment, @@ -262,6 +263,7 @@ export function getAllFileUploadsToComplete( toComplete[compareString].files.push({ id: file_id, title, + highlight_type, }); } } else { diff --git a/packages/web-api/src/types/request/files.ts b/packages/web-api/src/types/request/files.ts index e891bff6d..3d05ddd7f 100644 --- a/packages/web-api/src/types/request/files.ts +++ b/packages/web-api/src/types/request/files.ts @@ -34,6 +34,11 @@ export interface FileType { export interface FileUploadComplete { /** @description Encoded file ID. */ id: string; + /** + * @description Optional highlight type hint for the file. The upload processing job may overwrite this value. + * @see {@link https://docs.slack.dev/reference/methods/files.completeUploadExternal} + */ + highlight_type?: string; /** @description File title. */ title?: string; } @@ -168,6 +173,11 @@ export type FileUploadV2 = FileUpload & { channel_id?: string; /** @deprecated use channel_id instead */ channels?: string; + /** + * @description Optional highlight type hint for the file. The upload processing job may overwrite this value. + * @see {@link https://docs.slack.dev/reference/methods/files.completeUploadExternal} + */ + highlight_type?: string; /** @description Syntax type of the snippet being uploaded. E.g. `python`. */ snippet_type?: string; };