From 7d4f2bf7d64bf80631885083e5a2404ef06ebf9d Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Mon, 20 Jan 2025 00:55:40 +0100 Subject: [PATCH 1/5] refactor!: consolidate parameters into a single `options` object Co-authored-by: Micah Benac --- .../src/managers/ApplicationCommandManager.js | 16 +++++++------- packages/discord.js/typings/index.d.ts | 21 ++++++++++--------- packages/discord.js/typings/index.test-d.ts | 9 ++++---- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index 29e770aa553b..c9a889c30681 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -81,6 +81,7 @@ class ApplicationCommandManager extends CachedManager { /** * Options used to fetch Application Commands from Discord * @typedef {BaseFetchOptions} FetchApplicationCommandOptions + * @property {Snowflake} [id] The command's id to fetch * @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached * @property {Locale} [locale] The locale to use when fetching this command * @property {boolean} [withLocalizations] Whether to fetch all localization data @@ -88,12 +89,11 @@ class ApplicationCommandManager extends CachedManager { /** * Obtains one or multiple application commands from Discord, or the cache if it's already available. - * @param {Snowflake|FetchApplicationCommandOptions} [id] Options for fetching application command(s) - * @param {FetchApplicationCommandOptions} [options] Additional options for this fetch + * @param {FetchApplicationCommandOptions} [options] Options for fetching application command(s) * @returns {Promise>} * @example * // Fetch a single command - * client.application.commands.fetch('123456789012345678') + * client.application.commands.fetch({ id: '123456789012345678' }) * .then(command => console.log(`Fetched command ${command.name}`)) * .catch(console.error); * @example @@ -102,10 +102,12 @@ class ApplicationCommandManager extends CachedManager { * .then(commands => console.log(`Fetched ${commands.size} commands`)) * .catch(console.error); */ - async fetch(id, { guildId, cache = true, force = false, locale, withLocalizations } = {}) { - if (typeof id === 'object') { - ({ guildId, cache = true, locale, withLocalizations } = id); - } else if (id) { + async fetch(options = {}) { + if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true); + + const { cache = true, force = false, guildId, id, locale, withLocalizations } = options; + + if (id) { if (!force) { const existing = this.cache.get(id); if (existing) return existing; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 0ed841fe6bba..358d878418ad 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3913,14 +3913,16 @@ export class ApplicationCommandManager< guildId: Snowflake, ): Promise; public fetch( - id: Snowflake, - options: FetchApplicationCommandOptions & { guildId: Snowflake }, + options: Omit & { id: Snowflake }, + ): Promise; + public fetch( + options: FetchApplicationCommandOptions & { id: Snowflake; guildId: Snowflake }, ): Promise; - public fetch(options: FetchApplicationCommandOptions): Promise>; - public fetch(id: Snowflake, options?: FetchApplicationCommandOptions): Promise; public fetch( - id?: Snowflake, - options?: FetchApplicationCommandOptions, + options: Omit & { guildId: Snowflake }, + ): Promise>; + public fetch( + options?: Omit, ): Promise>; public set( commands: readonly ApplicationCommandDataResolvable[], @@ -4089,11 +4091,9 @@ export class GuildApplicationCommandManager extends ApplicationCommandManager, ): Promise; - public fetch(id: Snowflake, options?: FetchGuildApplicationCommandFetchOptions): Promise; - public fetch(options: FetchGuildApplicationCommandFetchOptions): Promise>; + public fetch(options: FetchGuildApplicationCommandFetchOptions & { id: Snowflake }): Promise; public fetch( - id?: undefined, - options?: FetchGuildApplicationCommandFetchOptions, + options?: Omit, ): Promise>; public set(commands: readonly ApplicationCommandDataResolvable[]): Promise>; } @@ -5461,6 +5461,7 @@ export type EmojiIdentifierResolvable = export type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji | ApplicationEmoji; export interface FetchApplicationCommandOptions extends BaseFetchOptions { + id?: Snowflake; guildId?: Snowflake; locale?: Locale; withLocalizations?: boolean; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index bda6ff0893ea..e43745bdaf6e 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -711,9 +711,9 @@ client.on('clientReady', async client => { ); // Test command manager methods - const globalCommand = await client.application?.commands.fetch(globalCommandId); - const guildCommandFromGlobal = await client.application?.commands.fetch(guildCommandId, { guildId: testGuildId }); - const guildCommandFromGuild = await client.guilds.cache.get(testGuildId)?.commands.fetch(guildCommandId); + const globalCommand = await client.application?.commands.fetch({ id: globalCommandId }); + const guildCommandFromGlobal = await client.application?.commands.fetch({ id: guildCommandId, guildId: testGuildId }); + const guildCommandFromGuild = await client.guilds.cache.get(testGuildId)?.commands.fetch({ id: guildCommandId }); await client.application?.commands.create(slashCommandBuilder); await client.application?.commands.create(contextMenuCommandBuilder); @@ -1589,9 +1589,8 @@ declare const autoModerationRuleManager: AutoModerationRuleManager; } declare const guildApplicationCommandManager: GuildApplicationCommandManager; +expectType>(guildApplicationCommandManager.fetch({ id: '0' })); expectType>>(guildApplicationCommandManager.fetch()); -expectType>>(guildApplicationCommandManager.fetch(undefined, {})); -expectType>(guildApplicationCommandManager.fetch('0')); declare const categoryChannelChildManager: CategoryChannelChildManager; { From b6c00c4dca1121bb36d840639b1cc08f1290cdf0 Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Thu, 23 Jan 2025 00:32:55 +0100 Subject: [PATCH 2/5] refactor: `id` overload --- .../src/managers/ApplicationCommandManager.js | 44 ++++++++++++++----- packages/discord.js/typings/index.d.ts | 6 ++- packages/discord.js/typings/index.test-d.ts | 3 +- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index c9a889c30681..7cc498ccd91a 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -89,39 +89,59 @@ class ApplicationCommandManager extends CachedManager { /** * Obtains one or multiple application commands from Discord, or the cache if it's already available. - * @param {FetchApplicationCommandOptions} [options] Options for fetching application command(s) + * @param {Snowflake|FetchApplicationCommandOptions} [options] Options for fetching application command(s) * @returns {Promise>} * @example * // Fetch a single command - * client.application.commands.fetch({ id: '123456789012345678' }) + * client.application.commands.fetch('123456789012345678') * .then(command => console.log(`Fetched command ${command.name}`)) * .catch(console.error); * @example * // Fetch all commands + * client.application.commands.fetch() + * .then(commands => console.log(`Fetched ${commands.size} commands`)) + * .catch(console.error); + * @example + * // Fetch all commands in a guild * guild.commands.fetch() * .then(commands => console.log(`Fetched ${commands.size} commands`)) * .catch(console.error); + * @example + * // Fetch a single command without checking cache + * guild.commands.fetch({ id: '123456789012345678', force: true }) + * .then(command => console.log(`Fetched command ${command.name}`)) + * .catch(console.error) */ - async fetch(options = {}) { - if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true); + async fetch(options) { + if (!options) return this._fetchMany(); - const { cache = true, force = false, guildId, id, locale, withLocalizations } = options; + const { cache, force, guildId, id, locale, withLocalizations } = options; - if (id) { - if (!force) { - const existing = this.cache.get(id); - if (existing) return existing; - } - const command = await this.client.rest.get(this.commandPath({ id, guildId })); - return this._add(command, cache); + if (typeof options === 'string' || typeof id === 'string') { + return this._fetchSingle({ cache, force, guildId, id: options.id ?? options }); } + return this._fetchMany({ cache, guildId, locale, withLocalizations }); + } + + async _fetchSingle({ cache, force = false, guildId, id }) { + if (!force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + + const command = await this.client.rest.get(this.commandPath({ id, guildId })); + return this._add(command, cache); + } + + async _fetchMany({ cache, guildId, locale, withLocalizations } = {}) { const data = await this.client.rest.get(this.commandPath({ guildId }), { headers: { 'X-Discord-Locale': locale, }, query: makeURLSearchParams({ with_localizations: withLocalizations }), }); + return data.reduce((coll, command) => coll.set(command.id, this._add(command, cache, guildId)), new Collection()); } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 358d878418ad..ac4365e8fe0e 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3913,7 +3913,7 @@ export class ApplicationCommandManager< guildId: Snowflake, ): Promise; public fetch( - options: Omit & { id: Snowflake }, + options: Snowflake | (Omit & { id: Snowflake }), ): Promise; public fetch( options: FetchApplicationCommandOptions & { id: Snowflake; guildId: Snowflake }, @@ -4091,7 +4091,9 @@ export class GuildApplicationCommandManager extends ApplicationCommandManager, ): Promise; - public fetch(options: FetchGuildApplicationCommandFetchOptions & { id: Snowflake }): Promise; + public fetch( + options: Snowflake | (FetchGuildApplicationCommandFetchOptions & { id: Snowflake }), + ): Promise; public fetch( options?: Omit, ): Promise>; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index e43745bdaf6e..b77a4f4acdb3 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -711,7 +711,7 @@ client.on('clientReady', async client => { ); // Test command manager methods - const globalCommand = await client.application?.commands.fetch({ id: globalCommandId }); + const globalCommand = await client.application?.commands.fetch(globalCommandId); const guildCommandFromGlobal = await client.application?.commands.fetch({ id: guildCommandId, guildId: testGuildId }); const guildCommandFromGuild = await client.guilds.cache.get(testGuildId)?.commands.fetch({ id: guildCommandId }); @@ -1589,6 +1589,7 @@ declare const autoModerationRuleManager: AutoModerationRuleManager; } declare const guildApplicationCommandManager: GuildApplicationCommandManager; +expectType>(guildApplicationCommandManager.fetch('0')); expectType>(guildApplicationCommandManager.fetch({ id: '0' })); expectType>>(guildApplicationCommandManager.fetch()); From 0c013aa6d3e20ef0a5fe52a72db82a7cbbc8fcf4 Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Thu, 23 Jan 2025 01:09:54 +0100 Subject: [PATCH 3/5] refactor: use destructured `id` instead of `options.id` --- packages/discord.js/src/managers/ApplicationCommandManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index 7cc498ccd91a..1187e5d2b25f 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -118,7 +118,7 @@ class ApplicationCommandManager extends CachedManager { const { cache, force, guildId, id, locale, withLocalizations } = options; if (typeof options === 'string' || typeof id === 'string') { - return this._fetchSingle({ cache, force, guildId, id: options.id ?? options }); + return this._fetchSingle({ cache, force, guildId, id: id ?? options }); } return this._fetchMany({ cache, guildId, locale, withLocalizations }); From 59b72527358db4cfcdf94b1ca143c9374f47ba34 Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Sat, 25 Jan 2025 20:48:50 +0100 Subject: [PATCH 4/5] fix: destructuring properties from string --- .../discord.js/src/managers/ApplicationCommandManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/discord.js/src/managers/ApplicationCommandManager.js b/packages/discord.js/src/managers/ApplicationCommandManager.js index 1187e5d2b25f..2498eca7219a 100644 --- a/packages/discord.js/src/managers/ApplicationCommandManager.js +++ b/packages/discord.js/src/managers/ApplicationCommandManager.js @@ -115,11 +115,11 @@ class ApplicationCommandManager extends CachedManager { async fetch(options) { if (!options) return this._fetchMany(); + if (typeof options === 'string') return this._fetchSingle({ id: options }); + const { cache, force, guildId, id, locale, withLocalizations } = options; - if (typeof options === 'string' || typeof id === 'string') { - return this._fetchSingle({ cache, force, guildId, id: id ?? options }); - } + if (id) return this._fetchSingle({ cache, force, guildId, id }); return this._fetchMany({ cache, guildId, locale, withLocalizations }); } From 583de9b77f7ed3d640ae3f6a65e38fb335528bcd Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Sat, 25 Jan 2025 21:35:20 +0100 Subject: [PATCH 5/5] types: merge overloads Co-authored-by: Almeida --- packages/discord.js/typings/index.d.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index ac4365e8fe0e..ffb3722b2b6d 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -3919,10 +3919,7 @@ export class ApplicationCommandManager< options: FetchApplicationCommandOptions & { id: Snowflake; guildId: Snowflake }, ): Promise; public fetch( - options: Omit & { guildId: Snowflake }, - ): Promise>; - public fetch( - options?: Omit, + options?: Omit, ): Promise>; public set( commands: readonly ApplicationCommandDataResolvable[],