diff --git a/packages/discord.js/src/structures/MessagePayload.js b/packages/discord.js/src/structures/MessagePayload.js index 8b5388c71..3fe368765 100644 --- a/packages/discord.js/src/structures/MessagePayload.js +++ b/packages/discord.js/src/structures/MessagePayload.js @@ -1,13 +1,20 @@ 'use strict'; const { Buffer } = require('node:buffer'); -const { isJSONEncodable } = require('@discordjs/util'); +const { isJSONEncodable, lazy } = require('@discordjs/util'); const { DiscordSnowflake } = require('@sapphire/snowflake'); const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors/index.js'); const { resolveFile } = require('../util/DataResolver.js'); const { MessageFlagsBitField } = require('../util/MessageFlagsBitField.js'); const { findName, verifyString, resolvePartialEmoji } = require('../util/Util.js'); +// Fixes circular dependencies. +const getWebhook = lazy(() => require('./Webhook.js').Webhook); +const getUser = lazy(() => require('./User.js').User); +const getGuildMember = lazy(() => require('./GuildMember.js').GuildMember); +const getMessage = lazy(() => require('./Message.js').Message); +const getMessageManager = lazy(() => require('../managers/MessageManager.js').MessageManager); + /** * Represents a message to be sent to the API. */ @@ -53,8 +60,7 @@ class MessagePayload { * @readonly */ get isWebhook() { - const { Webhook } = require('./Webhook.js'); - return this.target instanceof Webhook; + return this.target instanceof getWebhook(); } /** @@ -64,9 +70,7 @@ class MessagePayload { * @readonly */ get isUser() { - const { User } = require('./User.js'); - const { GuildMember } = require('./GuildMember.js'); - return this.target instanceof User || this.target instanceof GuildMember; + return this.target instanceof getUser() || this.target instanceof getGuildMember(); } /** @@ -76,8 +80,7 @@ class MessagePayload { * @readonly */ get isMessage() { - const { Message } = require('./Message.js'); - return this.target instanceof Message; + return this.target instanceof getMessage(); } /** @@ -87,8 +90,7 @@ class MessagePayload { * @readonly */ get isMessageManager() { - const { MessageManager } = require('../managers/MessageManager.js'); - return this.target instanceof MessageManager; + return this.target instanceof getMessageManager(); } /** diff --git a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js index 473c96467..fb752ab92 100644 --- a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js +++ b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -1,14 +1,17 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); +const { lazy } = require('@discordjs/util'); const { DiscordSnowflake } = require('@sapphire/snowflake'); const { InteractionType, Routes } = require('discord-api-types/v10'); const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../../errors/index.js'); const { MaxBulkDeletableMessageAge } = require('../../util/Constants.js'); const { InteractionCollector } = require('../InteractionCollector.js'); -// eslint-disable-next-line import-x/order const { MessageCollector } = require('../MessageCollector.js'); +// Fixes circular dependencies. +const getGuildMessageManager = lazy(() => require('../../managers/GuildMessageManager.js').GuildMessageManager); + /** * Interface for classes that have text-channel-like features. * @@ -21,8 +24,7 @@ class TextBasedChannel { * * @type {GuildMessageManager} */ - // eslint-disable-next-line no-use-before-define - this.messages = new GuildMessageManager(this); + this.messages = new (getGuildMessageManager())(this); /** * The channel's last message id, if one was sent @@ -427,7 +429,3 @@ class TextBasedChannel { } exports.TextBasedChannel = TextBasedChannel; - -// Fixes Circular -// eslint-disable-next-line import-x/order -const { GuildMessageManager } = require('../../managers/GuildMessageManager.js'); diff --git a/packages/discord.js/src/util/Components.js b/packages/discord.js/src/util/Components.js index 7f8b74ca2..5a1278659 100644 --- a/packages/discord.js/src/util/Components.js +++ b/packages/discord.js/src/util/Components.js @@ -1,9 +1,37 @@ -/* eslint-disable no-use-before-define */ 'use strict'; -// eslint-disable-next-line import-x/order +const { lazy } = require('@discordjs/util'); const { ComponentType } = require('discord-api-types/v10'); +// Fixes circular dependencies. +const getActionRow = lazy(() => require('../structures/ActionRow.js').ActionRow); +const getButtonComponent = lazy(() => require('../structures/ButtonComponent.js').ButtonComponent); +const getChannelSelectMenuComponent = lazy( + () => require('../structures/ChannelSelectMenuComponent.js').ChannelSelectMenuComponent, +); +const getComponent = lazy(() => require('../structures/Component.js').Component); +const getContainerComponent = lazy(() => require('../structures/ContainerComponent.js').ContainerComponent); +const getFileComponent = lazy(() => require('../structures/FileComponent.js').FileComponent); +const getLabelComponent = lazy(() => require('../structures/LabelComponent.js').LabelComponent); +const getMediaGalleryComponent = lazy(() => require('../structures/MediaGalleryComponent.js').MediaGalleryComponent); +const getMentionableSelectMenuComponent = lazy( + () => require('../structures/MentionableSelectMenuComponent.js').MentionableSelectMenuComponent, +); +const getRoleSelectMenuComponent = lazy( + () => require('../structures/RoleSelectMenuComponent.js').RoleSelectMenuComponent, +); +const getSectionComponent = lazy(() => require('../structures/SectionComponent.js').SectionComponent); +const getSeparatorComponent = lazy(() => require('../structures/SeparatorComponent.js').SeparatorComponent); +const getStringSelectMenuComponent = lazy( + () => require('../structures/StringSelectMenuComponent.js').StringSelectMenuComponent, +); +const getTextDisplayComponent = lazy(() => require('../structures/TextDisplayComponent.js').TextDisplayComponent); +const getTextInputComponent = lazy(() => require('../structures/TextInputComponent.js').TextInputComponent); +const getThumbnailComponent = lazy(() => require('../structures/ThumbnailComponent.js').ThumbnailComponent); +const getUserSelectMenuComponent = lazy( + () => require('../structures/UserSelectMenuComponent.js').UserSelectMenuComponent, +); + /** * @typedef {Object} BaseComponentData * @property {number} [id] the id of this component @@ -192,6 +220,25 @@ const { ComponentType } = require('discord-api-types/v10'); * SectionComponent|SeparatorComponent|TextDisplayComponent} MessageTopLevelComponent */ +const ComponentTypeToClass = { + [ComponentType.ActionRow]: getActionRow, + [ComponentType.Button]: getButtonComponent, + [ComponentType.StringSelect]: getStringSelectMenuComponent, + [ComponentType.TextInput]: getTextInputComponent, + [ComponentType.UserSelect]: getUserSelectMenuComponent, + [ComponentType.RoleSelect]: getRoleSelectMenuComponent, + [ComponentType.MentionableSelect]: getMentionableSelectMenuComponent, + [ComponentType.ChannelSelect]: getChannelSelectMenuComponent, + [ComponentType.Container]: getContainerComponent, + [ComponentType.TextDisplay]: getTextDisplayComponent, + [ComponentType.File]: getFileComponent, + [ComponentType.MediaGallery]: getMediaGalleryComponent, + [ComponentType.Section]: getSectionComponent, + [ComponentType.Separator]: getSeparatorComponent, + [ComponentType.Thumbnail]: getThumbnailComponent, + [ComponentType.Label]: getLabelComponent, +}; + /** * Transforms API data into a component * @@ -200,7 +247,7 @@ const { ComponentType } = require('discord-api-types/v10'); * @ignore */ function createComponent(data) { - return data instanceof Component ? data : new (ComponentTypeToClass[data.type] ?? Component)(data); + return data instanceof getComponent() ? data : new (ComponentTypeToClass[data.type]?.() ?? getComponent())(data); } /** @@ -241,40 +288,3 @@ function findComponentByCustomId(components, customId) { exports.createComponent = createComponent; exports.findComponentByCustomId = findComponentByCustomId; - -const { ActionRow } = require('../structures/ActionRow.js'); -const { ButtonComponent } = require('../structures/ButtonComponent.js'); -const { ChannelSelectMenuComponent } = require('../structures/ChannelSelectMenuComponent.js'); -const { Component } = require('../structures/Component.js'); -const { ContainerComponent } = require('../structures/ContainerComponent.js'); -const { FileComponent } = require('../structures/FileComponent.js'); -const { LabelComponent } = require('../structures/LabelComponent.js'); -const { MediaGalleryComponent } = require('../structures/MediaGalleryComponent.js'); -const { MentionableSelectMenuComponent } = require('../structures/MentionableSelectMenuComponent.js'); -const { RoleSelectMenuComponent } = require('../structures/RoleSelectMenuComponent.js'); -const { SectionComponent } = require('../structures/SectionComponent.js'); -const { SeparatorComponent } = require('../structures/SeparatorComponent.js'); -const { StringSelectMenuComponent } = require('../structures/StringSelectMenuComponent.js'); -const { TextDisplayComponent } = require('../structures/TextDisplayComponent.js'); -const { TextInputComponent } = require('../structures/TextInputComponent.js'); -const { ThumbnailComponent } = require('../structures/ThumbnailComponent.js'); -const { UserSelectMenuComponent } = require('../structures/UserSelectMenuComponent.js'); - -const ComponentTypeToClass = { - [ComponentType.ActionRow]: ActionRow, - [ComponentType.Button]: ButtonComponent, - [ComponentType.StringSelect]: StringSelectMenuComponent, - [ComponentType.TextInput]: TextInputComponent, - [ComponentType.UserSelect]: UserSelectMenuComponent, - [ComponentType.RoleSelect]: RoleSelectMenuComponent, - [ComponentType.MentionableSelect]: MentionableSelectMenuComponent, - [ComponentType.ChannelSelect]: ChannelSelectMenuComponent, - [ComponentType.Container]: ContainerComponent, - [ComponentType.TextDisplay]: TextDisplayComponent, - [ComponentType.File]: FileComponent, - [ComponentType.MediaGallery]: MediaGalleryComponent, - [ComponentType.Section]: SectionComponent, - [ComponentType.Separator]: SeparatorComponent, - [ComponentType.Thumbnail]: ThumbnailComponent, - [ComponentType.Label]: LabelComponent, -}; diff --git a/packages/discord.js/src/util/DataResolver.js b/packages/discord.js/src/util/DataResolver.js index 5e2c0adfd..d1d266aa2 100644 --- a/packages/discord.js/src/util/DataResolver.js +++ b/packages/discord.js/src/util/DataResolver.js @@ -3,10 +3,14 @@ const { Buffer } = require('node:buffer'); const fs = require('node:fs/promises'); const path = require('node:path'); +const { lazy } = require('@discordjs/util'); const { fetch } = require('undici'); const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors/index.js'); const { BaseInvite } = require('../structures/BaseInvite.js'); +// Fixes circular dependencies. +const getGuildTemplate = lazy(() => require('../structures/GuildTemplate.js').GuildTemplate); + /** * Data that can be resolved to give an invite code. This can be: * - An invite code @@ -54,8 +58,7 @@ function resolveInviteCode(data) { * @private */ function resolveGuildTemplateCode(data) { - const { GuildTemplate } = require('../structures/GuildTemplate.js'); - return resolveCode(data, GuildTemplate.GuildTemplatesPattern); + return resolveCode(data, getGuildTemplate().GuildTemplatesPattern); } /** diff --git a/packages/discord.js/src/util/Util.js b/packages/discord.js/src/util/Util.js index ceccbd4ca..0bbd2f073 100644 --- a/packages/discord.js/src/util/Util.js +++ b/packages/discord.js/src/util/Util.js @@ -2,13 +2,18 @@ const { parse } = require('node:path'); const { Collection } = require('@discordjs/collection'); +const { lazy } = require('@discordjs/util'); const { ChannelType, RouteBases, Routes } = require('discord-api-types/v10'); const { fetch } = require('undici'); -// eslint-disable-next-line import-x/order const { Colors } = require('./Colors.js'); // eslint-disable-next-line import-x/order const { DiscordjsError, DiscordjsRangeError, DiscordjsTypeError, ErrorCodes } = require('../errors/index.js'); +// Fixes circular dependencies. +const getAttachment = lazy(() => require('../structures/Attachment.js').Attachment); +const getGuildChannel = lazy(() => require('../structures/GuildChannel.js').GuildChannel); +const getSKU = lazy(() => require('../structures/SKU.js').SKU); + const isObject = data => typeof data === 'object' && data !== null; /** @@ -352,8 +357,7 @@ function resolveColor(color) { * @returns {Collection} */ function discordSort(collection) { - // eslint-disable-next-line no-use-before-define - const isGuildChannel = collection.first() instanceof GuildChannel; + const isGuildChannel = collection.first() instanceof getGuildChannel(); return collection.toSorted( isGuildChannel ? (a, b) => a.rawPosition - b.rawPosition || Number(BigInt(a.id) - BigInt(b.id)) @@ -555,8 +559,7 @@ function transformResolved( if (attachments) { result.attachments = new Collection(); for (const attachment of Object.values(attachments)) { - // eslint-disable-next-line no-use-before-define - const patched = new Attachment(attachment); + const patched = new (getAttachment())(attachment); result.attachments.set(attachment.id, patched); } } @@ -572,8 +575,7 @@ function transformResolved( */ function resolveSKUId(resolvable) { if (typeof resolvable === 'string') return resolvable; - // eslint-disable-next-line no-use-before-define - if (resolvable instanceof SKU) return resolvable.id; + if (resolvable instanceof getSKU()) return resolvable.id; return null; } @@ -600,8 +602,3 @@ exports.setPosition = setPosition; exports.basename = basename; exports.findName = findName; exports.transformResolved = transformResolved; - -// Fixes Circular -const { Attachment } = require('../structures/Attachment.js'); -const { GuildChannel } = require('../structures/GuildChannel.js'); -const { SKU } = require('../structures/SKU.js');