diff --git a/packages/web-api/src/WebClient.spec.ts b/packages/web-api/src/WebClient.spec.ts index e4d4575dc..eeb46e9a1 100644 --- a/packages/web-api/src/WebClient.spec.ts +++ b/packages/web-api/src/WebClient.spec.ts @@ -326,6 +326,24 @@ describe('WebClient', () => { assert.fail('Should have logged a warning and info when files.upload is used'); } }); + + it('warns when user is accessing a deprecated method', async () => { + const client = new WebClient(token, { logLevel: LogLevel.INFO, logger }); + await client.apiCall('workflows.stepCompleted', {}); + + let warnedAboutDeprecatedMethod = false; + for (const call of (logger.warn as sinon.SinonStub).getCalls()) { + if ( + call.args[0] === + 'workflows.stepCompleted is deprecated. Please check on https://docs.slack.dev/reference/methods for an alternative.' + ) { + warnedAboutDeprecatedMethod = true; + } + } + if (!warnedAboutDeprecatedMethod) { + assert.fail('Should have logged a warning when a deprecated method is used'); + } + }); }); describe('with OAuth scopes in the response headers', () => { diff --git a/packages/web-api/src/WebClient.ts b/packages/web-api/src/WebClient.ts index c5f83b9dc..36eecc0ac 100644 --- a/packages/web-api/src/WebClient.ts +++ b/packages/web-api/src/WebClient.ts @@ -964,7 +964,7 @@ function parseRetryHeaders(response: AxiosResponse): number | undefined { * @param logger instance of web clients logger */ function warnDeprecations(method: string, logger: Logger): void { - const deprecatedMethods = ['workflows.']; + const deprecatedMethods = ['workflows.stepCompleted', 'workflows.stepFailed', 'workflows.updateStep']; const isDeprecated = deprecatedMethods.some((depMethod) => { const re = new RegExp(`^${depMethod}`); diff --git a/packages/web-api/src/methods.ts b/packages/web-api/src/methods.ts index 3ebf5dbff..e3e6e06bf 100644 --- a/packages/web-api/src/methods.ts +++ b/packages/web-api/src/methods.ts @@ -250,6 +250,10 @@ import type { ViewsPublishArguments, ViewsPushArguments, ViewsUpdateArguments, + WorkflowsFeaturedAddArguments, + WorkflowsFeaturedListArguments, + WorkflowsFeaturedRemoveArguments, + WorkflowsFeaturedSetArguments, WorkflowsStepCompletedArguments, WorkflowsStepFailedArguments, WorkflowsUpdateStepArguments, @@ -503,6 +507,10 @@ import type { ViewsPublishResponse, ViewsPushResponse, ViewsUpdateResponse, + WorkflowsFeaturedAddResponse, + WorkflowsFeaturedListResponse, + WorkflowsFeaturedRemoveResponse, + WorkflowsFeaturedSetResponse, WorkflowsStepCompletedResponse, WorkflowsStepFailedResponse, WorkflowsUpdateStepResponse, @@ -2380,6 +2388,31 @@ export abstract class Methods extends EventEmitter { }; public readonly workflows = { + featured: { + /** + * @description Add featured workflows to a channel. + * @see {@link https://docs.slack.dev/reference/methods/workflows.featured.add `workflows.featured.add` API reference}. + */ + add: bindApiCall(this, 'workflows.featured.add'), + /** + * @description List the featured workflows for specified channels. + * @see {@link https://docs.slack.dev/reference/methods/workflows.featured.list `workflows.featured.list` API reference}. + */ + list: bindApiCall(this, 'workflows.featured.list'), + /** + * @description Remove featured workflows from a channel. + * @see {@link https://docs.slack.dev/reference/methods/workflows.featured.remove `workflows.featured.remove` API reference}. + */ + remove: bindApiCall( + this, + 'workflows.featured.remove', + ), + /** + * @description Set featured workflows for a channel. + * @see {@link https://docs.slack.dev/reference/methods/workflows.featured.set `workflows.featured.set` API reference}. + */ + set: bindApiCall(this, 'workflows.featured.set'), + }, /** * @description Indicate that an app's step in a workflow completed execution. * @deprecated Steps from Apps is deprecated. diff --git a/packages/web-api/src/types/request/index.ts b/packages/web-api/src/types/request/index.ts index 305055de8..0391c1607 100644 --- a/packages/web-api/src/types/request/index.ts +++ b/packages/web-api/src/types/request/index.ts @@ -317,6 +317,10 @@ export type { ViewsUpdateArguments, } from './views'; export type { + WorkflowsFeaturedAddArguments, + WorkflowsFeaturedListArguments, + WorkflowsFeaturedRemoveArguments, + WorkflowsFeaturedSetArguments, WorkflowsStepCompletedArguments, WorkflowsStepFailedArguments, WorkflowsUpdateStepArguments, diff --git a/packages/web-api/src/types/request/workflows.ts b/packages/web-api/src/types/request/workflows.ts index 64006935f..4173caf94 100644 --- a/packages/web-api/src/types/request/workflows.ts +++ b/packages/web-api/src/types/request/workflows.ts @@ -1,5 +1,53 @@ import type { TokenOverridable } from './common'; +// https://docs.slack.dev/reference/methods/workflows.featured.add +export interface WorkflowsFeaturedAddArguments extends TokenOverridable { + /** + * @description Channel to add featured workflow in. + */ + channel_id: string; + /** + * @description Comma-separated array of trigger IDs to add; max 15 + * @example ["Ft012345", "Ft012346"] + */ + trigger_ids: string[]; +} + +// https://docs.slack.dev/reference/methods/workflows.featured.list +export interface WorkflowsFeaturedListArguments extends TokenOverridable { + /** + * @description Comma-separated array of channel IDs to list featured workflows for. + * @example ["C012345678", "C987654321"] + */ + channel_ids: string[]; +} + +// https://docs.slack.dev/reference/methods/workflows.featured.remove +export interface WorkflowsFeaturedRemoveArguments extends TokenOverridable { + /** + * @description Channel to remove featured workflow from. + */ + channel_id: string; + /** + * @description Comma-separated array of trigger IDs to remove; max 15 + * @example ["Ft012345", "Ft012346"] + */ + trigger_ids: string[]; +} + +// https://docs.slack.dev/reference/methods/workflows.featured.set +export interface WorkflowsFeaturedSetArguments extends TokenOverridable { + /** + * @description Channel to set featured workflow in. + */ + channel_id: string; + /** + * @description Comma-separated array of trigger IDs that will replace any existing featured workflows in the channel; max 15 + * @example ["Ft012345", "Ft012346"] + */ + trigger_ids: string[]; +} + // TODO: breaking change: to be removed after Sep 12 2024 // https://docs.slack.dev/changelog/2023-08-workflow-steps-from-apps-step-back diff --git a/packages/web-api/src/types/response/WorkflowsFeaturedAddResponse.ts b/packages/web-api/src/types/response/WorkflowsFeaturedAddResponse.ts new file mode 100644 index 000000000..aa71dc15b --- /dev/null +++ b/packages/web-api/src/types/response/WorkflowsFeaturedAddResponse.ts @@ -0,0 +1,3 @@ +import type { WebAPICallResult } from '../../WebClient'; + +export type WorkflowsFeaturedAddResponse = WebAPICallResult & {}; diff --git a/packages/web-api/src/types/response/WorkflowsFeaturedListResponse.ts b/packages/web-api/src/types/response/WorkflowsFeaturedListResponse.ts new file mode 100644 index 000000000..e5de2cc91 --- /dev/null +++ b/packages/web-api/src/types/response/WorkflowsFeaturedListResponse.ts @@ -0,0 +1,11 @@ +import type { WebAPICallResult } from '../../WebClient'; + +export type WorkflowsFeaturedListResponse = WebAPICallResult & { + featured_workflows: { + channel_id: string; + triggers: { + id: string; + title: string; + }[]; + }[]; +}; diff --git a/packages/web-api/src/types/response/WorkflowsFeaturedRemoveResponse.ts b/packages/web-api/src/types/response/WorkflowsFeaturedRemoveResponse.ts new file mode 100644 index 000000000..45004b950 --- /dev/null +++ b/packages/web-api/src/types/response/WorkflowsFeaturedRemoveResponse.ts @@ -0,0 +1,3 @@ +import type { WebAPICallResult } from '../../WebClient'; + +export type WorkflowsFeaturedRemoveResponse = WebAPICallResult & {}; diff --git a/packages/web-api/src/types/response/WorkflowsFeaturedSetResponse.ts b/packages/web-api/src/types/response/WorkflowsFeaturedSetResponse.ts new file mode 100644 index 000000000..04903a4cc --- /dev/null +++ b/packages/web-api/src/types/response/WorkflowsFeaturedSetResponse.ts @@ -0,0 +1,3 @@ +import type { WebAPICallResult } from '../../WebClient'; + +export type WorkflowsFeaturedSetResponse = WebAPICallResult & {}; diff --git a/packages/web-api/src/types/response/index.ts b/packages/web-api/src/types/response/index.ts index 1f78f13fe..c9186bd75 100644 --- a/packages/web-api/src/types/response/index.ts +++ b/packages/web-api/src/types/response/index.ts @@ -308,6 +308,10 @@ export { ViewsOpenResponse } from './ViewsOpenResponse'; export { ViewsPublishResponse } from './ViewsPublishResponse'; export { ViewsPushResponse } from './ViewsPushResponse'; export { ViewsUpdateResponse } from './ViewsUpdateResponse'; +export { WorkflowsFeaturedAddResponse } from './WorkflowsFeaturedAddResponse'; +export { WorkflowsFeaturedListResponse } from './WorkflowsFeaturedListResponse'; +export { WorkflowsFeaturedRemoveResponse } from './WorkflowsFeaturedRemoveResponse'; +export { WorkflowsFeaturedSetResponse } from './WorkflowsFeaturedSetResponse'; export { WorkflowsStepCompletedResponse } from './WorkflowsStepCompletedResponse'; export { WorkflowsStepFailedResponse } from './WorkflowsStepFailedResponse'; export { WorkflowsUpdateStepResponse } from './WorkflowsUpdateStepResponse'; diff --git a/packages/web-api/test/types/methods/workflows.test-d.ts b/packages/web-api/test/types/methods/workflows.test-d.ts new file mode 100644 index 000000000..b897c8b23 --- /dev/null +++ b/packages/web-api/test/types/methods/workflows.test-d.ts @@ -0,0 +1,116 @@ +import { expectAssignable, expectError } from 'tsd'; + +import { WebClient } from '../../../src/WebClient'; + +const web = new WebClient('TOKEN'); + +// workflows.featured.add +// -- sad path +expectError(web.workflows.featured.add()); // lacking argument +expectError(web.workflows.featured.add({})); // empty argument +expectError( + web.workflows.featured.add({ + channel_id: 'C1234', // missing trigger_ids + }), +); +expectError( + web.workflows.featured.add({ + trigger_ids: [], // missing channel_id + }), +); +expectError( + web.workflows.featured.add({ + channel_id: 'C1234', + trigger_ids: 'Ft1234', // not an array + }), +); +// -- happy path +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: [], + }, +]); +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: ['Ft1234', 'Ft0001'], + }, +]); + +// workflows.featured.list +// -- sad path +expectError(web.workflows.featured.list()); // lacking argument +expectError(web.workflows.featured.list({})); // empty argument +expectError( + web.workflows.featured.list({ + channel_ids: 'C1234', // not an array + }), +); +// -- happy path +expectAssignable>([ + { + channel_ids: [], + }, +]); +expectAssignable>([ + { + channel_ids: ['C1234', 'C0001'], + }, +]); + +// workflows.featured.remove +// -- sad path +expectError(web.workflows.featured.remove()); // lacking argument +expectError(web.workflows.featured.remove({})); // empty argument +expectError( + web.workflows.featured.remove({ + channel_id: 'C1234', // missing trigger_ids + }), +); +expectError( + web.workflows.featured.remove({ + trigger_ids: [], // missing channel_id + }), +); +// -- happy path +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: [], + }, +]); +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: ['Ft1234', 'Ft0001'], + }, +]); + +// workflows.featured.set +// -- sad path +expectError(web.workflows.featured.set()); // lacking argument +expectError(web.workflows.featured.set({})); // empty argument +expectError( + web.workflows.featured.set({ + channel_id: 'C1234', // missing trigger_ids + }), +); +expectError( + web.workflows.featured.set({ + trigger_ids: [], // missing channel_id + }), +); +// -- happy path +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: [], + }, +]); +expectAssignable>([ + { + channel_id: 'C1234', + trigger_ids: ['Ft1234', 'Ft0001'], + }, +]);