From 96a0d83a1366703ecae40b5e0d5171be9123d079 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Thu, 14 Apr 2022 11:42:25 +0100 Subject: [PATCH] refactor: Tidy up builders and components (#7711) --- packages/discord.js/src/index.js | 4 +-- .../discord.js/src/structures/ActionRow.js | 14 ++++++++ .../src/structures/ActionRowBuilder.js | 11 +++++- .../src/structures/ButtonBuilder.js | 19 +++++++--- packages/discord.js/src/structures/Embed.js | 3 ++ .../discord.js/src/structures/EmbedBuilder.js | 34 ++++++++++-------- .../structures/MessageComponentInteraction.js | 25 ------------- .../discord.js/src/structures/ModalBuilder.js | 36 +++++++++++++++++++ .../src/structures/SelectMenuBuilder.js | 17 ++++++--- .../src/structures/SelectMenuOptionBuilder.js | 8 ++++- .../src/structures/TextInputBuilder.js | 17 ++++++--- .../src/structures/TextInputComponent.js | 8 +++++ packages/discord.js/src/util/Components.js | 13 +++++-- packages/discord.js/typings/index.d.ts | 20 ++++++++--- 14 files changed, 166 insertions(+), 63 deletions(-) create mode 100644 packages/discord.js/src/structures/ModalBuilder.js diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js index 1b0104021..c9aa4449e 100644 --- a/packages/discord.js/src/index.js +++ b/packages/discord.js/src/index.js @@ -99,7 +99,6 @@ exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommand exports.DMChannel = require('./structures/DMChannel'); exports.Embed = require('./structures/Embed'); exports.EmbedBuilder = require('./structures/EmbedBuilder'); -exports.UnsafeEmbed = require('@discordjs/builders').UnsafeEmbed; exports.Emoji = require('./structures/Emoji').Emoji; exports.Guild = require('./structures/Guild').Guild; exports.GuildAuditLogs = require('./structures/GuildAuditLogs'); @@ -122,6 +121,7 @@ exports.InviteStageInstance = require('./structures/InviteStageInstance'); exports.InviteGuild = require('./structures/InviteGuild'); exports.Message = require('./structures/Message').Message; exports.MessageAttachment = require('./structures/MessageAttachment'); +exports.ModalBuilder = require('./structures/ModalBuilder'); exports.MessageCollector = require('./structures/MessageCollector'); exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction'); exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction'); @@ -196,7 +196,6 @@ exports.InviteTargetType = require('discord-api-types/v10').InviteTargetType; exports.Locale = require('discord-api-types/v10').Locale; exports.MessageType = require('discord-api-types/v10').MessageType; exports.MessageFlags = require('discord-api-types/v10').MessageFlags; -exports.ModalBuilder = require('@discordjs/builders').ModalBuilder; exports.OAuth2Scopes = require('discord-api-types/v10').OAuth2Scopes; exports.PermissionFlagsBits = require('discord-api-types/v10').PermissionFlagsBits; exports.RESTJSONErrorCodes = require('discord-api-types/v10').RESTJSONErrorCodes; @@ -207,6 +206,7 @@ exports.TextInputStyle = require('discord-api-types/v10').TextInputStyle; exports.UserFlags = require('discord-api-types/v10').UserFlags; exports.WebhookType = require('discord-api-types/v10').WebhookType; exports.UnsafeButtonBuilder = require('@discordjs/builders').UnsafeButtonBuilder; +exports.UnsafeEmbedBuilder = require('@discordjs/builders').UnsafeEmbedBuilder; exports.UnsafeSelectMenuBuilder = require('@discordjs/builders').UnsafeSelectMenuBuilder; exports.UnsafeSelectMenuOptionBuilder = require('@discordjs/builders').UnsafeSelectMenuOptionBuilder; exports.UnsafeModalBuilder = require('@discordjs/builders').UnsafeModalBuilder; diff --git a/packages/discord.js/src/structures/ActionRow.js b/packages/discord.js/src/structures/ActionRow.js index b2a09d38d..b902a31aa 100644 --- a/packages/discord.js/src/structures/ActionRow.js +++ b/packages/discord.js/src/structures/ActionRow.js @@ -1,5 +1,6 @@ 'use strict'; +const { isJSONEncodable } = require('@discordjs/builders'); const Component = require('./Component'); const Components = require('../util/Components'); @@ -10,6 +11,7 @@ const Components = require('../util/Components'); class ActionRow extends Component { constructor({ components, ...data }) { super(data); + /** * The components in this action row * @type {Component[]} @@ -18,6 +20,18 @@ class ActionRow extends Component { this.components = components.map(c => Components.createComponent(c)); } + /** + * Creates a new action row builder from JSON data + * @param {JSONEncodable|APIActionRowComponent} other The other data + * @returns {ActionRowBuilder} + */ + static from(other) { + if (isJSONEncodable(other)) { + return new this(other.toJSON()); + } + return new this(other); + } + /** * Returns the API-compatible JSON for this component * @returns {APIActionRowComponent} diff --git a/packages/discord.js/src/structures/ActionRowBuilder.js b/packages/discord.js/src/structures/ActionRowBuilder.js index f7c97a9b1..1af68fe77 100644 --- a/packages/discord.js/src/structures/ActionRowBuilder.js +++ b/packages/discord.js/src/structures/ActionRowBuilder.js @@ -3,13 +3,22 @@ const { ActionRowBuilder: BuildersActionRow, ComponentBuilder } = require('@discordjs/builders'); const Transformers = require('../util/Transformers'); +/** + * Represents an action row builder. + * @extends {BuildersActionRow} + */ class ActionRowBuilder extends BuildersActionRow { constructor({ components, ...data } = {}) { super({ - components: components?.map(c => (c instanceof ComponentBuilder ? c : Transformers.toSnakeCase(c))), ...Transformers.toSnakeCase(data), + components: components?.map(c => (c instanceof ComponentBuilder ? c : Transformers.toSnakeCase(c))), }); } } module.exports = ActionRowBuilder; + +/** + * @external BuildersActionRow + * @see {@link https://discord.js.org/#/docs/builders/main/class/ActionRowBuilder} + */ diff --git a/packages/discord.js/src/structures/ButtonBuilder.js b/packages/discord.js/src/structures/ButtonBuilder.js index 2eab82803..44a88edc9 100644 --- a/packages/discord.js/src/structures/ButtonBuilder.js +++ b/packages/discord.js/src/structures/ButtonBuilder.js @@ -1,10 +1,14 @@ 'use strict'; -const { ButtonBuilder: BuildersButtonComponent, isJSONEncodable } = require('@discordjs/builders'); +const { ButtonBuilder: BuildersButton, isJSONEncodable } = require('@discordjs/builders'); const Transformers = require('../util/Transformers'); const Util = require('../util/Util'); -class ButtonBuilder extends BuildersButtonComponent { +/** + * Represents a button builder. + * @extends {BuildersButton} + */ +class ButtonBuilder extends BuildersButton { constructor({ emoji, ...data }) { super( Transformers.toSnakeCase({ ...data, emoji: emoji && typeof emoji === 'string' ? Util.parseEmoji(emoji) : emoji }), @@ -14,7 +18,7 @@ class ButtonBuilder extends BuildersButtonComponent { /** * Sets the emoji to display on this button * @param {string|APIMessageComponentEmoji} emoji The emoji to display on this button - * @returns {ButtonComponent} + * @returns {ButtonBuilder} */ setEmoji(emoji) { if (typeof emoji === 'string') { @@ -24,8 +28,8 @@ class ButtonBuilder extends BuildersButtonComponent { } /** - * Creates a new button builder from json data - * @param {JSONEncodable | APIButtonComponent} other The other data + * Creates a new button builder from JSON data + * @param {JSONEncodable|APIButtonComponent} other The other data * @returns {ButtonBuilder} */ static from(other) { @@ -37,3 +41,8 @@ class ButtonBuilder extends BuildersButtonComponent { } module.exports = ButtonBuilder; + +/** + * @external BuildersButton + * @see {@link https://discord.js.org/#/docs/builders/main/class/ButtonBuilder} + */ diff --git a/packages/discord.js/src/structures/Embed.js b/packages/discord.js/src/structures/Embed.js index d630e6f41..ddbec36c2 100644 --- a/packages/discord.js/src/structures/Embed.js +++ b/packages/discord.js/src/structures/Embed.js @@ -2,6 +2,9 @@ const isEqual = require('fast-deep-equal'); +/** + * Represents an embed. + */ class Embed { /** * Creates a new embed object diff --git a/packages/discord.js/src/structures/EmbedBuilder.js b/packages/discord.js/src/structures/EmbedBuilder.js index cc56d9697..289604f37 100644 --- a/packages/discord.js/src/structures/EmbedBuilder.js +++ b/packages/discord.js/src/structures/EmbedBuilder.js @@ -4,14 +4,27 @@ const { EmbedBuilder: BuildersEmbed, isJSONEncodable } = require('@discordjs/bui const Transformers = require('../util/Transformers'); const Util = require('../util/Util'); +/** + * Represents an embed builder. + * @extends {BuildersEmbed} + */ class EmbedBuilder extends BuildersEmbed { constructor(data) { super(Transformers.toSnakeCase(data)); } /** - * Creates a new embed builder from json data - * @param {JSONEncodable | APIEmbed} other The other data + * Sets the color of this embed + * @param {?ColorResolvable} color The color of the embed + * @returns {EmbedBuilder} + */ + setColor(color) { + return super.setColor(color && Util.resolveColor(color)); + } + + /** + * Creates a new embed builder from JSON data + * @param {JSONEncodable|APIEmbed} other The other data * @returns {EmbedBuilder} */ static from(other) { @@ -20,18 +33,11 @@ class EmbedBuilder extends BuildersEmbed { } return new this(other); } - - /** - * Sets the color of this embed - * @param {?ColorResolvable} color The color of the embed - * @returns {Embed} - */ - setColor(color) { - if (color === null) { - return super.setColor(null); - } - return super.setColor(Util.resolveColor(color)); - } } module.exports = EmbedBuilder; + +/** + * @external BuildersEmbed + * @see {@link https://discord.js.org/#/docs/builders/main/class/EmbedBuilder} + */ diff --git a/packages/discord.js/src/structures/MessageComponentInteraction.js b/packages/discord.js/src/structures/MessageComponentInteraction.js index 4f16b2715..8cbe2ed24 100644 --- a/packages/discord.js/src/structures/MessageComponentInteraction.js +++ b/packages/discord.js/src/structures/MessageComponentInteraction.js @@ -107,28 +107,3 @@ module.exports = MessageComponentInteraction; * @external APIMessageButton * @see {@link https://discord.com/developers/docs/interactions/message-components#button-object} */ - -/** - * @external ButtonComponent - * @see {@link https://discord.js.org/#/docs/builders/main/class/ButtonComponent} - */ - -/** - * @external SelectMenuComponent - * @see {@link https://discord.js.org/#/docs/builders/main/class/SelectMenuComponent} - */ - -/** - * @external SelectMenuOption - * @see {@link https://discord.js.org/#/docs/builders/main/class/SelectMenuComponent} - */ - -/** - * @external ActionRow - * @see {@link https://discord.js.org/#/docs/builders/main/class/ActionRow} - */ - -/** - * @external Embed - * @see {@link https://discord.js.org/#/docs/builders/main/class/Embed} - */ diff --git a/packages/discord.js/src/structures/ModalBuilder.js b/packages/discord.js/src/structures/ModalBuilder.js new file mode 100644 index 000000000..6f8c59823 --- /dev/null +++ b/packages/discord.js/src/structures/ModalBuilder.js @@ -0,0 +1,36 @@ +'use strict'; + +const { ModalBuilder: BuildersModal, ComponentBuilder, isJSONEncodable } = require('@discordjs/builders'); +const Transformers = require('../util/Transformers'); + +/** + * Represents a modal builder. + * @extends {BuildersModal} + */ +class ModalBuilder extends BuildersModal { + constructor({ components, ...data }) { + super({ + ...Transformers.toSnakeCase(data), + components: components?.map(c => (c instanceof ComponentBuilder ? c : Transformers.toSnakeCase(c))), + }); + } + + /** + * Creates a new modal builder from JSON data + * @param {JSONEncodable|APIModalComponent} other The other data + * @returns {ModalBuilder} + */ + static from(other) { + if (isJSONEncodable(other)) { + return new this(other.toJSON()); + } + return new this(other); + } +} + +module.exports = ModalBuilder; + +/** + * @external BuildersModal + * @see {@link https://discord.js.org/#/docs/builders/main/class/ModalBuilder} + */ diff --git a/packages/discord.js/src/structures/SelectMenuBuilder.js b/packages/discord.js/src/structures/SelectMenuBuilder.js index 2cf0c1167..65688a67b 100644 --- a/packages/discord.js/src/structures/SelectMenuBuilder.js +++ b/packages/discord.js/src/structures/SelectMenuBuilder.js @@ -1,10 +1,14 @@ 'use strict'; -const { SelectMenuBuilder: BuildersSelectMenuComponent, isJSONEncodable } = require('@discordjs/builders'); +const { SelectMenuBuilder: BuildersSelectMenu, isJSONEncodable } = require('@discordjs/builders'); const Transformers = require('../util/Transformers'); const Util = require('../util/Util'); -class SelectMenuBuilder extends BuildersSelectMenuComponent { +/** + * Represents a select menu builder. + * @extends {BuildersSelectMenu} + */ +class SelectMenuBuilder extends BuildersSelectMenu { constructor({ options, ...data }) { super( Transformers.toSnakeCase({ @@ -18,8 +22,8 @@ class SelectMenuBuilder extends BuildersSelectMenuComponent { } /** - * Creates a new select menu builder from json data - * @param {JSONEncodable | APISelectMenuComponent} other The other data + * Creates a new select menu builder from JSON data + * @param {JSONEncodable|APISelectMenuComponent} other The other data * @returns {SelectMenuBuilder} */ static from(other) { @@ -31,3 +35,8 @@ class SelectMenuBuilder extends BuildersSelectMenuComponent { } module.exports = SelectMenuBuilder; + +/** + * @external BuildersSelectMenu + * @see {@link https://discord.js.org/#/docs/builders/main/class/SelectMenuBuilder} + */ diff --git a/packages/discord.js/src/structures/SelectMenuOptionBuilder.js b/packages/discord.js/src/structures/SelectMenuOptionBuilder.js index c716bb4a6..1d2a13f27 100644 --- a/packages/discord.js/src/structures/SelectMenuOptionBuilder.js +++ b/packages/discord.js/src/structures/SelectMenuOptionBuilder.js @@ -4,7 +4,8 @@ const { SelectMenuOptionBuilder: BuildersSelectMenuOption } = require('@discordj const Util = require('../util/Util'); /** - * Represents a select menu option + * Represents a select menu option builder. + * @extends {BuildersSelectMenuOption} */ class SelectMenuOptionBuilder extends BuildersSelectMenuOption { /** @@ -21,3 +22,8 @@ class SelectMenuOptionBuilder extends BuildersSelectMenuOption { } module.exports = SelectMenuOptionBuilder; + +/** + * @external BuildersSelectMenuOption + * @see {@link https://discord.js.org/#/docs/builders/main/class/SelectMenuOptionBuilder} + */ diff --git a/packages/discord.js/src/structures/TextInputBuilder.js b/packages/discord.js/src/structures/TextInputBuilder.js index b15ad9774..cdd027b6a 100644 --- a/packages/discord.js/src/structures/TextInputBuilder.js +++ b/packages/discord.js/src/structures/TextInputBuilder.js @@ -1,16 +1,20 @@ 'use strict'; -const { TextInputBuilder: BuildersTextInputComponent, isJSONEncodable } = require('@discordjs/builders'); +const { TextInputBuilder: BuildersTextInput, isJSONEncodable } = require('@discordjs/builders'); const Transformers = require('../util/Transformers'); -class TextInputBuilder extends BuildersTextInputComponent { +/** + * Represents a text input builder. + * @extends {BuildersTextInput} + */ +class TextInputBuilder extends BuildersTextInput { constructor(data) { super(Transformers.toSnakeCase(data)); } /** - * Creates a new text input builder from json data - * @param {JSONEncodable | APITextInputComponent} other The other data + * Creates a new text input builder from JSON data + * @param {JSONEncodable|APITextInputComponent} other The other data * @returns {TextInputBuilder} */ static from(other) { @@ -22,3 +26,8 @@ class TextInputBuilder extends BuildersTextInputComponent { } module.exports = TextInputBuilder; + +/** + * @external BuildersTextInput + * @see {@link https://discord.js.org/#/docs/builders/main/class/TextInputBuilder} + */ diff --git a/packages/discord.js/src/structures/TextInputComponent.js b/packages/discord.js/src/structures/TextInputComponent.js index 58ea3a13e..3cc311575 100644 --- a/packages/discord.js/src/structures/TextInputComponent.js +++ b/packages/discord.js/src/structures/TextInputComponent.js @@ -2,9 +2,15 @@ const Component = require('./Component'); +/** + * Represents a text input component. + * @extends {Component} + */ class TextInputComponent extends Component { /** * The custom id of this text input + * @type {string} + * @readonly */ get customId() { return this.data.custom_id; @@ -12,6 +18,8 @@ class TextInputComponent extends Component { /** * The value for this text input + * @type {string} + * @readonly */ get value() { return this.data.value; diff --git a/packages/discord.js/src/util/Components.js b/packages/discord.js/src/util/Components.js index 5f1d2336a..5465e1d4f 100644 --- a/packages/discord.js/src/util/Components.js +++ b/packages/discord.js/src/util/Components.js @@ -1,15 +1,17 @@ 'use strict'; -// This file contains the typedefs for camel-cased json data +// This file contains the typedefs for camel-cased JSON data const { ComponentType } = require('discord-api-types/v10'); /** * @typedef {Object} BaseComponentData * @property {ComponentType} type The type of component */ + /** * @typedef {BaseComponentData} ActionRowData * @property {ComponentData[]} components The components in this action row */ + /** * @typedef {BaseComponentData} ButtonComponentData * @property {ButtonStyle} style The style of the button @@ -19,6 +21,7 @@ const { ComponentType } = require('discord-api-types/v10'); * @property {?string} customId The custom id of the button * @property {?string} url The URL of the button */ + /** * @typedef {object} SelectMenuComponentOptionData * @property {string} label The label of the option @@ -27,6 +30,7 @@ const { ComponentType } = require('discord-api-types/v10'); * @property {?APIComponentEmoji} emoji The emoji on the option * @property {?boolean} default Whether this option is selected by default */ + /** * @typedef {BaseComponentData} SelectMenuComponentData * @property {string} customId The custom id of the select menu @@ -39,7 +43,7 @@ const { ComponentType } = require('discord-api-types/v10'); /** * @typedef {ActionRowData|ButtonComponentData|SelectMenuComponentData} MessageComponentData - / + */ /** * @typedef {BaseComponentData} TextInputComponentData @@ -95,3 +99,8 @@ const ButtonComponent = require('../structures/ButtonComponent'); const Component = require('../structures/Component'); const SelectMenuComponent = require('../structures/SelectMenuComponent'); const TextInputComponent = require('../structures/TextInputComponent'); + +/** + * @external JSONEncodable + * @see {@link https://discord.js.org/#/docs/builders/main/typedef/JSONEncodable} + */ diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 0e828404e..510b1f6e3 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -27,6 +27,7 @@ import { underscore, userMention, ModalActionRowComponentBuilder, + ModalBuilder as BuildersModal, } from '@discordjs/builders'; import { Collection } from '@discordjs/collection'; import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest'; @@ -243,6 +244,11 @@ export class ActionRowBuilder< type?: ComponentType.ActionRow; }), ); + public static from( + other: + | JSONEncodable> + | APIActionRowComponent, + ): ActionRowBuilder; } export type MessageActionRowComponent = ButtonComponent | SelectMenuComponent; @@ -581,6 +587,11 @@ export class SelectMenuOptionBuilder extends BuildersSelectMenuOption { public setEmoji(emoji: ComponentEmojiResolvable): this; } +export class ModalBuilder extends BuildersModal { + public constructor(data?: ModalData | APIModalComponent); + public static from(other: JSONEncodable | APIModalComponent): ModalBuilder; +} + export class TextInputBuilder extends BuilderTextInputComponent { public constructor(data?: TextInputComponentData | APITextInputComponent); public static from(other: JSONEncodable | APITextInputComponent): TextInputBuilder; @@ -4865,7 +4876,7 @@ export interface TextInputComponentData extends BaseComponentData { export interface ModalData { customId: string; title: string; - components: ActionRowData[]; + components: (ActionRow | ActionRowData)[]; } export type MessageTarget = @@ -5385,14 +5396,13 @@ export { WebhookType, } from 'discord-api-types/v10'; export { + UnsafeEmbedBuilder, + UnsafeModalBuilder, + UnsafeTextInputBuilder, UnsafeButtonBuilder, UnsafeSelectMenuBuilder, UnsafeSelectMenuOptionBuilder, MessageActionRowComponentBuilder, ModalActionRowComponentBuilder, - UnsafeEmbedBuilder, - ModalBuilder, - UnsafeModalBuilder, - UnsafeTextInputBuilder, } from '@discordjs/builders'; export { DiscordAPIError, HTTPError, RateLimitError } from '@discordjs/rest';