diff --git a/src/client/Client.js b/src/client/Client.js
index 763379d85b63..95c6f77594ed 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -10,6 +10,7 @@ const ChannelManager = require('../managers/ChannelManager');
const GuildManager = require('../managers/GuildManager');
const UserManager = require('../managers/UserManager');
const ShardClientUtil = require('../sharding/ShardClientUtil');
+const ClientPresence = require('../structures/ClientPresence');
const GuildPreview = require('../structures/GuildPreview');
const GuildTemplate = require('../structures/GuildTemplate');
const Invite = require('../structures/Invite');
@@ -22,7 +23,6 @@ const DataResolver = require('../util/DataResolver');
const Intents = require('../util/Intents');
const Options = require('../util/Options');
const Permissions = require('../util/Permissions');
-const Structures = require('../util/Structures');
/**
* The main hub for interacting with the Discord API, and the starting point for any bot.
@@ -119,7 +119,6 @@ class Client extends BaseClient {
*/
this.channels = new ChannelManager(this);
- const ClientPresence = Structures.get('ClientPresence');
/**
* The presence of the Client
* @private
diff --git a/src/client/actions/InteractionCreate.js b/src/client/actions/InteractionCreate.js
index 3938af811692..85072d059e2b 100644
--- a/src/client/actions/InteractionCreate.js
+++ b/src/client/actions/InteractionCreate.js
@@ -1,8 +1,10 @@
'use strict';
const Action = require('./Action');
+const ButtonInteraction = require('../../structures/ButtonInteraction');
+const CommandInteraction = require('../../structures/CommandInteraction');
+const SelectMenuInteraction = require('../../structures/SelectMenuInteraction');
const { Events, InteractionTypes, MessageComponentTypes } = require('../../util/Constants');
-const Structures = require('../../util/Structures');
let deprecationEmitted = false;
@@ -16,15 +18,15 @@ class InteractionCreateAction extends Action {
let InteractionType;
switch (data.type) {
case InteractionTypes.APPLICATION_COMMAND:
- InteractionType = Structures.get('CommandInteraction');
+ InteractionType = CommandInteraction;
break;
case InteractionTypes.MESSAGE_COMPONENT:
switch (data.data.component_type) {
case MessageComponentTypes.BUTTON:
- InteractionType = Structures.get('ButtonInteraction');
+ InteractionType = ButtonInteraction;
break;
case MessageComponentTypes.SELECT_MENU:
- InteractionType = Structures.get('SelectMenuInteraction');
+ InteractionType = SelectMenuInteraction;
break;
default:
client.emit(
diff --git a/src/client/actions/VoiceStateUpdate.js b/src/client/actions/VoiceStateUpdate.js
index e135bbd89187..a01191a378be 100644
--- a/src/client/actions/VoiceStateUpdate.js
+++ b/src/client/actions/VoiceStateUpdate.js
@@ -1,15 +1,14 @@
'use strict';
const Action = require('./Action');
+const VoiceState = require('../../structures/VoiceState');
const { Events } = require('../../util/Constants');
-const Structures = require('../../util/Structures');
class VoiceStateUpdate extends Action {
handle(data) {
const client = this.client;
const guild = client.guilds.cache.get(data.guild_id);
if (guild) {
- const VoiceState = Structures.get('VoiceState');
// Update the state
const oldState =
guild.voiceStates.cache.get(data.user_id)?._clone() ?? new VoiceState(guild, { user_id: data.user_id });
diff --git a/src/index.js b/src/index.js
index 2ccdff2749a5..d1643d46421c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -26,7 +26,6 @@ module.exports = {
Options: require('./util/Options'),
Permissions: require('./util/Permissions'),
SnowflakeUtil: require('./util/SnowflakeUtil'),
- Structures: require('./util/Structures'),
SystemChannelFlags: require('./util/SystemChannelFlags'),
ThreadMemberFlags: require('./util/ThreadMemberFlags'),
UserFlags: require('./util/UserFlags'),
diff --git a/src/managers/DataManager.js b/src/managers/DataManager.js
index cd304d956347..9c63a2327fea 100644
--- a/src/managers/DataManager.js
+++ b/src/managers/DataManager.js
@@ -3,8 +3,6 @@
const BaseManager = require('./BaseManager');
const { Error } = require('../errors');
-let Structures;
-
/**
* Manages the API methods of a data model along with a collection of instances.
* @extends {BaseManager}
@@ -14,8 +12,6 @@ class DataManager extends BaseManager {
constructor(client, holds) {
super(client);
- if (!Structures) Structures = require('../util/Structures');
-
/**
* The data structure belonging to this manager.
* @name DataManager#holds
@@ -23,7 +19,7 @@ class DataManager extends BaseManager {
* @private
* @readonly
*/
- Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds });
+ Object.defineProperty(this, 'holds', { value: holds });
}
/**
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
index 817f35e320c3..e0e291d3a9a0 100644
--- a/src/structures/Channel.js
+++ b/src/structures/Channel.js
@@ -1,6 +1,14 @@
'use strict';
const Base = require('./Base');
+let CategoryChannel;
+let DMChannel;
+let NewsChannel;
+let StageChannel;
+let StoreChannel;
+let TextChannel;
+let ThreadChannel;
+let VoiceChannel;
const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants');
const SnowflakeUtil = require('../util/SnowflakeUtil');
@@ -120,11 +128,18 @@ class Channel extends Base {
}
static create(client, data, guild) {
- const Structures = require('../util/Structures');
+ if (!CategoryChannel) CategoryChannel = require('./CategoryChannel');
+ if (!DMChannel) DMChannel = require('./DMChannel');
+ if (!NewsChannel) NewsChannel = require('./NewsChannel');
+ if (!StageChannel) StageChannel = require('./StageChannel');
+ if (!StoreChannel) StoreChannel = require('./StoreChannel');
+ if (!TextChannel) TextChannel = require('./TextChannel');
+ if (!ThreadChannel) ThreadChannel = require('./ThreadChannel');
+ if (!VoiceChannel) VoiceChannel = require('./VoiceChannel');
+
let channel;
if (!data.guild_id && !guild) {
if ((data.recipients && data.type !== ChannelTypes.GROUP) || data.type === ChannelTypes.DM) {
- const DMChannel = Structures.get('DMChannel');
channel = new DMChannel(client, data);
} else if (data.type === ChannelTypes.GROUP) {
const PartialGroupDMChannel = require('./PartialGroupDMChannel');
@@ -136,39 +151,32 @@ class Channel extends Base {
if (guild) {
switch (data.type) {
case ChannelTypes.TEXT: {
- const TextChannel = Structures.get('TextChannel');
channel = new TextChannel(guild, data);
break;
}
case ChannelTypes.VOICE: {
- const VoiceChannel = Structures.get('VoiceChannel');
channel = new VoiceChannel(guild, data);
break;
}
case ChannelTypes.CATEGORY: {
- const CategoryChannel = Structures.get('CategoryChannel');
channel = new CategoryChannel(guild, data);
break;
}
case ChannelTypes.NEWS: {
- const NewsChannel = Structures.get('NewsChannel');
channel = new NewsChannel(guild, data);
break;
}
case ChannelTypes.STORE: {
- const StoreChannel = Structures.get('StoreChannel');
channel = new StoreChannel(guild, data);
break;
}
case ChannelTypes.STAGE: {
- const StageChannel = Structures.get('StageChannel');
channel = new StageChannel(guild, data);
break;
}
case ChannelTypes.NEWS_THREAD:
case ChannelTypes.PUBLIC_THREAD:
case ChannelTypes.PRIVATE_THREAD: {
- const ThreadChannel = Structures.get('ThreadChannel');
channel = new ThreadChannel(guild, data);
channel.parent?.threads.cache.set(channel.id, channel);
break;
diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js
index 7321ee1782a0..3949c80c8449 100644
--- a/src/structures/ClientUser.js
+++ b/src/structures/ClientUser.js
@@ -1,13 +1,13 @@
'use strict';
+const User = require('./User');
const DataResolver = require('../util/DataResolver');
-const Structures = require('../util/Structures');
/**
* Represents the logged in client's Discord user.
* @extends {User}
*/
-class ClientUser extends Structures.get('User') {
+class ClientUser extends User {
constructor(client, data) {
super(client, data);
this._typing = new Map();
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index 7bbaf4c89418..01bfdc31ab33 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -1,11 +1,12 @@
'use strict';
const Base = require('./Base');
+const { Presence } = require('./Presence');
+const VoiceState = require('./VoiceState');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { Error } = require('../errors');
const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
const Permissions = require('../util/Permissions');
-let Structures;
/**
* Represents a member of a guild on Discord.
@@ -130,8 +131,6 @@ class GuildMember extends Base {
* @readonly
*/
get voice() {
- if (!Structures) Structures = require('../util/Structures');
- const VoiceState = Structures.get('VoiceState');
return this.guild.voiceStates.cache.get(this.id) ?? new VoiceState(this.guild, { user_id: this.id });
}
@@ -159,8 +158,6 @@ class GuildMember extends Base {
* @readonly
*/
get presence() {
- if (!Structures) Structures = require('../util/Structures');
- const Presence = Structures.get('Presence');
return (
this.guild.presences.cache.get(this.id) ??
new Presence(this.client, {
diff --git a/src/structures/User.js b/src/structures/User.js
index d336a1c6215c..a48de5f24160 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -1,13 +1,12 @@
'use strict';
const Base = require('./Base');
+const { Presence } = require('./Presence');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { Error } = require('../errors');
const SnowflakeUtil = require('../util/SnowflakeUtil');
const UserFlags = require('../util/UserFlags');
-let Structures;
-
/**
* Represents a user on Discord.
* @implements {TextBasedChannel}
@@ -153,8 +152,6 @@ class User extends Base {
for (const guild of this.client.guilds.cache.values()) {
if (guild.presences.cache.has(this.id)) return guild.presences.cache.get(this.id);
}
- if (!Structures) Structures = require('../util/Structures');
- const Presence = Structures.get('Presence');
return new Presence(this.client, { user: { id: this.id } });
}
diff --git a/src/util/Structures.js b/src/util/Structures.js
deleted file mode 100644
index 33343e7e1294..000000000000
--- a/src/util/Structures.js
+++ /dev/null
@@ -1,122 +0,0 @@
-'use strict';
-
-/**
- * An extendable structure:
- * * **`GuildEmoji`**
- * * **`DMChannel`**
- * * **`TextChannel`**
- * * **`VoiceChannel`**
- * * **`CategoryChannel`**
- * * **`NewsChannel`**
- * * **`StoreChannel`**
- * * **`StageChannel`**
- * * **`ThreadChannel`**
- * * **`GuildMember`**
- * * **`ThreadMember`**
- * * **`Guild`**
- * * **`Message`**
- * * **`MessageReaction`**
- * * **`Presence`**
- * * **`ClientPresence`**
- * * **`VoiceState`**
- * * **`Role`**
- * * **`User`**
- * * **`CommandInteraction`**
- * * **`ButtonInteraction`**
- * * **`StageInstance`**
- * * **`SelectMenuInteraction`**
- * @typedef {string} ExtendableStructure
- */
-
-/**
- * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}.
- */
-class Structures extends null {
- /**
- * Retrieves a structure class.
- * @param {string} structure Name of the structure to retrieve
- * @returns {Function}
- */
- static get(structure) {
- if (typeof structure === 'string') return structures[structure];
- throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`);
- }
-
- /**
- * Extends a structure.
- * Make sure to extend all structures before instantiating your client.
- * Extending after doing so may not work as expected.
- * @param {ExtendableStructure} structure Name of the structure class to extend
- * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the
- * extended class/prototype
- * @returns {Function} Extended class/prototype returned from the extender
- * @example
- * const { Structures } = require('discord.js');
- *
- * Structures.extend('Guild', Guild => {
- * class CoolGuild extends Guild {
- * constructor(client, data) {
- * super(client, data);
- * this.cool = true;
- * }
- * }
- *
- * return CoolGuild;
- * });
- */
- static extend(structure, extender) {
- if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`);
- if (typeof extender !== 'function') {
- const received = `(received ${typeof extender})`;
- throw new TypeError(
- `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`,
- );
- }
-
- const extended = extender(structures[structure]);
- if (typeof extended !== 'function') {
- const received = `(received ${typeof extended})`;
- throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`);
- }
-
- if (!(extended.prototype instanceof structures[structure])) {
- const prototype = Object.getPrototypeOf(extended);
- const received = `${extended.name ?? 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`;
- throw new Error(
- 'The class/prototype returned from the extender function must extend the existing structure class/prototype' +
- ` (received function ${received}; expected extension of ${structures[structure].name}).`,
- );
- }
-
- structures[structure] = extended;
- return extended;
- }
-}
-
-const structures = {
- GuildEmoji: require('../structures/GuildEmoji'),
- DMChannel: require('../structures/DMChannel'),
- TextChannel: require('../structures/TextChannel'),
- VoiceChannel: require('../structures/VoiceChannel'),
- CategoryChannel: require('../structures/CategoryChannel'),
- NewsChannel: require('../structures/NewsChannel'),
- StoreChannel: require('../structures/StoreChannel'),
- StageChannel: require('../structures/StageChannel'),
- ThreadChannel: require('../structures/ThreadChannel'),
- GuildMember: require('../structures/GuildMember'),
- ThreadMember: require('../structures/ThreadMember'),
- Guild: require('../structures/Guild'),
- Message: require('../structures/Message'),
- MessageReaction: require('../structures/MessageReaction'),
- Presence: require('../structures/Presence').Presence,
- ClientPresence: require('../structures/ClientPresence'),
- VoiceState: require('../structures/VoiceState'),
- Role: require('../structures/Role'),
- User: require('../structures/User'),
- CommandInteraction: require('../structures/CommandInteraction'),
- ButtonInteraction: require('../structures/ButtonInteraction'),
- SelectMenuInteraction: require('../structures/SelectMenuInteraction'),
- StageInstance: require('../structures/StageInstance'),
-};
-
-module.exports = Structures;
diff --git a/typings/index.d.ts b/typings/index.d.ts
index 3d2a68890e45..b16f8e0287a2 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -1887,20 +1887,6 @@ declare module 'discord.js' {
public type: 'store';
}
- export class Structures extends null {
- private constructor();
- public static get(structure: K): Extendable[K];
- public static get(structure: string): (...args: any[]) => void;
- public static extend(
- structure: K,
- extender: (baseClass: Extendable[K]) => T,
- ): T;
- public static extend void>(
- structure: string,
- extender: (baseClass: typeof Function) => T,
- ): T;
- }
-
export class SystemChannelFlags extends BitField {
public static FLAGS: Record;
public static resolve(bit?: BitFieldResolvable): number;
@@ -2668,7 +2654,11 @@ declare module 'discord.js' {
public delete(channel: StageChannel | Snowflake): Promise;
}
- export class ThreadManager extends CachedManager {
+ export class ThreadManager extends CachedManager<
+ Snowflake,
+ ThreadChannel,
+ ThreadChannelResolvable
+ > {
constructor(channel: TextChannel | NewsChannel, iterable?: Iterable);
public channel: TextChannel | NewsChannel;
public create(options: ThreadCreateOptions): Promise;
@@ -3319,29 +3309,6 @@ declare module 'discord.js' {
type ExplicitContentFilterLevel = keyof typeof ExplicitContentFilterLevels;
- interface Extendable {
- GuildEmoji: typeof GuildEmoji;
- DMChannel: typeof DMChannel;
- TextChannel: typeof TextChannel;
- VoiceChannel: typeof VoiceChannel;
- CategoryChannel: typeof CategoryChannel;
- NewsChannel: typeof NewsChannel;
- StoreChannel: typeof StoreChannel;
- ThreadChannel: typeof ThreadChannel;
- GuildMember: typeof GuildMember;
- ThreadMember: typeof ThreadMember;
- Guild: typeof Guild;
- Message: typeof Message;
- MessageReaction: typeof MessageReaction;
- Presence: typeof Presence;
- VoiceState: typeof VoiceState;
- Role: typeof Role;
- User: typeof User;
- CommandInteraction: typeof CommandInteraction;
- ButtonInteraction: typeof ButtonInteraction;
- SelectMenuInteraction: typeof SelectMenuInteraction;
- }
-
interface FetchApplicationCommandOptions extends BaseFetchOptions {
guildID?: Snowflake;
}