From 328501bd8ee343edfd3492f8ba81d5c57006d496 Mon Sep 17 00:00:00 2001 From: Shino Date: Wed, 21 Jul 2021 17:22:47 -0400 Subject: [PATCH] refactor(CommandInteractionOptionResolver): add readonly data property (#6156) --- src/structures/CommandInteraction.js | 2 +- .../CommandInteractionOptionResolver.js | 40 ++++++++++++------- typings/index.d.ts | 3 +- typings/index.ts | 1 + 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/structures/CommandInteraction.js b/src/structures/CommandInteraction.js index e8d59f3d5243..cc546d6353a8 100644 --- a/src/structures/CommandInteraction.js +++ b/src/structures/CommandInteraction.js @@ -52,7 +52,7 @@ class CommandInteraction extends Interaction { */ this.options = new CommandInteractionOptionResolver( this.client, - data.data.options?.map(option => this.transformOption(option, data.data.resolved)), + data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [], ); /** diff --git a/src/structures/CommandInteractionOptionResolver.js b/src/structures/CommandInteractionOptionResolver.js index cddc1ead9e1d..b317f32d588d 100644 --- a/src/structures/CommandInteractionOptionResolver.js +++ b/src/structures/CommandInteractionOptionResolver.js @@ -15,13 +15,6 @@ class CommandInteractionOptionResolver { */ Object.defineProperty(this, 'client', { value: client }); - /** - * The interaction options array. - * @type {CommandInteractionOption[]} - * @private - */ - this._options = options ?? []; - /** * The name of the sub-command group. * @type {?string} @@ -35,14 +28,33 @@ class CommandInteractionOptionResolver { * @private */ this._subCommand = null; - if (this._options[0]?.type === 'SUB_COMMAND_GROUP') { - this._group = this._options[0].name; - this._options = this._options[0].options ?? []; + + /** + * The bottom-level options for the interaction. + * If there is a sub-command (or sub-command and group), this is the options for the sub-command. + * @type {CommandInteractionOption[]} + * @private + */ + this._hoistedOptions = options; + + // Hoist sub-command group if present + if (this._hoistedOptions[0]?.type === 'SUB_COMMAND_GROUP') { + this._group = this._hoistedOptions[0].name; + this._hoistedOptions = this._hoistedOptions[0].options ?? []; } - if (this._options[0]?.type === 'SUB_COMMAND') { - this._subCommand = this._options[0].name; - this._options = this._options[0].options ?? []; + // Hoist sub-command if present + if (this._hoistedOptions[0]?.type === 'SUB_COMMAND') { + this._subCommand = this._hoistedOptions[0].name; + this._hoistedOptions = this._hoistedOptions[0].options ?? []; } + + /** + * The interaction options array. + * @name CommandInteractionOptionResolver#data + * @type {ReadonlyArray} + * @readonly + */ + Object.defineProperty(this, 'data', { value: Object.freeze([...options]) }); } /** @@ -52,7 +64,7 @@ class CommandInteractionOptionResolver { * @returns {?CommandInteractionOption} The option, if found. */ get(name, required = false) { - const option = this._options.find(opt => opt.name === name); + const option = this._hoistedOptions.find(opt => opt.name === name); if (!option) { if (required) { throw new TypeError('COMMAND_INTERACTION_OPTION_NOT_FOUND', name); diff --git a/typings/index.d.ts b/typings/index.d.ts index 00a1f4d16bc2..b18c2c8a2d88 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -427,8 +427,9 @@ export class CommandInteraction extends Interaction { export class CommandInteractionOptionResolver { public constructor(client: Client, options: CommandInteractionOption[]); public readonly client: Client; - private _options: CommandInteractionOption[]; + public readonly data: readonly CommandInteractionOption[]; private _group: string | null; + private _hoistedOptions: CommandInteractionOption[]; private _subCommand: string | null; private _getTypedOption( name: string, diff --git a/typings/index.ts b/typings/index.ts index e878de584b69..c4668555cb76 100644 --- a/typings/index.ts +++ b/typings/index.ts @@ -656,6 +656,7 @@ client.on('interactionCreate', async interaction => { if (interaction.isCommand()) { assertType(interaction); assertType(interaction.options); + assertType(interaction.options.data); const optionalOption = interaction.options.get('name'); const requiredOption = interaction.options.get('name', true);