Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reviewing Types #1542

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@slack/types",
"version": "2.7.0",
"version": "2.8.0-centralized.1",
"description": "Shared type definitions for the Node Slack SDK",
"author": "Slack Technologies, LLC",
"license": "MIT",
Expand Down
117 changes: 73 additions & 44 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/*
* Reusable shapes for argument values
*/
// TODO: dialogs are deprecated https://api.slack.com/dialogs
filmaj marked this conversation as resolved.
Show resolved Hide resolved
// Guide on upgrading dialogs to modals: https://api.slack.com/block-kit/dialogs-to-modals
export interface Dialog {
title: string;
callback_id: string;
Expand Down Expand Up @@ -63,16 +65,10 @@ export interface WorkflowStepView {

export type View = HomeView | ModalView | WorkflowStepView;

/*
* Block Elements
/**
* Composition Objects: https://api.slack.com/reference/block-kit/composition-objects
*/

export interface ImageElement {
type: 'image';
image_url: string;
alt_text: string;
}

export interface PlainTextElement {
type: 'plain_text';
text: string;
Expand All @@ -87,43 +83,60 @@ export interface MrkdwnElement {

export interface MrkdwnOption {
text: MrkdwnElement;
value?: string;
value: string;
url?: string;
description?: PlainTextElement;
}

export interface PlainTextOption {
text: PlainTextElement;
value?: string;
value: string; // TODO: technically this property is optional, but if it is not provided, if the option is selected
// as a value in e.g. a static menu, then the returned value will be `null`
url?: string;
description?: PlainTextElement;
}

export type Option = MrkdwnOption | PlainTextOption;

export interface Confirm {
title?: PlainTextElement;
title: PlainTextElement;
text: PlainTextElement | MrkdwnElement;
confirm?: PlainTextElement;
deny?: PlainTextElement;
style?: 'primary' | 'danger';
confirm: PlainTextElement;
deny: PlainTextElement;
style?: 'primary' | 'danger'; // TODO: factor out into own type
}

export type Option = MrkdwnOption | PlainTextOption;

export interface DispatchActionConfig {
trigger_actions_on?: ('on_enter_pressed' | 'on_character_entered')[];
}

/*
* Action Types
* Block Elements: https://api.slack.com/reference/block-kit/block-elements
* Also known as interactive elements
* Exported below as Action
*/

// Selects and Multiselects are available in different surface areas so I've separated them here
export type Select = UsersSelect | StaticSelect | ConversationsSelect | ChannelsSelect | ExternalSelect;

export type MultiSelect =
MultiUsersSelect | MultiStaticSelect | MultiConversationsSelect | MultiChannelsSelect | MultiExternalSelect;
export type KnownAction =
Select | MultiSelect | Button | Overflow | Datepicker | Timepicker | RadioButtons | Checkboxes | PlainTextInput;

export interface Action {
type: string;
/**
* @description: A string acting as a unique identifier for a block.
*/
block_id?: string; // TODO: in event payloads, this property will always be present. When defining a block, however,
// it is optional. If not defined when the block is created, Slack will auto-assign a block_id for you - thus why it
// is always present in payloads. So: how can we capture that? Differentiate between the event payload vs. the block
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably have to, since I don't see a world where this particular behavior changes - and the behavior seems reasonable. Were you thinking that this Block Kit type could somehow be used to model event payload responses?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly! At least, I was consider if that would be possible! If you look at the block_actions payload event's fields, you'll see that there is an array of actions provided in the payload. These actions are the exact block kit elements that were interacted with - so I was considering if it would be possible to re-use the types in this repo to try to model the items of that actions array in the block_actions payload.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the item in actions in a block_actions payload, we already have complete types in bolt-js. If we would like to have it, we can consider moving the ones in bolt-js into this repo. Reusing Action and so on here may cause unnecessary complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seratch Yes I would like to eventually move as many types for things shared across repos as possible into this repo. For the block_actions payload, for example, I know right now we only need it in bolt-js. However, in deno-slack-sdk, it is also needed. So all of this work is in prep for trying to consolidate not just around our existing node projects, but across our newer deno ones too.

// element?
action_id?: string;
}

// Selects and Multiselects are available in different surface areas so I've separated them here
export type Select = UsersSelect | StaticSelect | ConversationsSelect | ChannelsSelect | ExternalSelect;

export type MultiSelect =
MultiUsersSelect | MultiStaticSelect | MultiConversationsSelect | MultiChannelsSelect | MultiExternalSelect;

export interface UsersSelect extends Action {
type: 'users_select';
initial_user?: string;
Expand All @@ -145,10 +158,11 @@ export interface StaticSelect extends Action {
type: 'static_select';
placeholder?: PlainTextElement;
initial_option?: PlainTextOption;
options?: PlainTextOption[];
option_groups?: {
options?: PlainTextOption[]; // TODO: mutually exclusive with option_groups but one of them is required
// TODO: minimum length of 1
option_groups?: { // todo: factor into own interface
label: PlainTextElement;
options: PlainTextOption[];
options: PlainTextOption[]; // TODO: min length 1
}[];
confirm?: Confirm;
focus_on_load?: boolean;
Expand All @@ -158,10 +172,11 @@ export interface MultiStaticSelect extends Action {
type: 'multi_static_select';
placeholder?: PlainTextElement;
initial_options?: PlainTextOption[];
options?: PlainTextOption[];
option_groups?: {
options?: PlainTextOption[]; // TODO: options and option_groups are mutually exclusive but one of them is required
// TODO: minimum length of 1
option_groups?: { // todo: factor into own interface
label: PlainTextElement;
options: PlainTextOption[];
options: PlainTextOption[]; // TODO: min length 1
}[];
max_selected_items?: number;
confirm?: Confirm;
Expand Down Expand Up @@ -202,6 +217,7 @@ export interface ChannelsSelect extends Action {
type: 'channels_select';
initial_channel?: string;
placeholder?: PlainTextElement;
response_url_enabled?: boolean;
confirm?: Confirm;
focus_on_load?: boolean;
}
Expand Down Expand Up @@ -235,18 +251,22 @@ export interface MultiExternalSelect extends Action {
}

export interface Button extends Action {
type: 'button';
accessibility_label?: string;
confirm?: Confirm;
style?: 'danger' | 'primary';
text: PlainTextElement;
value?: string;
type: 'button';
/**
* @description: A URL to load in the user's browser when the button is clicked. Maximum length for this field is
* 3000 characters.
*/
url?: string;
style?: 'danger' | 'primary';
confirm?: Confirm;
accessibility_label?: string;
value?: string;
}

export interface Overflow extends Action {
type: 'overflow';
options: PlainTextOption[];
options: PlainTextOption[]; // TODO: min length 1
confirm?: Confirm;
}

Expand All @@ -270,15 +290,15 @@ export interface Timepicker extends Action {
export interface RadioButtons extends Action {
type: 'radio_buttons';
initial_option?: Option;
options: Option[];
options: Option[]; // TODO: min length 1
confirm?: Confirm;
focus_on_load?: boolean;
}

export interface Checkboxes extends Action {
type: 'checkboxes';
initial_options?: Option[];
options: Option[];
options: Option[]; // TODO: min length 1
confirm?: Confirm;
focus_on_load?: boolean;
}
Expand All @@ -294,22 +314,30 @@ export interface PlainTextInput extends Action {
focus_on_load?: boolean;
}

export interface DispatchActionConfig {
trigger_actions_on?: ('on_enter_pressed' | 'on_character_entered')[];
export interface ImageElement {
type: 'image';
image_url: string;
alt_text: string;
}

/*
* Block Types
/**
* Layout Blocks: https://api.slack.com/reference/block-kit/blocks
*/

export type KnownBlock = ImageBlock | ContextBlock | ActionsBlock | DividerBlock |
SectionBlock | InputBlock | FileBlock | HeaderBlock | VideoBlock;

export interface Block {
type: string;
/**
* @description: A string acting as a unique identifier for a block. If not specified, a `block_id` will be generated.
* You can use this `block_id` when you receive an interaction payload to identify the source of the action. Maximum
* length for this field is 255 characters. block_id should be unique for each message and each iteration of a
* message. If a message is updated, use a new block_id.
*/
block_id?: string;
}

export type KnownBlock = ImageBlock | ContextBlock | ActionsBlock | DividerBlock |
SectionBlock | InputBlock | FileBlock | HeaderBlock | VideoBlock;

export interface ImageBlock extends Block {
type: 'image';
image_url: string;
Expand All @@ -324,7 +352,7 @@ export interface ContextBlock extends Block {

export interface ActionsBlock extends Block {
type: 'actions';
elements: (Button | Overflow | Datepicker | Timepicker | Select | RadioButtons | Checkboxes | Action)[];
elements: (Button | Overflow | Datepicker | Timepicker | Select | MultiSelect | RadioButtons | Checkboxes | Action)[];
}

export interface DividerBlock extends Block {
Expand All @@ -339,6 +367,7 @@ export interface SectionBlock extends Block {
| Overflow
| Datepicker
| Timepicker
| PlainTextInput
| Select
| MultiSelect
| Action
Expand Down