From ac683b9d040635de8514c80a9d433d9c6d63701b Mon Sep 17 00:00:00 2001 From: Vlad Frangu Date: Wed, 8 Oct 2025 10:21:41 +0300 Subject: [PATCH] feat(builders): modal select menus in builders v1 (#11138) * feat(builders): modal select menus * chore: fix test * fix: move setRequired up * fix: pack * chore: forwardport https://github.com/discordjs/discord.js/pull/11139 * types: expect errors * fix: id validator being required * fix: validators 2 * Apply suggestion from @Jiralite * Apply suggestion from @Jiralite * Apply suggestion from @Jiralite * fix: replace tests * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../__tests__/components/textInput.test.ts | 2 +- .../__tests__/components/v2/container.test.ts | 2 +- packages/builders/package.json | 2 +- packages/builders/src/components/Component.ts | 4 +- .../builders/src/components/Components.ts | 7 + .../src/components/label/Assertions.ts | 29 + .../builders/src/components/label/Label.ts | 198 ++ .../src/components/selectMenu/Assertions.ts | 92 + .../components/selectMenu/BaseSelectMenu.ts | 12 + .../src/components/textInput/Assertions.ts | 25 +- .../src/components/textInput/TextInput.ts | 7 +- packages/builders/src/index.ts | 3 + .../src/interactions/modals/Assertions.ts | 5 +- .../builders/src/interactions/modals/Modal.ts | 151 +- packages/discord.js/typings/index.d.ts | 6 +- packages/discord.js/typings/index.test-d.ts | 2596 +---------------- pnpm-lock.yaml | 296 +- 17 files changed, 700 insertions(+), 2737 deletions(-) create mode 100644 packages/builders/src/components/label/Assertions.ts create mode 100644 packages/builders/src/components/label/Label.ts create mode 100644 packages/builders/src/components/selectMenu/Assertions.ts diff --git a/packages/builders/__tests__/components/textInput.test.ts b/packages/builders/__tests__/components/textInput.test.ts index ab09ffe00..44b711200 100644 --- a/packages/builders/__tests__/components/textInput.test.ts +++ b/packages/builders/__tests__/components/textInput.test.ts @@ -100,7 +100,7 @@ describe('Text Input Components', () => { .setPlaceholder('hello') .setStyle(TextInputStyle.Paragraph) .toJSON(); - }).toThrowError(); + }).not.toThrowError(); }); test('GIVEN valid input THEN valid JSON outputs are given', () => { diff --git a/packages/builders/__tests__/components/v2/container.test.ts b/packages/builders/__tests__/components/v2/container.test.ts index b01d2fd92..f67ad2af0 100644 --- a/packages/builders/__tests__/components/v2/container.test.ts +++ b/packages/builders/__tests__/components/v2/container.test.ts @@ -1,8 +1,8 @@ import { type APIContainerComponent, ComponentType, SeparatorSpacingSize } from 'discord-api-types/v10'; import { describe, test, expect } from 'vitest'; -import { ButtonBuilder } from '../../../dist/index.mjs'; import { ActionRowBuilder } from '../../../src/components/ActionRow.js'; import { createComponentBuilder } from '../../../src/components/Components.js'; +import { ButtonBuilder } from '../../../src/components/button/Button.js'; import { ContainerBuilder } from '../../../src/components/v2/Container.js'; import { FileBuilder } from '../../../src/components/v2/File.js'; import { MediaGalleryBuilder } from '../../../src/components/v2/MediaGallery.js'; diff --git a/packages/builders/package.json b/packages/builders/package.json index fd0c73179..5247461ec 100644 --- a/packages/builders/package.json +++ b/packages/builders/package.json @@ -68,7 +68,7 @@ "@discordjs/formatters": "workspace:^", "@discordjs/util": "workspace:^", "@sapphire/shapeshift": "^4.0.0", - "discord-api-types": "^0.38.16", + "discord-api-types": "^0.38.26", "fast-deep-equal": "^3.1.3", "ts-mixer": "^6.0.4", "tslib": "^2.6.3" diff --git a/packages/builders/src/components/Component.ts b/packages/builders/src/components/Component.ts index bd6e9f1bb..b2e5cf884 100644 --- a/packages/builders/src/components/Component.ts +++ b/packages/builders/src/components/Component.ts @@ -5,6 +5,7 @@ import type { APIBaseComponent, ComponentType, APIMessageComponent, + APIModalComponent, } from 'discord-api-types/v10'; import { idValidator } from './Assertions'; @@ -14,7 +15,8 @@ import { idValidator } from './Assertions'; export type AnyAPIActionRowComponent = | APIActionRowComponent | APIComponentInActionRow - | APIMessageComponent; + | APIMessageComponent + | APIModalComponent; /** * The base component builder that contains common symbols for all sorts of components. diff --git a/packages/builders/src/components/Components.ts b/packages/builders/src/components/Components.ts index a2a03ff8b..4f9e174ca 100644 --- a/packages/builders/src/components/Components.ts +++ b/packages/builders/src/components/Components.ts @@ -8,6 +8,7 @@ import { } from './ActionRow.js'; import { ComponentBuilder } from './Component.js'; import { ButtonBuilder } from './button/Button.js'; +import { LabelBuilder } from './label/Label.js'; import { ChannelSelectMenuBuilder } from './selectMenu/ChannelSelectMenu.js'; import { MentionableSelectMenuBuilder } from './selectMenu/MentionableSelectMenu.js'; import { RoleSelectMenuBuilder } from './selectMenu/RoleSelectMenu.js'; @@ -100,6 +101,10 @@ export interface MappedComponentTypes { * The media gallery component type is associated with a {@link MediaGalleryBuilder}. */ [ComponentType.MediaGallery]: MediaGalleryBuilder; + /** + * The label component type is associated with a {@link LabelBuilder}. + */ + [ComponentType.Label]: LabelBuilder; } /** @@ -161,6 +166,8 @@ export function createComponentBuilder( return new ThumbnailBuilder(data); case ComponentType.MediaGallery: return new MediaGalleryBuilder(data); + case ComponentType.Label: + return new LabelBuilder(data); default: // @ts-expect-error This case can still occur if we get a newer unsupported component type throw new Error(`Cannot properly serialize component type: ${data.type}`); diff --git a/packages/builders/src/components/label/Assertions.ts b/packages/builders/src/components/label/Assertions.ts new file mode 100644 index 000000000..6da7a68fb --- /dev/null +++ b/packages/builders/src/components/label/Assertions.ts @@ -0,0 +1,29 @@ +import { s } from '@sapphire/shapeshift'; +import { ComponentType } from 'discord-api-types/v10'; +import { isValidationEnabled } from '../../util/validation.js'; +import { idValidator } from '../Assertions.js'; +import { + selectMenuChannelPredicate, + selectMenuMentionablePredicate, + selectMenuRolePredicate, + selectMenuStringPredicate, + selectMenuUserPredicate, +} from '../selectMenu/Assertions.js'; +import { textInputPredicate } from '../textInput/Assertions.js'; + +export const labelPredicate = s + .object({ + id: idValidator.optional(), + type: s.literal(ComponentType.Label), + label: s.string().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(45), + description: s.string().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(100).optional(), + component: s.union([ + textInputPredicate, + selectMenuUserPredicate, + selectMenuRolePredicate, + selectMenuMentionablePredicate, + selectMenuChannelPredicate, + selectMenuStringPredicate, + ]), + }) + .setValidationEnabled(isValidationEnabled); diff --git a/packages/builders/src/components/label/Label.ts b/packages/builders/src/components/label/Label.ts new file mode 100644 index 000000000..98e656d1f --- /dev/null +++ b/packages/builders/src/components/label/Label.ts @@ -0,0 +1,198 @@ +import type { + APIChannelSelectComponent, + APILabelComponent, + APIMentionableSelectComponent, + APIRoleSelectComponent, + APIStringSelectComponent, + APITextInputComponent, + APIUserSelectComponent, +} from 'discord-api-types/v10'; +import { ComponentType } from 'discord-api-types/v10'; +import { ComponentBuilder } from '../Component.js'; +import { createComponentBuilder, resolveBuilder } from '../Components.js'; +import { ChannelSelectMenuBuilder } from '../selectMenu/ChannelSelectMenu.js'; +import { MentionableSelectMenuBuilder } from '../selectMenu/MentionableSelectMenu.js'; +import { RoleSelectMenuBuilder } from '../selectMenu/RoleSelectMenu.js'; +import { StringSelectMenuBuilder } from '../selectMenu/StringSelectMenu.js'; +import { UserSelectMenuBuilder } from '../selectMenu/UserSelectMenu.js'; +import { TextInputBuilder } from '../textInput/TextInput.js'; +import { labelPredicate } from './Assertions.js'; + +export interface LabelBuilderData extends Partial> { + component?: + | ChannelSelectMenuBuilder + | MentionableSelectMenuBuilder + | RoleSelectMenuBuilder + | StringSelectMenuBuilder + | TextInputBuilder + | UserSelectMenuBuilder; +} + +/** + * A builder that creates API-compatible JSON data for labels. + */ +export class LabelBuilder extends ComponentBuilder { + /** + * @internal + */ + public override readonly data: LabelBuilderData; + + /** + * Creates a new label. + * + * @param data - The API data to create this label with + * @example + * Creating a label from an API data object: + * ```ts + * const label = new LabelBuilder({ + * label: "label", + * component, + * }); + * ``` + * @example + * Creating a label using setters and API data: + * ```ts + * const label = new LabelBuilder({ + * label: 'label', + * component, + * }).setLabel('new text'); + * ``` + */ + public constructor(data: Partial = {}) { + super({ type: ComponentType.Label }); + + const { component, ...rest } = data; + + this.data = { + ...rest, + component: component ? createComponentBuilder(component) : undefined, + type: ComponentType.Label, + }; + } + + /** + * Sets the label for this label. + * + * @param label - The label to use + */ + public setLabel(label: string) { + this.data.label = label; + return this; + } + + /** + * Sets the description for this label. + * + * @param description - The description to use + */ + public setDescription(description: string) { + this.data.description = description; + return this; + } + + /** + * Clears the description for this label. + */ + public clearDescription() { + this.data.description = undefined; + return this; + } + + /** + * Sets a string select menu component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setStringSelectMenuComponent( + input: + | APIStringSelectComponent + | StringSelectMenuBuilder + | ((builder: StringSelectMenuBuilder) => StringSelectMenuBuilder), + ): this { + this.data.component = resolveBuilder(input, StringSelectMenuBuilder); + return this; + } + + /** + * Sets a user select menu component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setUserSelectMenuComponent( + input: APIUserSelectComponent | UserSelectMenuBuilder | ((builder: UserSelectMenuBuilder) => UserSelectMenuBuilder), + ): this { + this.data.component = resolveBuilder(input, UserSelectMenuBuilder); + return this; + } + + /** + * Sets a role select menu component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setRoleSelectMenuComponent( + input: APIRoleSelectComponent | RoleSelectMenuBuilder | ((builder: RoleSelectMenuBuilder) => RoleSelectMenuBuilder), + ): this { + this.data.component = resolveBuilder(input, RoleSelectMenuBuilder); + return this; + } + + /** + * Sets a mentionable select menu component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setMentionableSelectMenuComponent( + input: + | APIMentionableSelectComponent + | MentionableSelectMenuBuilder + | ((builder: MentionableSelectMenuBuilder) => MentionableSelectMenuBuilder), + ): this { + this.data.component = resolveBuilder(input, MentionableSelectMenuBuilder); + return this; + } + + /** + * Sets a channel select menu component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setChannelSelectMenuComponent( + input: + | APIChannelSelectComponent + | ChannelSelectMenuBuilder + | ((builder: ChannelSelectMenuBuilder) => ChannelSelectMenuBuilder), + ): this { + this.data.component = resolveBuilder(input, ChannelSelectMenuBuilder); + return this; + } + + /** + * Sets a text input component to this label. + * + * @param input - A function that returns a component builder or an already built builder + */ + public setTextInputComponent( + input: APITextInputComponent | TextInputBuilder | ((builder: TextInputBuilder) => TextInputBuilder), + ): this { + this.data.component = resolveBuilder(input, TextInputBuilder); + return this; + } + + /** + * {@inheritDoc ComponentBuilder.toJSON} + */ + public override toJSON(): APILabelComponent { + const { component, ...rest } = this.data; + + const data = { + ...rest, + // The label predicate validates the component. + component: component?.toJSON(), + }; + + labelPredicate.parse(data); + + return data as APILabelComponent; + } +} diff --git a/packages/builders/src/components/selectMenu/Assertions.ts b/packages/builders/src/components/selectMenu/Assertions.ts new file mode 100644 index 000000000..831d1793c --- /dev/null +++ b/packages/builders/src/components/selectMenu/Assertions.ts @@ -0,0 +1,92 @@ +import { Result, s } from '@sapphire/shapeshift'; +import { ChannelType, ComponentType, SelectMenuDefaultValueType } from 'discord-api-types/v10'; +import { isValidationEnabled } from '../../util/validation.js'; +import { customIdValidator, emojiValidator, idValidator } from '../Assertions.js'; +import { labelValidator } from '../textInput/Assertions.js'; + +const selectMenuBasePredicate = s.object({ + id: idValidator.optional(), + placeholder: s.string().lengthLessThanOrEqual(150).optional(), + min_values: s.number().greaterThanOrEqual(0).lessThanOrEqual(25).optional(), + max_values: s.number().greaterThanOrEqual(0).lessThanOrEqual(25).optional(), + custom_id: customIdValidator, + disabled: s.boolean().optional(), +}); + +export const selectMenuChannelPredicate = selectMenuBasePredicate + .extend({ + type: s.literal(ComponentType.ChannelSelect), + channel_types: s.nativeEnum(ChannelType).array().optional(), + default_values: s + .object({ id: s.string(), type: s.literal(SelectMenuDefaultValueType.Channel) }) + .array() + .lengthLessThanOrEqual(25) + .optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export const selectMenuMentionablePredicate = selectMenuBasePredicate + .extend({ + type: s.literal(ComponentType.MentionableSelect), + default_values: s + .object({ + id: s.string(), + type: s.literal([SelectMenuDefaultValueType.Role, SelectMenuDefaultValueType.User]), + }) + .array() + .lengthLessThanOrEqual(25) + .optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export const selectMenuRolePredicate = selectMenuBasePredicate + .extend({ + type: s.literal(ComponentType.RoleSelect), + default_values: s + .object({ id: s.string(), type: s.literal(SelectMenuDefaultValueType.Role) }) + .array() + .lengthLessThanOrEqual(25) + .optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export const selectMenuUserPredicate = selectMenuBasePredicate + .extend({ + type: s.literal(ComponentType.UserSelect), + default_values: s + .object({ id: s.string(), type: s.literal(SelectMenuDefaultValueType.User) }) + .array() + .lengthLessThanOrEqual(25) + .optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export const selectMenuStringOptionPredicate = s + .object({ + label: labelValidator, + value: s.string().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(100), + description: s.string().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(100).optional(), + emoji: emojiValidator.optional(), + default: s.boolean().optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export const selectMenuStringPredicate = selectMenuBasePredicate + .extend({ + type: s.literal(ComponentType.StringSelect), + options: selectMenuStringOptionPredicate.array().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(25), + }) + .reshape((value) => { + if (value.min_values !== undefined && value.options.length < value.min_values) { + return Result.err(new RangeError(`The number of options must be greater than or equal to min_values`)); + } + + if (value.min_values !== undefined && value.max_values !== undefined && value.min_values > value.max_values) { + return Result.err( + new RangeError(`The maximum amount of options must be greater than or equal to the minimum amount of options`), + ); + } + + return Result.ok(value); + }) + .setValidationEnabled(isValidationEnabled); diff --git a/packages/builders/src/components/selectMenu/BaseSelectMenu.ts b/packages/builders/src/components/selectMenu/BaseSelectMenu.ts index 298d7dc5e..a6006f3ff 100644 --- a/packages/builders/src/components/selectMenu/BaseSelectMenu.ts +++ b/packages/builders/src/components/selectMenu/BaseSelectMenu.ts @@ -1,6 +1,7 @@ import type { APISelectMenuComponent } from 'discord-api-types/v10'; import { customIdValidator, disabledValidator, minMaxValidator, placeholderValidator } from '../Assertions.js'; import { ComponentBuilder } from '../Component.js'; +import { requiredValidator } from '../textInput/Assertions.js'; /** * The base select menu builder that contains common symbols for select menu builders. @@ -60,6 +61,17 @@ export abstract class BaseSelectMenuBuilder< return this; } + /** + * Sets whether this select menu is required. + * + * @remarks Only for use in modals. + * @param required - Whether this select menu is required + */ + public setRequired(required = true) { + this.data.required = requiredValidator.parse(required); + return this; + } + /** * {@inheritDoc ComponentBuilder.toJSON} */ diff --git a/packages/builders/src/components/textInput/Assertions.ts b/packages/builders/src/components/textInput/Assertions.ts index 084a01c6a..3c93409fa 100644 --- a/packages/builders/src/components/textInput/Assertions.ts +++ b/packages/builders/src/components/textInput/Assertions.ts @@ -1,9 +1,9 @@ import { s } from '@sapphire/shapeshift'; -import { TextInputStyle } from 'discord-api-types/v10'; +import { ComponentType, TextInputStyle } from 'discord-api-types/v10'; import { isValidationEnabled } from '../../util/validation.js'; -import { customIdValidator } from '../Assertions.js'; +import { customIdValidator, idValidator } from '../Assertions.js'; -export const textInputStyleValidator = s.nativeEnum(TextInputStyle); +export const textInputStyleValidator = s.nativeEnum(TextInputStyle).setValidationEnabled(isValidationEnabled); export const minLengthValidator = s .number() .int() @@ -16,7 +16,7 @@ export const maxLengthValidator = s .greaterThanOrEqual(1) .lessThanOrEqual(4_000) .setValidationEnabled(isValidationEnabled); -export const requiredValidator = s.boolean(); +export const requiredValidator = s.boolean().setValidationEnabled(isValidationEnabled); export const valueValidator = s.string().lengthLessThanOrEqual(4_000).setValidationEnabled(isValidationEnabled); export const placeholderValidator = s.string().lengthLessThanOrEqual(100).setValidationEnabled(isValidationEnabled); export const labelValidator = s @@ -25,8 +25,21 @@ export const labelValidator = s .lengthLessThanOrEqual(45) .setValidationEnabled(isValidationEnabled); -export function validateRequiredParameters(customId?: string, style?: TextInputStyle, label?: string) { +export const textInputPredicate = s + .object({ + type: s.literal(ComponentType.TextInput), + custom_id: customIdValidator, + style: textInputStyleValidator, + id: idValidator.optional(), + min_length: minLengthValidator.optional(), + max_length: maxLengthValidator.optional(), + placeholder: placeholderValidator.optional(), + value: valueValidator.optional(), + required: requiredValidator.optional(), + }) + .setValidationEnabled(isValidationEnabled); + +export function validateRequiredParameters(customId?: string, style?: TextInputStyle) { customIdValidator.parse(customId); textInputStyleValidator.parse(style); - labelValidator.parse(label); } diff --git a/packages/builders/src/components/textInput/TextInput.ts b/packages/builders/src/components/textInput/TextInput.ts index c8bb1f838..93d0300b6 100644 --- a/packages/builders/src/components/textInput/TextInput.ts +++ b/packages/builders/src/components/textInput/TextInput.ts @@ -30,7 +30,7 @@ export class TextInputBuilder * ```ts * const textInput = new TextInputBuilder({ * custom_id: 'a cool text input', - * label: 'Type something', + * placeholder: 'Type something', * style: TextInputStyle.Short, * }); * ``` @@ -38,7 +38,7 @@ export class TextInputBuilder * Creating a text input using setters and API data: * ```ts * const textInput = new TextInputBuilder({ - * label: 'Type something else', + * placeholder: 'Type something else', * }) * .setCustomId('woah') * .setStyle(TextInputStyle.Paragraph); @@ -62,6 +62,7 @@ export class TextInputBuilder * Sets the label for this text input. * * @param label - The label to use + * @deprecated Use a label builder to create a label (and optionally a description) instead. */ public setLabel(label: string) { this.data.label = labelValidator.parse(label); @@ -132,7 +133,7 @@ export class TextInputBuilder * {@inheritDoc ComponentBuilder.toJSON} */ public toJSON(): APITextInputComponent { - validateRequiredParameters(this.data.custom_id, this.data.style, this.data.label); + validateRequiredParameters(this.data.custom_id, this.data.style); return { ...this.data, diff --git a/packages/builders/src/index.ts b/packages/builders/src/index.ts index 62030af0d..84ceb8aeb 100644 --- a/packages/builders/src/index.ts +++ b/packages/builders/src/index.ts @@ -34,6 +34,9 @@ export { export * from './components/selectMenu/StringSelectMenuOption.js'; export * from './components/selectMenu/UserSelectMenu.js'; +export * from './components/label/Label.js'; +export * as LabelAssertions from './components/label/Assertions.js'; + export * as ComponentsV2Assertions from './components/v2/Assertions.js'; export * from './components/v2/Container.js'; export * from './components/v2/File.js'; diff --git a/packages/builders/src/interactions/modals/Assertions.ts b/packages/builders/src/interactions/modals/Assertions.ts index 79597ff47..97db2cb38 100644 --- a/packages/builders/src/interactions/modals/Assertions.ts +++ b/packages/builders/src/interactions/modals/Assertions.ts @@ -1,6 +1,7 @@ import { s } from '@sapphire/shapeshift'; import { ActionRowBuilder, type ModalActionRowComponentBuilder } from '../../components/ActionRow.js'; import { customIdValidator } from '../../components/Assertions.js'; +import { LabelBuilder } from '../../components/label/Label.js'; import { isValidationEnabled } from '../../util/validation.js'; export const titleValidator = s @@ -9,7 +10,7 @@ export const titleValidator = s .lengthLessThanOrEqual(45) .setValidationEnabled(isValidationEnabled); export const componentsValidator = s - .instance(ActionRowBuilder) + .union([s.instance(ActionRowBuilder), s.instance(LabelBuilder)]) .array() .lengthGreaterThanOrEqual(1) .setValidationEnabled(isValidationEnabled); @@ -17,7 +18,7 @@ export const componentsValidator = s export function validateRequiredParameters( customId?: string, title?: string, - components?: ActionRowBuilder[], + components?: (ActionRowBuilder | LabelBuilder)[], ) { customIdValidator.parse(customId); titleValidator.parse(title); diff --git a/packages/builders/src/interactions/modals/Modal.ts b/packages/builders/src/interactions/modals/Modal.ts index 513b36765..49f940db9 100644 --- a/packages/builders/src/interactions/modals/Modal.ts +++ b/packages/builders/src/interactions/modals/Modal.ts @@ -2,13 +2,18 @@ import type { JSONEncodable } from '@discordjs/util'; import type { + APITextInputComponent, APIActionRowComponent, APIComponentInModalActionRow, + APILabelComponent, APIModalInteractionResponseCallbackData, } from 'discord-api-types/v10'; +import { ComponentType } from 'discord-api-types/v10'; import { ActionRowBuilder, type ModalActionRowComponentBuilder } from '../../components/ActionRow.js'; import { customIdValidator } from '../../components/Assertions.js'; -import { createComponentBuilder } from '../../components/Components.js'; +import { createComponentBuilder, resolveBuilder } from '../../components/Components.js'; +import { LabelBuilder } from '../../components/label/Label.js'; +import { TextInputBuilder } from '../../components/textInput/TextInput.js'; import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js'; import { titleValidator, validateRequiredParameters } from './Assertions.js'; @@ -24,7 +29,7 @@ export class ModalBuilder implements JSONEncodable[] = []; + public readonly components: (ActionRowBuilder | LabelBuilder)[] = []; /** * Creates a new modal from API data. @@ -33,8 +38,10 @@ export class ModalBuilder implements JSONEncodable = {}) { this.data = { ...data }; - this.components = (components?.map((component) => createComponentBuilder(component)) ?? - []) as ActionRowBuilder[]; + this.components = (components?.map((component) => createComponentBuilder(component)) ?? []) as ( + | ActionRowBuilder + | LabelBuilder + )[]; } /** @@ -61,28 +68,150 @@ export class ModalBuilder implements JSONEncodable | APIActionRowComponent + | ActionRowBuilder + | APIActionRowComponent + | APILabelComponent + | APITextInputComponent + | LabelBuilder + | TextInputBuilder > ) { this.components.push( - ...normalizeArray(components).map((component) => - component instanceof ActionRowBuilder - ? component - : new ActionRowBuilder(component), - ), + ...normalizeArray(components).map((component, idx) => { + if (component instanceof ActionRowBuilder || component instanceof LabelBuilder) { + return component; + } + + if (component instanceof TextInputBuilder) { + return new ActionRowBuilder().addComponents(component); + } + + if ('type' in component) { + if (component.type === ComponentType.ActionRow) { + return new ActionRowBuilder(component); + } + + if (component.type === ComponentType.Label) { + return new LabelBuilder(component); + } + + if (component.type === ComponentType.TextInput) { + return new ActionRowBuilder().addComponents( + new TextInputBuilder(component), + ); + } + } + + throw new TypeError(`Invalid component passed in ModalBuilder.addComponents at index ${idx}!`); + }), ); return this; } + /** + * Adds label components to this modal. + * + * @param components - The components to add + */ + public addLabelComponents( + ...components: RestOrArray LabelBuilder)> + ) { + const normalized = normalizeArray(components); + const resolved = normalized.map((label) => resolveBuilder(label, LabelBuilder)); + + this.components.push(...resolved); + + return this; + } + + /** + * Adds action rows to this modal. + * + * @param components - The components to add + * @deprecated Use {@link ModalBuilder.addLabelComponents} instead + */ + public addActionRowComponents( + ...components: RestOrArray< + | ActionRowBuilder + | APIActionRowComponent + | (( + builder: ActionRowBuilder, + ) => ActionRowBuilder) + > + ) { + const normalized = normalizeArray(components); + const resolved = normalized.map((row) => resolveBuilder(row, ActionRowBuilder)); + + this.components.push(...resolved); + + return this; + } + + /** + * Sets the labels for this modal. + * + * @param components - The components to set + */ + public setLabelComponents( + ...components: RestOrArray LabelBuilder)> + ) { + const normalized = normalizeArray(components); + this.spliceLabelComponents(0, this.components.length, ...normalized); + + return this; + } + + /** + * Removes, replaces, or inserts labels for this modal. + * + * @remarks + * This method behaves similarly + * to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}. + * The maximum amount of labels that can be added is 5. + * + * It's useful for modifying and adjusting order of the already-existing labels of a modal. + * @example + * Remove the first label: + * ```ts + * modal.spliceLabelComponents(0, 1); + * ``` + * @example + * Remove the first n labels: + * ```ts + * const n = 4; + * modal.spliceLabelComponents(0, n); + * ``` + * @example + * Remove the last label: + * ```ts + * modal.spliceLabelComponents(-1, 1); + * ``` + * @param index - The index to start at + * @param deleteCount - The number of labels to remove + * @param labels - The replacing label objects + */ + public spliceLabelComponents( + index: number, + deleteCount: number, + ...labels: (APILabelComponent | LabelBuilder | ((builder: LabelBuilder) => LabelBuilder))[] + ): this { + const resolved = labels.map((label) => resolveBuilder(label, LabelBuilder)); + this.components.splice(index, deleteCount, ...resolved); + + return this; + } + /** * Sets components for this modal. * * @param components - The components to set + * @deprecated Use {@link ModalBuilder.setLabelComponents} instead */ - public setComponents(...components: RestOrArray>) { + public setComponents(...components: RestOrArray | LabelBuilder>) { this.components.splice(0, this.components.length, ...normalizeArray(components)); return this; } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 766d81e1c..d998a7cb0 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -314,8 +314,9 @@ export class ActionRowBuilder< >, ); public static from( - other: - | JSONEncodable>> + other: // @ts-expect-error builders/1.x. + | JSONEncodable>> + // @ts-expect-error builders/1.x. | APIActionRowComponent>, ): ActionRowBuilder; } @@ -6461,6 +6462,7 @@ export interface BaseMessageOptions { )[]; components?: readonly ( | JSONEncodable> + // @ts-expect-error builders/1.x. | ActionRowData | APIActionRowComponent )[]; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index a0271423f..18b800f3a 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -1,2595 +1 @@ -import type { ChildProcess } from 'node:child_process'; -import type { Worker } from 'node:worker_threads'; -import { - APIInteractionGuildMember, - APIPartialChannel, - APIPartialGuild, - APIInteractionDataResolvedGuildMember, - APIInteractionDataResolvedChannel, - APIRole, - APIButtonComponent, - APISelectMenuComponent, - ApplicationCommandOptionType, - ComponentType, - ApplicationCommandPermissionType, - ChannelType, - InteractionType, - GatewayIntentBits, - Locale, - PermissionFlagsBits, - AuditLogEvent, - ButtonStyle, - TextInputStyle, - APITextInputComponent, - APIEmbed, - ApplicationCommandType, - APIMessage, - APIActionRowComponent, - APIComponentInActionRow, - APIStringSelectComponent, - APIUserSelectComponent, - APIRoleSelectComponent, - APIChannelSelectComponent, - APIMentionableSelectComponent, - APIModalInteractionResponseCallbackData, - WebhookType, -} from 'discord-api-types/v10'; -import { - ApplicationCommand, - ApplicationCommandData, - ApplicationCommandManager, - ApplicationCommandOptionData, - ApplicationCommandResolvable, - ApplicationCommandSubCommandData, - ApplicationCommandSubGroupData, - CommandInteraction, - ButtonInteraction, - CacheType, - CategoryChannel, - Client, - ClientApplication, - ClientUser, - CloseEvent, - Collection, - ChatInputCommandInteraction, - CommandInteractionOption, - CommandInteractionOptionResolver, - CommandOptionNonChoiceResolvableType, - ContextMenuCommandInteraction, - DMChannel, - Guild, - GuildApplicationCommandManager, - GuildChannelManager, - GuildEmoji, - GuildEmojiManager, - GuildMember, - GuildResolvable, - IntentsBitField, - Interaction, - InteractionCollector, - Message, - AttachmentBuilder, - MessageCollector, - MessageComponentInteraction, - MessageReaction, - ModalBuilder, - NewsChannel, - Options, - PartialTextBasedChannelFields, - PartialUser, - PermissionsBitField, - ReactionCollector, - Role, - RoleManager, - Serialized, - ShardClientUtil, - ShardingManager, - Snowflake, - StageChannel, - TextBasedChannelFields, - type TextBasedChannel, - type TextBasedChannelTypes, - type VoiceBasedChannel, - type GuildBasedChannel, - type NonThreadGuildBasedChannel, - type GuildTextBasedChannel, - TextChannel, - ThreadChannel, - ThreadMember, - Typing, - User, - VoiceChannel, - Shard, - WebSocketShard, - Collector, - GuildAuditLogsEntry, - GuildAuditLogs, - type AuditLogChange, - StageInstance, - ActionRowBuilder, - ButtonComponent, - SelectMenuComponent, - RepliableInteraction, - ThreadChannelType, - Events, - WebSocketShardEvents, - Status, - CategoryChannelChildManager, - ActionRowData, - MessageActionRowComponentData, - PartialThreadMember, - ThreadMemberFlagsBitField, - ButtonBuilder, - EmbedBuilder, - MessageActionRowComponent, - StringSelectMenuBuilder, - TextInputBuilder, - TextInputComponent, - Embed, - MessageActionRowComponentBuilder, - GuildBanManager, - GuildBan, - MessageManager, - ChannelMention, - UserMention, - PartialGroupDMChannel, - Attachment, - MessageContextMenuCommandInteraction, - UserContextMenuCommandInteraction, - AnyThreadChannel, - ThreadMemberManager, - CollectedMessageInteraction, - ShardEvents, - Webhook, - WebhookClient, - InteractionWebhook, - ActionRowComponent, - ActionRow, - GuildAuditLogsActionType, - GuildAuditLogsTargetType, - ModalSubmitInteraction, - ForumChannel, - ChannelFlagsBitField, - GuildForumThreadManager, - GuildTextThreadManager, - AnySelectMenuInteraction, - StringSelectMenuInteraction, - StringSelectMenuComponent, - UserSelectMenuInteraction, - RoleSelectMenuInteraction, - ChannelSelectMenuInteraction, - MentionableSelectMenuInteraction, - MessageMentions, - AutoModerationActionExecution, - AutoModerationRule, - AutoModerationRuleManager, - PrivateThreadChannel, - PublicThreadChannel, - GuildMemberManager, - GuildMemberFlagsBitField, - ThreadManager, - FetchedThreads, - FetchedThreadsMore, - DMMessageManager, - GuildMessageManager, - ApplicationCommandChannelOptionData, - ApplicationCommandChannelOption, - ApplicationCommandChoicesOption, - ApplicationCommandChoicesData, - ApplicationCommandSubGroup, - ApplicationCommandSubCommand, - ChatInputApplicationCommandData, - ApplicationCommandPermissionsManager, - GuildOnboarding, - StringSelectMenuComponentData, - ButtonComponentData, - MediaChannel, - PartialDMChannel, - PartialGuildMember, - PartialMessage, - PartialMessageReaction, - resolvePartialEmoji, - PartialEmojiOnlyId, - Emoji, - PartialEmoji, - Awaitable, - Channel, - DirectoryChannel, - Entitlement, - SKU, - UserSelectMenuBuilder, - RoleSelectMenuBuilder, - ChannelSelectMenuBuilder, - MentionableSelectMenuBuilder, - UserSelectMenuComponent, - RoleSelectMenuComponent, - ChannelSelectMenuComponent, - MentionableSelectMenuComponent, - Poll, - ApplicationEmoji, - ApplicationEmojiManager, - StickerPack, -} from '.'; -import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd'; -import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders'; -import { ReadonlyCollection } from '@discordjs/collection'; - -// Test type transformation: -declare const serialize: (value: Value) => Serialized; -declare const notPropertyOf: ( - value: Value, - property: Property & Exclude, -) => void; - -const client: Client = new Client({ - intents: GatewayIntentBits.Guilds, - makeCache: Options.cacheWithLimits({ - MessageManager: 200, - // @ts-expect-error - Message: 100, - GuildMemberManager: { - maxSize: 200, - keepOverLimit: member => member.id === client.user?.id, - }, - ThreadManager: { - maxSize: 200, - keepOverLimit: value => !value.archived, - }, - }), -}); - -if (client.isReady()) { - expectType>(client); -} else { - expectType(client); -} - -const testGuildId = '222078108977594368'; // DJS -const testUserId = '987654321098765432'; // example id -const globalCommandId = '123456789012345678'; // example id -const guildCommandId = '234567890123456789'; // example id - -client.on('autoModerationActionExecution', autoModerationActionExecution => - expectType(autoModerationActionExecution), -); - -client.on('autoModerationRuleCreate', ({ client }) => expectType>(client)); -client.on('autoModerationRuleDelete', ({ client }) => expectType>(client)); - -client.on('autoModerationRuleUpdate', (oldAutoModerationRule, { client: newClient }) => { - expectType>(oldAutoModerationRule!.client); - expectType>(newClient); -}); - -client.on('channelCreate', ({ client }) => expectType>(client)); -client.on('channelDelete', ({ client }) => expectType>(client)); -client.on('channelPinsUpdate', ({ client }) => expectType>(client)); - -client.on('channelUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('emojiCreate', ({ client }) => expectType>(client)); -client.on('emojiDelete', ({ client }) => expectType>(client)); - -client.on('emojiUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('guildBanAdd', ({ client }) => expectType>(client)); -client.on('guildBanRemove', ({ client }) => expectType>(client)); -client.on('guildDelete', ({ client }) => expectType>(client)); -client.on('guildIntegrationsUpdate', ({ client }) => expectType>(client)); -client.on('guildMemberAdd', ({ client }) => expectType>(client)); -client.on('guildMemberAvailable', ({ client }) => expectType>(client)); - -client.on('guildMemberRemove', member => { - expectType>(member.client); - if (member.partial) return expectType(member.joinedAt); - expectType(member.joinedAt); -}); - -client.on('guildMembersChunk', (members, { client }) => { - expectType>(members.first()!.client); - expectType>(client); -}); - -client.on('guildMemberUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('guildScheduledEventCreate', ({ client }) => expectType>(client)); -client.on('guildScheduledEventDelete', ({ client }) => expectType>(client)); - -client.on('guildScheduledEventUpdate', (oldGuildScheduledEvent, { client }) => { - expectType>(oldGuildScheduledEvent!.client); - expectType>(client); -}); - -client.on('guildScheduledEventUserAdd', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('guildScheduledEventUserRemove', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('guildUnavailable', ({ client }) => expectType>(client)); - -client.on('guildUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('interactionCreate', async interaction => { - expectType>(interaction.client); - expectType(interaction.guildId); - expectType(interaction.channelId); - expectType(interaction.member); - - if (interaction.type === InteractionType.MessageComponent) { - expectType(interaction.channelId); - } - - if (interaction.type !== InteractionType.ApplicationCommand) return; - - void new ActionRowBuilder(); - - const button = new ButtonBuilder(); - - const actionRow = new ActionRowBuilder({ - type: ComponentType.ActionRow, - components: [button.toJSON()], - }); - - actionRow.toJSON(); - - await interaction.reply({ content: 'Hi!', components: [actionRow] }); - - // @ts-expect-error - interaction.reply({ content: 'Hi!', components: [[button]] }); - - void new ActionRowBuilder({}); - - // @ts-expect-error - await interaction.reply({ content: 'Hi!', components: [button] }); - - await interaction.reply({ - content: 'test', - components: [ - { - components: [ - { - custom_id: 'abc', - label: 'abc', - style: ButtonStyle.Primary, - type: ComponentType.Button, - }, - ], - type: ComponentType.ActionRow, - }, - ], - }); - - // This is for testing never type resolution - if (!interaction.inGuild()) { - return; - } - - if (interaction.inRawGuild()) { - expectNotType(interaction); - return; - } - - if (interaction.inCachedGuild()) { - expectNotType(interaction); - return; - } -}); - -client.on('inviteCreate', ({ client }) => expectType>(client)); -client.on('inviteDelete', ({ client }) => expectType>(client)); - -// This is to check that stuff is the right type -declare const assertIsMessage: (m: Promise) => void; - -client.on('messageCreate', async message => { - const { client, channel } = message; - - // https://github.com/discordjs/discord.js/issues/8545 - { - // These should not throw any errors when comparing messages from any source. - channel.messages.cache.filter(message => message); - (await channel.messages.fetch()).filter(({ author }) => author.id === message.author.id); - - if (channel.isDMBased()) { - expectType(channel.messages.channel.messages); - } else { - expectType(channel.messages.channel.messages); - } - } - - if (!message.inGuild() && message.partial) { - expectNotType(message); - } - - expectType>(client); - assertIsMessage(channel.send('string')); - assertIsMessage(channel.send({})); - assertIsMessage(channel.send({ embeds: [] })); - - const attachment = new AttachmentBuilder('file.png'); - const embed = new EmbedBuilder(); - assertIsMessage(channel.send({ files: [attachment] })); - assertIsMessage(channel.send({ embeds: [embed] })); - assertIsMessage(channel.send({ embeds: [embed], files: [attachment] })); - - if (message.inGuild()) { - expectAssignable>(message); - const component = await message.awaitMessageComponent({ componentType: ComponentType.Button }); - expectType>(component); - expectType>(await component.reply({ fetchReply: true })); - - const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button }); - expectType>>(buttonCollector); - expectAssignable< - ( - test: ButtonInteraction<'cached'>, - items: Collection>, - ) => Awaitable - >(buttonCollector.filter); - expectType(message.channel); - expectType(message.guild); - expectType(message.member); - - expectType>(message.mentions); - expectType(message.guild); - expectType>(message.mentions.members); - } - - expectType>(message.channel); - expectNotType(message.channel); - - // @ts-expect-error - channel.send(); - // @ts-expect-error - channel.send({ another: 'property' }); - - // Check collector creations. - - // Verify that buttons interactions are inferred. - const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button }); - expectAssignable>(message.awaitMessageComponent({ componentType: ComponentType.Button })); - expectAssignable>(channel.awaitMessageComponent({ componentType: ComponentType.Button })); - expectAssignable>(buttonCollector); - - // Verify that select menus interaction are inferred. - const selectMenuCollector = message.createMessageComponentCollector({ componentType: ComponentType.StringSelect }); - expectAssignable>( - message.awaitMessageComponent({ componentType: ComponentType.StringSelect }), - ); - expectAssignable>( - channel.awaitMessageComponent({ componentType: ComponentType.StringSelect }), - ); - expectAssignable>(selectMenuCollector); - - // Verify that message component interactions are default collected types. - const defaultCollector = message.createMessageComponentCollector(); - expectAssignable>(message.awaitMessageComponent()); - expectAssignable>(channel.awaitMessageComponent()); - expectAssignable>(defaultCollector); - - // Verify that additional options don't affect default collector types. - const semiDefaultCollector = message.createMessageComponentCollector({ time: 10000 }); - expectType>(semiDefaultCollector); - const semiDefaultCollectorChannel = message.createMessageComponentCollector({ time: 10000 }); - expectType>(semiDefaultCollectorChannel); - - // Verify that interaction collector options can't be used. - message.createMessageComponentCollector({ - // @ts-expect-error - interactionType: InteractionType.ApplicationCommand, - }); - - // Make sure filter parameters are properly inferred. - message.createMessageComponentCollector({ - filter: i => { - expectType(i); - return true; - }, - }); - - message.createMessageComponentCollector({ - componentType: ComponentType.Button, - filter: i => { - expectType(i); - return true; - }, - }); - - message.createMessageComponentCollector({ - componentType: ComponentType.StringSelect, - filter: i => { - expectType(i); - return true; - }, - }); - - message.awaitMessageComponent({ - filter: i => { - expectType(i); - return true; - }, - }); - - message.awaitMessageComponent({ - componentType: ComponentType.Button, - filter: i => { - expectType(i); - return true; - }, - }); - - message.awaitMessageComponent({ - componentType: ComponentType.StringSelect, - filter: i => { - expectType(i); - return true; - }, - }); - - const webhook = await message.fetchWebhook(); - - if (webhook.isChannelFollower()) { - expectAssignable(webhook.sourceGuild); - expectAssignable(webhook.sourceChannel); - expectType>(webhook); - } else if (webhook.isIncoming()) { - expectType(webhook.token); - expectType>(webhook); - } - - expectNotType(webhook.sourceGuild); - expectNotType(webhook.sourceChannel); - expectNotType(webhook.token); - - channel.awaitMessageComponent({ - filter: i => { - expectType>(i); - return true; - }, - }); - - channel.awaitMessageComponent({ - componentType: ComponentType.Button, - filter: i => { - expectType>(i); - return true; - }, - }); - - channel.awaitMessageComponent({ - componentType: ComponentType.StringSelect, - filter: i => { - expectType>(i); - return true; - }, - }); - - // Check that both builders and builder data can be sent in messages - const row = new ActionRowBuilder(); - - const rawButtonsRow: ActionRowData = { - type: ComponentType.ActionRow, - components: [ - { type: ComponentType.Button, label: 'test', style: ButtonStyle.Primary, customId: 'test' }, - { - type: ComponentType.Button, - label: 'another test', - style: ButtonStyle.Link, - url: 'https://discord.js.org', - }, - ], - }; - - const buttonsRow: ActionRowData = { - type: ComponentType.ActionRow, - components: [new ButtonBuilder()], - }; - - const rawStringSelectMenuRow: ActionRowData = { - type: ComponentType.ActionRow, - components: [ - { - type: ComponentType.StringSelect, - options: [{ label: 'test', value: 'test' }], - customId: 'test', - }, - ], - }; - - const stringSelectRow: ActionRowData = { - type: ComponentType.ActionRow, - components: [new StringSelectMenuBuilder()], - }; - - const embedData = { description: 'test', color: 0xff0000 }; - - channel.send({ - components: [row, rawButtonsRow, buttonsRow, rawStringSelectMenuRow, stringSelectRow], - embeds: [embed, embedData], - }); -}); - -client.on('messageDelete', ({ client }) => expectType>(client)); - -client.on('messageDeleteBulk', (messages, { client }) => { - expectType>(messages.first()!.client); - expectType>(client); -}); - -client.on('messageReactionAdd', async (reaction, { client }) => { - expectType>(reaction.client); - expectType>(client); - - if (reaction.partial) { - expectType(reaction.count); - reaction = await reaction.fetch(); - } - - expectType(reaction.count); - if (reaction.message.partial) return expectType(reaction.message.content); - expectType(reaction.message.content); -}); - -client.on('messageReactionRemove', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('messageReactionRemoveAll', async (message, reactions) => { - console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`); - if (message.partial) message = await message.fetch(); - console.log(`messageReactionRemoveAll - content: ${message.content}`); - expectType>(message.client); - expectType>(reactions.first()!.client); -}); - -client.on('messageReactionRemoveEmoji', ({ client }) => expectType>(client)); - -client.on('messageUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('presenceUpdate', (oldPresence, { client }) => { - expectType>(oldPresence!.client); - expectType>(client); -}); - -declare const slashCommandBuilder: SlashCommandBuilder; -declare const contextMenuCommandBuilder: ContextMenuCommandBuilder; - -client.on('ready', async client => { - expectType>(client); - console.log(`Client is logged in as ${client.user.tag} and ready!`); - - // Test fetching all global commands and ones from one guild - expectType>>( - await client.application!.commands.fetch(), - ); - expectType>>( - await client.application!.commands.fetch({ guildId: testGuildId }), - ); - - // 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); - - await client.application?.commands.create(slashCommandBuilder); - await client.application?.commands.create(contextMenuCommandBuilder); - await guild.commands.create(slashCommandBuilder); - await guild.commands.create(contextMenuCommandBuilder); - - await client.application?.commands.edit(globalCommandId, slashCommandBuilder); - await client.application?.commands.edit(globalCommandId, contextMenuCommandBuilder); - await guild.commands.edit(guildCommandId, slashCommandBuilder); - await guild.commands.edit(guildCommandId, contextMenuCommandBuilder); - - await client.application?.commands.edit(globalCommandId, { defaultMemberPermissions: null }); - await globalCommand?.edit({ defaultMemberPermissions: null }); - await globalCommand?.setDefaultMemberPermissions(null); - await guildCommandFromGlobal?.edit({ dmPermission: false }); - - // @ts-expect-error - await client.guilds.cache.get(testGuildId)?.commands.fetch(guildCommandId, { guildId: testGuildId }); - - // Test command permissions - const globalPermissionsManager = client.application?.commands.permissions; - const guildPermissionsManager = client.guilds.cache.get(testGuildId)?.commands.permissions; - - // Permissions from global manager - await globalPermissionsManager?.add({ - command: globalCommandId, - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await globalPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); - await globalPermissionsManager?.fetch({ guild: testGuildId }); - await globalPermissionsManager?.fetch({ command: globalCommandId, guild: testGuildId }); - await globalPermissionsManager?.remove({ - command: globalCommandId, - guild: testGuildId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - await globalPermissionsManager?.remove({ - command: globalCommandId, - guild: testGuildId, - users: [testUserId], - token: 'VeryRealToken', - }); - await globalPermissionsManager?.remove({ - command: globalCommandId, - guild: testGuildId, - channels: [testGuildId], - token: 'VeryRealToken', - }); - await globalPermissionsManager?.remove({ - command: globalCommandId, - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - channels: [testGuildId], - token: 'VeryRealToken', - }); - await globalPermissionsManager?.set({ - command: globalCommandId, - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // @ts-expect-error - await globalPermissionsManager?.add({ - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId }); - // @ts-expect-error - await globalPermissionsManager?.fetch(); - // @ts-expect-error - await globalPermissionsManager?.fetch({ command: globalCommandId }); - // @ts-expect-error - await globalPermissionsManager?.remove({ command: globalCommandId, roles: [testGuildId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalPermissionsManager?.remove({ command: globalCommandId, users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalPermissionsManager?.remove({ - command: globalCommandId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalPermissionsManager?.set({ - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // @ts-expect-error - await globalPermissionsManager?.add({ - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalPermissionsManager?.has({ guild: testGuildId, permissionId: testGuildId }); - // @ts-expect-error - await globalPermissionsManager?.remove({ guild: testGuildId, roles: [testGuildId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalPermissionsManager?.remove({ guild: testGuildId, users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalPermissionsManager?.remove({ - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalPermissionsManager?.set({ - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // Permissions from guild manager - await guildPermissionsManager?.add({ - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await guildPermissionsManager?.has({ command: globalCommandId, permissionId: testGuildId }); - await guildPermissionsManager?.fetch({}); - await guildPermissionsManager?.fetch({ command: globalCommandId }); - await guildPermissionsManager?.remove({ command: globalCommandId, roles: [testGuildId], token: 'VeryRealToken' }); - await guildPermissionsManager?.remove({ command: globalCommandId, users: [testUserId], token: 'VeryRealToken' }); - await guildPermissionsManager?.remove({ command: globalCommandId, channels: [testGuildId], token: 'VeryRealToken' }); - await guildPermissionsManager?.remove({ - command: globalCommandId, - roles: [testGuildId], - users: [testUserId], - channels: [testGuildId], - token: 'VeryRealToken', - }); - await guildPermissionsManager?.set({ - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildPermissionsManager?.add({ - command: globalCommandId, - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildPermissionsManager?.has({ command: globalCommandId, guild: testGuildId, permissionId: testGuildId }); - // @ts-expect-error - await guildPermissionsManager?.fetch({ guild: testGuildId }); - // @ts-expect-error - await guildPermissionsManager?.fetch({ command: globalCommandId, guild: testGuildId }); - await guildPermissionsManager?.remove({ - command: globalCommandId, - // @ts-expect-error - guild: testGuildId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - await guildPermissionsManager?.remove({ - command: globalCommandId, - // @ts-expect-error - guild: testGuildId, - users: [testUserId], - token: 'VeryRealToken', - }); - await guildPermissionsManager?.remove({ - command: globalCommandId, - // @ts-expect-error - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildPermissionsManager?.set({ - command: globalCommandId, - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // @ts-expect-error - await guildPermissionsManager?.add({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildPermissionsManager?.has({ permissionId: testGuildId }); - // @ts-expect-error - await guildPermissionsManager?.remove({ roles: [testGuildId], token: 'VeryRealToken' }); - // @ts-expect-error - await guildPermissionsManager?.remove({ users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await guildPermissionsManager?.remove({ roles: [testGuildId], users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await guildPermissionsManager?.set({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // Permissions from cached global ApplicationCommand - await globalCommand?.permissions.add({ - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); - await globalCommand?.permissions.fetch({ guild: testGuildId }); - await globalCommand?.permissions.remove({ guild: testGuildId, roles: [testGuildId], token: 'VeryRealToken' }); - await globalCommand?.permissions.remove({ guild: testGuildId, users: [testUserId], token: 'VeryRealToken' }); - await globalCommand?.permissions.remove({ - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.set({ - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await globalCommand?.permissions.add({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.has({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - permissionId: testGuildId, - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalCommand?.permissions.fetch({ command: globalCommandId, guild: testGuildId, token: 'VeryRealToken' }); - await globalCommand?.permissions.remove({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.remove({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - users: [testUserId], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.remove({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await globalCommand?.permissions.set({ - // @ts-expect-error - command: globalCommandId, - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - // @ts-expect-error - await globalCommand?.permissions.add({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await globalCommand?.permissions.has({ permissionId: testGuildId }); - // @ts-expect-error - await globalCommand?.permissions.fetch({}); - // @ts-expect-error - await globalCommand?.permissions.remove({ roles: [testGuildId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalCommand?.permissions.remove({ users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalCommand?.permissions.remove({ roles: [testGuildId], users: [testUserId], token: 'VeryRealToken' }); - // @ts-expect-error - await globalCommand?.permissions.set({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - }); - - // Permissions from cached guild ApplicationCommand - await guildCommandFromGlobal?.permissions.add({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.has({ permissionId: testGuildId }); - await guildCommandFromGlobal?.permissions.fetch({}); - await guildCommandFromGlobal?.permissions.remove({ roles: [testGuildId], token: 'VeryRealToken' }); - await guildCommandFromGlobal?.permissions.remove({ users: [testUserId], token: 'VeryRealToken' }); - await guildCommandFromGlobal?.permissions.remove({ - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.set({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildCommandFromGlobal?.permissions.add({ - // @ts-expect-error - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildCommandFromGlobal?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); - await guildCommandFromGlobal?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.set({ - // @ts-expect-error - command: guildCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildCommandFromGlobal?.permissions.add({ - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildCommandFromGlobal?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); - await guildCommandFromGlobal?.permissions.remove({ - // @ts-expect-error - guild: testGuildId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildCommandFromGlobal?.permissions.remove({ guild: testGuildId, users: [testUserId], token: 'VeryRealToken' }); - await guildCommandFromGlobal?.permissions.remove({ - // @ts-expect-error - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGlobal?.permissions.set({ - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildCommandFromGuild?.permissions.add({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.has({ permissionId: testGuildId }); - await guildCommandFromGuild?.permissions.fetch({}); - await guildCommandFromGuild?.permissions.remove({ roles: [testGuildId], token: 'VeryRealToken' }); - await guildCommandFromGuild?.permissions.remove({ users: [testUserId], token: 'VeryRealToken' }); - await guildCommandFromGuild?.permissions.remove({ - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.set({ - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildCommandFromGuild?.permissions.add({ - // @ts-expect-error - command: globalCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildCommandFromGuild?.permissions.has({ command: guildCommandId, permissionId: testGuildId }); - await guildCommandFromGuild?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - roles: [testGuildId], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.remove({ - // @ts-expect-error - command: guildCommandId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.set({ - // @ts-expect-error - command: guildCommandId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - - await guildCommandFromGuild?.permissions.add({ - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); - // @ts-expect-error - await guildCommandFromGuild?.permissions.has({ guild: testGuildId, permissionId: testGuildId }); - // @ts-expect-error - await guildCommandFromGuild?.permissions.remove({ guild: testGuildId, roles: [testGuildId], token: 'VeryRealToken' }); - // @ts-expect-error - await guildCommandFromGuild?.permissions.remove({ guild: testGuildId, users: [testUserId], token: 'VeryRealToken' }); - await guildCommandFromGuild?.permissions.remove({ - // @ts-expect-error - guild: testGuildId, - roles: [testGuildId], - users: [testUserId], - token: 'VeryRealToken', - }); - await guildCommandFromGuild?.permissions.set({ - // @ts-expect-error - guild: testGuildId, - permissions: [{ type: ApplicationCommandPermissionType.Role, id: testGuildId, permission: true }], - token: 'VeryRealToken', - }); -}); - -client.on('roleCreate', ({ client }) => expectType>(client)); -client.on('roleDelete', ({ client }) => expectType>(client)); - -client.on('roleUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('stageInstanceCreate', ({ client }) => expectType>(client)); -client.on('stageInstanceDelete', ({ client }) => expectType>(client)); - -client.on('stageInstanceUpdate', (oldStageInstance, { client }) => { - expectType>(oldStageInstance!.client); - expectType>(client); -}); - -client.on('stickerCreate', ({ client }) => expectType>(client)); -client.on('stickerDelete', ({ client }) => expectType>(client)); - -client.on('stickerUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('threadCreate', thread => { - expectType>(thread.client); - - if (thread.type === ChannelType.PrivateThread) { - expectType(thread.createdTimestamp); - expectType(thread.createdAt); - } else { - expectType(thread.createdTimestamp); - expectType(thread.createdAt); - } -}); - -client.on('threadDelete', ({ client }) => expectType>(client)); - -client.on('threadListSync', (threads, { client }) => { - expectType>(threads.first()!.client); - expectType>(client); -}); - -client.on('threadMembersUpdate', (addedMembers, removedMembers, thread) => { - expectType>(addedMembers.first()!.client); - expectType>(removedMembers.first()!.client); - expectType>(thread.client); - expectType>(addedMembers); - expectType>(removedMembers); - expectType(thread); - const left = removedMembers.first(); - if (!left) return; - - if (left.partial) { - expectType(left); - expectType(left.flags); - } else { - expectType(left); - expectType(left.flags); - } -}); - -client.on('threadMemberUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('threadUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('typingStart', ({ client }) => expectType>(client)); - -client.on('userUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('voiceStateUpdate', ({ client: oldClient }, { client: newClient }) => { - expectType>(oldClient); - expectType>(newClient); -}); - -client.on('webhooksUpdate', ({ client }) => expectType>(client)); - -client.on('guildCreate', async g => { - expectType>(g.client); - const channel = g.channels.cache.random(); - if (!channel) return; - - if (channel.type === ChannelType.GuildText) { - const row: ActionRowData = { - type: ComponentType.ActionRow, - components: [ - new ButtonBuilder(), - { type: ComponentType.Button, style: ButtonStyle.Primary, label: 'string', customId: 'foo' }, - { type: ComponentType.Button, style: ButtonStyle.Link, label: 'test', url: 'test' }, - { type: ComponentType.StringSelect, customId: 'foo', options: [{ label: 'label', value: 'value' }] }, - new StringSelectMenuBuilder(), - // @ts-expect-error - { type: ComponentType.TextInput, style: TextInputStyle.Paragraph, customId: 'foo', label: 'test' }, - // @ts-expect-error - new TextInputBuilder(), - ], - }; - - const row2 = new ActionRowBuilder({ - type: ComponentType.ActionRow, - components: [ - { type: ComponentType.Button, style: ButtonStyle.Primary, label: 'string', customId: 'foo' }, - { type: ComponentType.Button, style: ButtonStyle.Link, label: 'test', url: 'test' }, - { type: ComponentType.StringSelect, customId: 'foo', options: [{ label: 'label', value: 'value' }] }, - ], - }); - - channel.send({ components: [row, row2] }); - } - - channel.setName('foo').then(updatedChannel => { - console.log(`New channel name: ${updatedChannel.name}`); - }); - - // @ts-expect-error no options - expectNotType>(g.members.add(testUserId)); - - // @ts-expect-error no access token - expectNotType>(g.members.add(testUserId, {})); - - expectNotType>( - // @ts-expect-error invalid role resolvable - g.members.add(testUserId, { accessToken: 'totallyRealAccessToken', roles: [g.roles.cache] }), - ); - - expectType>( - g.members.add(testUserId, { accessToken: 'totallyRealAccessToken', fetchWhenExisting: false }), - ); - - expectType>(g.members.add(testUserId, { accessToken: 'totallyRealAccessToken' })); - - expectType>( - g.members.add(testUserId, { - accessToken: 'totallyRealAccessToken', - mute: true, - deaf: false, - roles: [g.roles.cache.first()!], - force: true, - fetchWhenExisting: true, - }), - ); -}); - -// EventEmitter static method overrides -expectType]>>(Client.once(client, 'ready')); -expectType]>>(Client.on(client, 'ready')); - -client.login('absolutely-valid-token'); - -declare const loggedInClient: Client; -expectType(loggedInClient.application); -expectType(loggedInClient.readyAt); -expectType(loggedInClient.readyTimestamp); -expectType(loggedInClient.token); -expectType(loggedInClient.uptime); -expectType(loggedInClient.user); - -declare const loggedOutClient: Client; -expectType(loggedOutClient.application); -expectType(loggedOutClient.readyAt); -expectType(loggedOutClient.readyTimestamp); -expectType(loggedOutClient.token); -expectType(loggedOutClient.uptime); -expectType(loggedOutClient.user); - -expectType(serialize(undefined)); -expectType(serialize(null)); -expectType(serialize([1, 2, 3])); -expectType<{}>(serialize(new Set([1, 2, 3]))); -expectType<{}>( - serialize( - new Map([ - [1, '2'], - [2, '4'], - ]), - ), -); -expectType(serialize(new PermissionsBitField(PermissionFlagsBits.AttachFiles))); -expectType(serialize(new IntentsBitField(GatewayIntentBits.Guilds))); -expectAssignable( - serialize( - new Collection([ - [1, '2'], - [2, '4'], - ]), - ), -); -expectType(serialize(Symbol('a'))); -expectType(serialize(() => {})); -expectType(serialize(BigInt(42))); - -// Test type return of broadcastEval: -declare const shardClientUtil: ShardClientUtil; -declare const shardingManager: ShardingManager; - -expectType>(shardingManager.broadcastEval(() => 1)); -expectType>(shardClientUtil.broadcastEval(() => 1)); -expectType>(shardingManager.broadcastEval(async () => 1)); -expectType>(shardClientUtil.broadcastEval(async () => 1)); - -declare const dmChannel: DMChannel; -declare const threadChannel: ThreadChannel; -declare const threadChannelFromForum: ThreadChannel; -declare const threadChannelNotFromForum: ThreadChannel; -declare const newsChannel: NewsChannel; -declare const textChannel: TextChannel; -declare const voiceChannel: VoiceChannel; -declare const guild: Guild; -declare const user: User; -declare const guildMember: GuildMember; - -// Test thread channels' parent inference -expectType(threadChannel.parent); -expectType(threadChannelFromForum.parent); -expectType(threadChannelNotFromForum.parent); - -// Test whether the structures implement send -expectType['send']>(dmChannel.send); -expectType['send']>(threadChannel.send); -expectType['send']>(newsChannel.send); -expectType['send']>(textChannel.send); -expectType['send']>(voiceChannel.send); -expectAssignable(user); -expectAssignable(guildMember); - -expectType>(textChannel.setType(ChannelType.GuildAnnouncement)); -expectType>(newsChannel.setType(ChannelType.GuildText)); - -expectType(dmChannel.lastMessage); -expectType(threadChannel.lastMessage); -expectType(newsChannel.lastMessage); -expectType(textChannel.lastMessage); -expectType(voiceChannel.lastMessage); - -notPropertyOf(user, 'lastMessage'); -notPropertyOf(user, 'lastMessageId'); -notPropertyOf(guildMember, 'lastMessage'); -notPropertyOf(guildMember, 'lastMessageId'); - -// Test collector event parameters -declare const messageCollector: MessageCollector; -messageCollector.on('collect', (...args) => { - expectType<[Message, Collection]>(args); -}); - -(async () => { - for await (const value of messageCollector) { - expectType<[Message, Collection]>(value); - } -})(); - -declare const reactionCollector: ReactionCollector; -reactionCollector.on('dispose', (...args) => { - expectType<[MessageReaction, User]>(args); -}); - -(async () => { - for await (const value of reactionCollector) { - expectType<[MessageReaction, User]>(value); - } -})(); - -// Make sure the properties are typed correctly, and that no backwards properties -// (K -> V and V -> K) exist: -expectAssignable<'messageCreate'>(Events.MessageCreate); -expectAssignable<'close'>(WebSocketShardEvents.Close); -expectAssignable<'death'>(ShardEvents.Death); -expectAssignable<1>(Status.Connecting); - -declare const applicationCommandData: ApplicationCommandData; -declare const applicationCommandOptionData: ApplicationCommandOptionData; -declare const applicationCommandResolvable: ApplicationCommandResolvable; -declare const applicationCommandManager: ApplicationCommandManager; -{ - type ApplicationCommandScope = ApplicationCommand<{ guild: GuildResolvable }>; - - expectType>(applicationCommandManager.create(applicationCommandData)); - expectAssignable>(applicationCommandManager.create(applicationCommandData, '0')); - expectType>( - applicationCommandManager.edit(applicationCommandResolvable, applicationCommandData), - ); - expectType>( - applicationCommandManager.edit(applicationCommandResolvable, applicationCommandData, '0'), - ); - expectType>>( - applicationCommandManager.set([applicationCommandData]), - ); - expectType>>( - applicationCommandManager.set([applicationCommandData] as const, '0'), - ); - - // Test inference of choice values. - if ('choices' in applicationCommandOptionData) { - if (applicationCommandOptionData.type === ApplicationCommandOptionType.String) { - expectType(applicationCommandOptionData.choices[0]!.value); - expectNotType(applicationCommandOptionData.choices[0]!.value); - } - - if (applicationCommandOptionData.type === ApplicationCommandOptionType.Integer) { - expectType(applicationCommandOptionData.choices[0]!.value); - expectNotType(applicationCommandOptionData.choices[0]!.value); - } - - if (applicationCommandOptionData.type === ApplicationCommandOptionType.Number) { - expectType(applicationCommandOptionData.choices[0]!.value); - expectNotType(applicationCommandOptionData.choices[0]!.value); - } - } -} - -declare const applicationCommandPermissionsManager: ApplicationCommandPermissionsManager< - {}, - {}, - Guild | null, - Snowflake ->; -{ - applicationCommandPermissionsManager.add({ permissions: [], token: '' }); - applicationCommandPermissionsManager.add({ permissions: [] as const, token: '' }); - applicationCommandPermissionsManager.set({ permissions: [], token: '' }); - applicationCommandPermissionsManager.set({ permissions: [] as const, token: '' }); - applicationCommandPermissionsManager.remove({ channels: [], roles: [], users: [], token: '' }); - - applicationCommandPermissionsManager.remove({ - channels: [] as const, - roles: [] as const, - users: [] as const, - token: '', - }); -} - -declare const chatInputApplicationCommandData: ChatInputApplicationCommandData; -{ - chatInputApplicationCommandData.options = []; - chatInputApplicationCommandData.options = [] as const; -} - -declare const applicationCommandChannelOptionData: ApplicationCommandChannelOptionData; -declare const applicationCommandChannelOption: ApplicationCommandChannelOption; -{ - applicationCommandChannelOptionData.channelTypes = [] as const; - applicationCommandChannelOptionData.channel_types = [] as const; - applicationCommandChannelOption.channelTypes = [] as const; -} - -declare const applicationNonChoiceOptionData: ApplicationCommandOptionData & { - type: CommandOptionNonChoiceResolvableType; -}; -{ - // Options aren't allowed on this command type. - - // @ts-expect-error - applicationNonChoiceOptionData.choices; -} - -declare const applicationCommandChoicesData: ApplicationCommandChoicesData; -declare const applicationCommandChoicesOption: ApplicationCommandChoicesOption; -{ - applicationCommandChoicesData.choices = []; - applicationCommandChoicesData.choices = [] as const; - applicationCommandChoicesOption.choices = []; - applicationCommandChoicesOption.choices = [] as const; -} - -declare const applicationCommandSubCommandData: ApplicationCommandSubCommandData; -declare const applicationCommandSubCommand: ApplicationCommandSubCommand; -{ - applicationCommandSubCommandData.options = []; - applicationCommandSubCommandData.options = [] as const; - applicationCommandSubCommand.options = []; - applicationCommandSubCommand.options = [] as const; -} - -declare const applicationSubGroupCommandData: ApplicationCommandSubGroupData; -declare const applicationCommandSubGroup: ApplicationCommandSubGroup; -{ - expectType(applicationSubGroupCommandData.type); - applicationSubGroupCommandData.options = []; - applicationSubGroupCommandData.options = [] as const; - applicationCommandSubGroup.options = []; - applicationCommandSubGroup.options = [] as const; -} - -declare const autoModerationRuleManager: AutoModerationRuleManager; -{ - expectType>(autoModerationRuleManager.fetch('1234567890')); - expectType>(autoModerationRuleManager.fetch({ autoModerationRule: '1234567890' })); - expectType>( - autoModerationRuleManager.fetch({ autoModerationRule: '1234567890', cache: false }), - ); - expectType>( - autoModerationRuleManager.fetch({ autoModerationRule: '1234567890', force: true }), - ); - expectType>( - autoModerationRuleManager.fetch({ autoModerationRule: '1234567890', cache: false, force: true }), - ); - expectType>>(autoModerationRuleManager.fetch()); - expectType>>(autoModerationRuleManager.fetch({})); - expectType>>(autoModerationRuleManager.fetch({ cache: false })); - // @ts-expect-error The `force` option cannot be used alongside fetching all auto moderation rules. - autoModerationRuleManager.fetch({ force: false }); -} - -declare const guildApplicationCommandManager: GuildApplicationCommandManager; -expectType>>(guildApplicationCommandManager.fetch()); -expectType>>(guildApplicationCommandManager.fetch(undefined, {})); -expectType>(guildApplicationCommandManager.fetch('0')); - -declare const categoryChannelChildManager: CategoryChannelChildManager; -{ - expectType>(categoryChannelChildManager.create({ name: 'name', type: ChannelType.GuildVoice })); - expectType>(categoryChannelChildManager.create({ name: 'name', type: ChannelType.GuildText })); - expectType>( - categoryChannelChildManager.create({ name: 'name', type: ChannelType.GuildAnnouncement }), - ); - expectType>( - categoryChannelChildManager.create({ name: 'name', type: ChannelType.GuildStageVoice }), - ); - expectType>(categoryChannelChildManager.create({ name: 'name' })); - expectType>(categoryChannelChildManager.create({ name: 'name' })); -} - -declare const guildChannelManager: GuildChannelManager; -{ - expectType>(guildChannelManager.create({ name: 'name' })); - expectType>(guildChannelManager.create({ name: 'name' })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildVoice })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildCategory })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildText })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildAnnouncement })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildStageVoice })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildForum })); - expectType>(guildChannelManager.create({ name: 'name', type: ChannelType.GuildMedia })); - - expectType>>(guildChannelManager.fetch()); - expectType>>( - guildChannelManager.fetch(undefined, {}), - ); - expectType>(guildChannelManager.fetch('0')); - - const channel = guildChannelManager.cache.first()!; - - if (channel.isTextBased()) { - const { messages } = channel; - const message = await messages.fetch('123'); - expectType(messages); - expectType>>(messages.crosspost('1234567890')); - expectType>>(messages.edit('1234567890', 'text')); - expectType>>(messages.fetch('1234567890')); - expectType>>>(messages.fetchPinned()); - expectType(message.guild); - expectType(message.guildId); - expectType(message.channel.messages.channel); - } -} - -{ - const { messages } = dmChannel; - const message = await messages.fetch('123'); - expectType(messages); - expectType>(messages.edit('1234567890', 'text')); - expectType>(messages.fetch('1234567890')); - expectType>>(messages.fetchPinned()); - expectType(message.guild); - expectType(message.guildId); - expectType(message.channel.messages.channel); - expectType(message.mentions); - expectType(message.mentions.guild); - expectType | null>(message.mentions.members); - - if (messages.channel.isDMBased()) { - expectType(messages.channel); - expectType(messages.channel.messages.channel); - } - - // @ts-expect-error Crossposting is not possible in direct messages. - messages.crosspost('1234567890'); -} - -declare const threadManager: ThreadManager; -{ - expectType>(threadManager.fetch('12345678901234567')); - expectType>(threadManager.fetch('12345678901234567', { cache: true, force: false })); - expectType>(threadManager.fetch()); - expectType>(threadManager.fetch({})); - expectType>(threadManager.fetch({ archived: { limit: 4 } })); - - // @ts-expect-error The force option has no effect here. - threadManager.fetch({ archived: {} }, { force: true }); -} - -declare const guildForumThreadManager: GuildForumThreadManager; -expectType(guildForumThreadManager.channel); - -declare const guildTextThreadManager: GuildTextThreadManager< - ChannelType.PublicThread | ChannelType.PrivateThread | ChannelType.AnnouncementThread ->; -expectType(guildTextThreadManager.channel); - -declare const guildMemberManager: GuildMemberManager; -{ - expectType>(guildMemberManager.fetch('12345678901234567')); - expectType>(guildMemberManager.fetch({ user: '12345678901234567' })); - expectType>(guildMemberManager.fetch({ user: '12345678901234567', cache: true, force: false })); - expectType>(guildMemberManager.fetch({ user: '12345678901234567', cache: true, force: false })); - expectType>>(guildMemberManager.fetch()); - expectType>>(guildMemberManager.fetch({})); - expectType>>(guildMemberManager.fetch({ user: ['12345678901234567'] })); - expectType>>(guildMemberManager.fetch({ withPresences: false })); - expectType>(guildMemberManager.fetch({ user: '12345678901234567', withPresences: true })); - - expectType>>( - guildMemberManager.fetch({ query: 'test', user: ['12345678901234567'], nonce: 'test' }), - ); - - // @ts-expect-error The cache & force options have no effect here. - guildMemberManager.fetch({ cache: true, force: false }); - // @ts-expect-error The force option has no effect here. - guildMemberManager.fetch({ user: ['12345678901234567'], cache: true, force: false }); -} - -declare const messageManager: MessageManager; -{ - expectType>(messageManager.fetch('1234567890')); - expectType>(messageManager.fetch({ message: '1234567890' })); - expectType>(messageManager.fetch({ message: '1234567890', cache: true, force: false })); - expectType>>(messageManager.fetch()); - expectType>>(messageManager.fetch({})); - expectType>>( - messageManager.fetch({ limit: 100, before: '1234567890', cache: false }), - ); - // @ts-expect-error - messageManager.fetch({ cache: true, force: false }); - // @ts-expect-error - messageManager.fetch({ message: '1234567890', after: '1234567890', cache: true, force: false }); -} - -declare const roleManager: RoleManager; -expectType>>(roleManager.fetch()); -expectType>>(roleManager.fetch(undefined, {})); -expectType>(roleManager.fetch('0')); - -declare const guildEmojiManager: GuildEmojiManager; -expectType>>(guildEmojiManager.fetch()); -expectType>>(guildEmojiManager.fetch(undefined, {})); -expectType>(guildEmojiManager.fetch('0')); - -declare const applicationEmojiManager: ApplicationEmojiManager; -expectType>>(applicationEmojiManager.fetch()); -expectType>>(applicationEmojiManager.fetch(undefined, {})); -expectType>(applicationEmojiManager.fetch('0')); - -declare const guildBanManager: GuildBanManager; -{ - expectType>(guildBanManager.fetch('1234567890')); - expectType>(guildBanManager.fetch({ user: '1234567890' })); - expectType>(guildBanManager.fetch({ user: '1234567890', cache: true, force: false })); - expectType>>(guildBanManager.fetch()); - expectType>>(guildBanManager.fetch({})); - expectType>>(guildBanManager.fetch({ limit: 100, before: '1234567890' })); - // @ts-expect-error - guildBanManager.fetch({ cache: true, force: false }); - // @ts-expect-error - guildBanManager.fetch({ user: '1234567890', after: '1234567890', cache: true, force: false }); -} - -declare const threadMemberWithGuildMember: ThreadMember; -declare const threadMemberManager: ThreadMemberManager; -{ - expectType>(threadMemberManager.fetch('12345678')); - expectType>(threadMemberManager.fetch({ member: '12345678', cache: false })); - expectType>(threadMemberManager.fetch({ member: '12345678', force: true })); - expectType>>(threadMemberManager.fetch({ member: threadMemberWithGuildMember })); - expectType>>(threadMemberManager.fetch({ member: '12345678901234567', withMember: true })); - expectType>>(threadMemberManager.fetch()); - expectType>>(threadMemberManager.fetch({})); - - expectType>>>( - threadMemberManager.fetch({ cache: true, limit: 50, withMember: true, after: '12345678901234567' }), - ); - - expectType>>( - threadMemberManager.fetch({ cache: true, withMember: false }), - ); - - // @ts-expect-error The `force` option cannot be used alongside fetching all thread members. - threadMemberManager.fetch({ cache: true, force: false }); - // @ts-expect-error `withMember` needs to be `true` to receive paginated results. - threadMemberManager.fetch({ withMember: false, limit: 5, after: '12345678901234567' }); -} - -declare const typing: Typing; -expectType(typing.user); -if (typing.user.partial) expectType(typing.user.username); -if (!typing.user.partial) expectType(typing.user.tag); - -expectType(typing.channel); -if (typing.channel.partial) expectType(typing.channel.lastMessageId); - -expectType(typing.member); -expectType(typing.guild); - -if (typing.inGuild()) { - expectType(typing.channel.guild); - expectType(typing.guild); -} - -// Test interactions -declare const interaction: Interaction; -declare const booleanValue: boolean; -if (interaction.inGuild()) { - expectType(interaction.guildId); -} else { - expectType(interaction.guildId); -} - -client.on('interactionCreate', async interaction => { - if (interaction.type === InteractionType.MessageComponent) { - expectType(interaction); - expectType(interaction.component); - expectType(interaction.message); - expectDeprecated(interaction.sendPremiumRequired()); - if (interaction.inCachedGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.update({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferUpdate({ fetchReply: true })); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.update({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferUpdate({ fetchReply: true })); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType(interaction.message); - expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); - expectType>(interaction.editReply({ content: 'a' })); - expectType>(interaction.fetchReply()); - expectType>(interaction.update({ content: 'a', fetchReply: true })); - expectType>(interaction.deferUpdate({ fetchReply: true })); - expectType>(interaction.followUp({ content: 'a' })); - } - } - - if (interaction.inCachedGuild()) { - expectAssignable(interaction.member); - expectNotType>(interaction); - expectAssignable(interaction); - expectType(interaction.guildLocale); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction.member); - expectNotAssignable>(interaction); - expectType(interaction.guildLocale); - } else if (interaction.inGuild()) { - expectType(interaction.guildLocale); - } else { - expectType(interaction.member); - expectNotAssignable>(interaction); - expectType(interaction.guildId); - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - (interaction.commandType === ApplicationCommandType.User || - interaction.commandType === ApplicationCommandType.Message) - ) { - expectType(interaction); - // @ts-expect-error No attachment options on contextmenu commands - interaction.options.getAttachment('name'); - if (interaction.inCachedGuild()) { - expectAssignable(interaction); - expectAssignable(interaction.guild); - expectAssignable>(interaction); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction); - expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inGuild()) { - expectAssignable(interaction); - expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); - expectType>(interaction.editReply({ content: 'a' })); - expectType>(interaction.fetchReply()); - expectType>(interaction.followUp({ content: 'a' })); - } - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - interaction.commandType === ApplicationCommandType.Message - ) { - expectType(interaction.targetMessage); - expectType(interaction.options.getMessage('_MESSAGE')); - if (interaction.inCachedGuild()) { - expectType>(interaction.targetMessage); - expectType | null>(interaction.options.getMessage('_MESSAGE')); - } else if (interaction.inRawGuild()) { - expectType>(interaction.targetMessage); - expectType | null>(interaction.options.getMessage('_MESSAGE')); - } else if (interaction.inGuild()) { - expectType(interaction.targetMessage); - expectType(interaction.options.getMessage('_MESSAGE')); - } - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - interaction.commandType === ApplicationCommandType.User - ) { - expectType(interaction.targetUser); - expectType(interaction.targetMember); - expectType(interaction.options.getUser('user')); - expectType(interaction.options.getMember('user')); - if (interaction.inCachedGuild()) { - expectType(interaction.targetMember); - expectType(interaction.options.getMember('user')); - } else if (interaction.inRawGuild()) { - expectType(interaction.targetMember); - expectType(interaction.options.getMember('user')); - } else if (interaction.inGuild()) { - expectType(interaction.targetMember); - expectType(interaction.options.getMember('user')); - } - } - - if (interaction.type === InteractionType.MessageComponent && interaction.componentType === ComponentType.Button) { - expectType(interaction); - expectType(interaction.component); - expectType(interaction.message); - if (interaction.inCachedGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); - } else if (interaction.inGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType(interaction.message); - expectAssignable(interaction.guild); - expectType>(interaction.reply({ fetchReply: true })); - } - } - - if ( - interaction.type === InteractionType.MessageComponent && - interaction.componentType === ComponentType.StringSelect - ) { - expectType(interaction); - expectType(interaction.component); - expectType(interaction.message); - if (interaction.inCachedGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType>(interaction.message); - expectType(interaction.guild); - expectType>>(interaction.reply({ fetchReply: true })); - } else if (interaction.inGuild()) { - expectAssignable(interaction); - expectType(interaction.component); - expectType(interaction.message); - expectType(interaction.guild); - expectType>(interaction.reply({ fetchReply: true })); - } - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - interaction.commandType === ApplicationCommandType.ChatInput - ) { - expectDeprecated(interaction.sendPremiumRequired()); - if (interaction.inRawGuild()) { - expectNotAssignable>(interaction); - expectAssignable(interaction); - expectType>>(interaction.reply({ fetchReply: true })); - expectType(interaction.options.getMember('test')); - - expectType(interaction.options.getChannel('test', true)); - expectType(interaction.options.getRole('test', true)); - } else if (interaction.inCachedGuild()) { - const msg = await interaction.reply({ fetchReply: true }); - const btn = await msg.awaitMessageComponent({ componentType: ComponentType.Button }); - - expectType>(msg); - expectType>(btn); - - expectType(interaction.options.getMember('test')); - expectAssignable(interaction); - expectType>>(interaction.reply({ fetchReply: true })); - - expectType(interaction.options.getChannel('test', true)); - expectType(interaction.options.getRole('test', true)); - - expectType(interaction.options.getChannel('test', true, [ChannelType.PublicThread])); - expectType(interaction.options.getChannel('test', true, [ChannelType.AnnouncementThread])); - expectType( - interaction.options.getChannel('test', true, [ChannelType.PublicThread, ChannelType.AnnouncementThread]), - ); - expectType(interaction.options.getChannel('test', true, [ChannelType.PrivateThread])); - - expectType(interaction.options.getChannel('test', true, [ChannelType.GuildText])); - expectType(interaction.options.getChannel('test', false, [ChannelType.GuildText])); - expectType( - interaction.options.getChannel('test', true, [ChannelType.GuildForum, ChannelType.GuildVoice]), - ); - expectType(interaction.options.getChannel('test', true, [ChannelType.GuildText] as const)); - expectType( - interaction.options.getChannel('test', false, [ChannelType.GuildForum, ChannelType.GuildVoice]), - ); - expectType(interaction.options.getChannel('test', true, [ChannelType.GuildMedia])); - } else { - // @ts-expect-error - consumeCachedCommand(interaction); - expectType(interaction); - expectType>(interaction.reply({ fetchReply: true })); - expectType(interaction.options.getMember('test')); - - expectType(interaction.options.getChannel('test', true)); - expectType(interaction.options.getRole('test', true)); - } - - expectType(interaction); - expectType, 'getFocused' | 'getMessage'>>(interaction.options); - expectType(interaction.options.data); - - const optionalOption = interaction.options.get('name'); - const requiredOption = interaction.options.get('name', true); - expectType(optionalOption); - expectType(requiredOption); - expectType(requiredOption.options); - - expectType(interaction.options.getString('name', booleanValue)); - expectType(interaction.options.getString('name', false)); - expectType(interaction.options.getString('name', true)); - - expectType(interaction.options.getSubcommand()); - expectType(interaction.options.getSubcommand(true)); - expectType(interaction.options.getSubcommand(booleanValue)); - expectType(interaction.options.getSubcommand(false)); - - expectType(interaction.options.getSubcommandGroup(true)); - expectType(interaction.options.getSubcommandGroup()); - expectType(interaction.options.getSubcommandGroup(booleanValue)); - expectType(interaction.options.getSubcommandGroup(false)); - - // @ts-expect-error - interaction.options.getMessage('name'); - } - - if (interaction.isRepliable()) { - expectAssignable(interaction); - interaction.reply('test'); - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - interaction.commandType === ApplicationCommandType.ChatInput && - interaction.isRepliable() - ) { - expectAssignable(interaction); - expectAssignable(interaction); - } - - if (interaction.type === InteractionType.ModalSubmit && interaction.isRepliable()) { - expectType(interaction); - if (interaction.inCachedGuild()) { - expectAssignable(interaction); - expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.deferUpdate({ fetchReply: true })); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inRawGuild()) { - expectAssignable(interaction); - expectType(interaction.guild); - expectType>>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>>(interaction.deferReply({ fetchReply: true })); - expectType>>(interaction.editReply({ content: 'a' })); - expectType>>(interaction.fetchReply()); - expectType>>(interaction.deferUpdate({ fetchReply: true })); - expectType>>(interaction.followUp({ content: 'a' })); - } else if (interaction.inGuild()) { - expectAssignable(interaction); - expectType(interaction.guild); - expectType>(interaction.reply({ content: 'a', fetchReply: true })); - expectType>(interaction.deferReply({ fetchReply: true })); - expectType>(interaction.editReply({ content: 'a' })); - expectType>(interaction.fetchReply()); - expectType>(interaction.deferUpdate({ fetchReply: true })); - expectType>(interaction.followUp({ content: 'a' })); - } - } - - if (interaction.isModalSubmit()) { - expectDeprecated(interaction.sendPremiumRequired()); - } -}); - -declare const shard: Shard; - -shard.on('death', process => { - expectType(process); -}); - -declare const webSocketShard: WebSocketShard; - -webSocketShard.on('close', event => { - expectType(event); -}); - -declare const collector: Collector; - -collector.on('collect', (collected, ...other) => { - expectType(collected); - expectType(other); -}); - -collector.on('dispose', (vals, ...other) => { - expectType(vals); - expectType(other); -}); - -collector.on('end', (collection, reason) => { - expectType>(collection); - expectType(reason); -}); - -(async () => { - for await (const value of collector) { - expectType<[Interaction, ...string[]]>(value); - } -})(); - -expectType>(shard.eval(client => client.readyTimestamp)); - -// Test audit logs -expectType>>(guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick })); - -expectType>>( - guild.fetchAuditLogs({ type: AuditLogEvent.ChannelCreate }), -); - -expectType>>( - guild.fetchAuditLogs({ type: AuditLogEvent.IntegrationUpdate }), -); - -expectType>>(guild.fetchAuditLogs({ type: null })); -expectType>>(guild.fetchAuditLogs()); - -expectType | undefined>>( - guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()), -); -expectAssignable | undefined>>( - guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()), -); - -expectType | undefined>>( - guild.fetchAuditLogs({ type: null }).then(al => al.entries.first()), -); -expectType | undefined>>( - guild.fetchAuditLogs().then(al => al.entries.first()), -); - -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()?.extra), -); - -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.MemberRoleUpdate }).then(al => al.entries.first()?.extra), -); - -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.StageInstanceCreate }).then(al => al.entries.first()?.extra), -); -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.MessageDelete }).then(al => al.entries.first()?.extra), -); - -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()?.target), -); -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.StageInstanceCreate }).then(al => al.entries.first()?.target), -); -expectType>( - guild.fetchAuditLogs({ type: AuditLogEvent.MessageDelete }).then(al => al.entries.first()?.target), -); - -declare const AuditLogChange: AuditLogChange; -// @ts-expect-error -expectType(AuditLogChange.old); -// @ts-expect-error -expectType(AuditLogChange.new); -if (AuditLogChange.key === 'available') { - expectType(AuditLogChange.old); - expectType(AuditLogChange.new); -} - -declare const TextBasedChannel: TextBasedChannel; -declare const TextBasedChannelTypes: TextBasedChannelTypes; -declare const VoiceBasedChannel: VoiceBasedChannel; -declare const GuildBasedChannel: GuildBasedChannel; -declare const NonThreadGuildBasedChannel: NonThreadGuildBasedChannel; -declare const GuildTextBasedChannel: GuildTextBasedChannel; - -expectType(TextBasedChannel); -expectType< - | ChannelType.GuildText - | ChannelType.DM - | ChannelType.GroupDM - | ChannelType.GuildAnnouncement - | ChannelType.GuildVoice - | ChannelType.GuildStageVoice - | ThreadChannelType ->(TextBasedChannelTypes); -expectType(VoiceBasedChannel); -expectType(GuildBasedChannel); -expectType( - NonThreadGuildBasedChannel, -); -expectType(GuildTextBasedChannel); - -const button = new ButtonBuilder({ - label: 'test', - style: ButtonStyle.Primary, - customId: 'test', -}); - -const selectMenu = new StringSelectMenuBuilder({ - maxValues: 10, - minValues: 2, - customId: 'test', -}); - -new ActionRowBuilder({ - components: [selectMenu.toJSON(), button.toJSON()], -}); - -new StringSelectMenuBuilder({ - customId: 'foo', -}); - -new ButtonBuilder({ - style: ButtonStyle.Danger, -}) - .setEmoji('') - .setEmoji('<:foo:123>') - .setEmoji('foobar:123') - .setEmoji('😏') - .setEmoji({ - name: 'test', - id: '123', - animated: false, - }); - -// @ts-expect-error -new EmbedBuilder().setColor('abc'); - -new EmbedBuilder().setColor('#ffffff'); - -expectNotAssignable>({ - type: ComponentType.ActionRow, - components: [ - { - type: ComponentType.Button, - }, - ], -}); - -declare const chatInputInteraction: ChatInputCommandInteraction; - -expectType(chatInputInteraction.options.getAttachment('attachment', true)); -expectType(chatInputInteraction.options.getAttachment('attachment')); - -declare const modal: ModalBuilder; - -chatInputInteraction.showModal(modal); - -chatInputInteraction.showModal({ - title: 'abc', - custom_id: 'abc', - components: [ - { - components: [ - { - custom_id: 'aa', - label: 'label', - style: TextInputStyle.Short, - type: ComponentType.TextInput, - }, - ], - type: ComponentType.ActionRow, - }, - ], -}); - -declare const stringSelectMenuData: APIStringSelectComponent; -StringSelectMenuBuilder.from(stringSelectMenuData); - -declare const userSelectMenuData: APIUserSelectComponent; -UserSelectMenuBuilder.from(userSelectMenuData); - -declare const roleSelectMenuData: APIRoleSelectComponent; -RoleSelectMenuBuilder.from(roleSelectMenuData); - -declare const channelSelectMenuData: APIChannelSelectComponent; -ChannelSelectMenuBuilder.from(channelSelectMenuData); - -declare const mentionableSelectMenuData: APIMentionableSelectComponent; -MentionableSelectMenuBuilder.from(mentionableSelectMenuData); - -declare const stringSelectMenuComp: StringSelectMenuComponent; -StringSelectMenuBuilder.from(stringSelectMenuComp); - -declare const userSelectMenuComp: UserSelectMenuComponent; -UserSelectMenuBuilder.from(userSelectMenuComp); - -declare const roleSelectMenuComp: RoleSelectMenuComponent; -RoleSelectMenuBuilder.from(roleSelectMenuComp); - -declare const channelSelectMenuComp: ChannelSelectMenuComponent; -ChannelSelectMenuBuilder.from(channelSelectMenuComp); - -declare const mentionableSelectMenuComp: MentionableSelectMenuComponent; -MentionableSelectMenuBuilder.from(mentionableSelectMenuComp); - -declare const buttonData: APIButtonComponent; -ButtonBuilder.from(buttonData); - -declare const buttonComp: ButtonComponent; -ButtonBuilder.from(buttonComp); - -declare const modalData: APIModalInteractionResponseCallbackData; -ModalBuilder.from(modalData); - -declare const textInputData: APITextInputComponent; -TextInputBuilder.from(textInputData); - -declare const textInputComp: TextInputComponent; -TextInputBuilder.from(textInputComp); - -declare const embedData: APIEmbed; -EmbedBuilder.from(embedData); - -declare const embedComp: Embed; -EmbedBuilder.from(embedComp); - -declare const actionRowData: APIActionRowComponent; -ActionRowBuilder.from(actionRowData); - -declare const actionRowComp: ActionRow; -ActionRowBuilder.from(actionRowComp); - -declare const buttonsActionRowData: APIActionRowComponent; -declare const buttonsActionRowComp: ActionRow; - -expectType>(ActionRowBuilder.from(buttonsActionRowData)); -expectType>(ActionRowBuilder.from(buttonsActionRowComp)); - -declare const anyComponentsActionRowData: APIActionRowComponent; -declare const anyComponentsActionRowComp: ActionRow; - -expectType(ActionRowBuilder.from(anyComponentsActionRowData)); -expectType(ActionRowBuilder.from(anyComponentsActionRowComp)); - -type UserMentionChannels = DMChannel | PartialDMChannel; -declare const channelMentionChannels: Exclude; -declare const userMentionChannels: UserMentionChannels; - -expectType(channelMentionChannels.toString()); -expectType(userMentionChannels.toString()); -expectType(user.toString()); -expectType(guildMember.toString()); - -declare const webhook: Webhook; -declare const webhookClient: WebhookClient; -declare const interactionWebhook: InteractionWebhook; -declare const snowflake: Snowflake; - -expectType>(webhook.send('content')); -expectType>(webhook.editMessage(snowflake, 'content')); -expectType>(webhook.fetchMessage(snowflake)); -expectType>(webhook.edit({ name: 'name' })); - -expectType>(webhookClient.send('content')); -expectType>(webhookClient.editMessage(snowflake, 'content')); -expectType>(webhookClient.fetchMessage(snowflake)); - -expectType>(interactionWebhook.client); -expectType>(interactionWebhook.send('content')); -expectType>(interactionWebhook.editMessage(snowflake, 'content')); -expectType>(interactionWebhook.fetchMessage(snowflake)); - -declare const partialGroupDMChannel: PartialGroupDMChannel; -declare const categoryChannel: CategoryChannel; -declare const stageChannel: StageChannel; -declare const forumChannel: ForumChannel; - -await forumChannel.edit({ - availableTags: [...forumChannel.availableTags, { name: 'tag' }], -}); - -await forumChannel.setAvailableTags([{ ...forumChannel.availableTags, name: 'tag' }]); -await forumChannel.setAvailableTags([{ name: 'tag' }]); - -expectType>(textChannel.flags); -expectType>(voiceChannel.flags); -expectType>(stageChannel.flags); -expectType>(forumChannel.flags); -expectType>(dmChannel.flags); -expectType>(categoryChannel.flags); -expectType>(newsChannel.flags); -expectType>(categoryChannel.flags); -expectType>(threadChannel.flags); - -expectType(partialGroupDMChannel.flags); - -// Select menu type narrowing -if (interaction.isAnySelectMenu()) { - expectType(interaction); -} - -declare const anySelectMenu: AnySelectMenuInteraction; - -if (anySelectMenu.isStringSelectMenu()) { - expectType(anySelectMenu); -} else if (anySelectMenu.isUserSelectMenu()) { - expectType(anySelectMenu); -} else if (anySelectMenu.isRoleSelectMenu()) { - expectType(anySelectMenu); -} else if (anySelectMenu.isChannelSelectMenu()) { - expectType(anySelectMenu); -} else if (anySelectMenu.isMentionableSelectMenu()) { - expectType(anySelectMenu); -} - -client.on('guildAuditLogEntryCreate', (auditLogEntry, guild) => { - expectType(auditLogEntry); - expectType(guild); -}); - -expectType>(guildMember.flags); - -declare const emojiResolvable: GuildEmoji | Emoji | string; - -{ - const onboarding = await guild.fetchOnboarding(); - expectType(onboarding); - - expectType(await guild.editOnboarding(onboarding)); - - await guild.editOnboarding({ - defaultChannels: onboarding.defaultChannels, - enabled: onboarding.enabled, - mode: onboarding.mode, - prompts: onboarding.prompts, - }); - - const prompt = onboarding.prompts.first()!; - const option = prompt.options.first()!; - - await guild.editOnboarding({ prompts: [prompt] }); - await guild.editOnboarding({ prompts: [{ ...prompt, options: [option] }] }); - - await guild.editOnboarding({ prompts: [{ ...prompt, options: [{ ...option, emoji: emojiResolvable }] }] }); -} - -declare const partialDMChannel: PartialDMChannel; -expectType(partialDMChannel.partial); -expectType(partialDMChannel.lastMessageId); - -declare const partialGuildMember: PartialGuildMember; -expectType(partialGuildMember.partial); -expectType(partialGuildMember.joinedAt); -expectType(partialGuildMember.joinedTimestamp); -expectType(partialGuildMember.pending); - -declare const partialMessage: PartialMessage; -expectType(partialMessage.partial); -expectType(partialMessage.type); -expectType(partialMessage.system); -expectType(partialMessage.pinned); -expectType(partialMessage.tts); -expectAssignable(partialMessage.content); -expectAssignable(partialMessage.cleanContent); -expectAssignable(partialMessage.author); - -declare const partialMessageReaction: PartialMessageReaction; -expectType(partialMessageReaction.partial); -expectType(partialMessageReaction.count); - -declare const partialThreadMember: PartialThreadMember; -expectType(partialThreadMember.partial); -expectType(partialThreadMember.flags); -expectType(partialThreadMember.joinedAt); -expectType(partialThreadMember.joinedTimestamp); - -declare const partialUser: PartialUser; -expectType(partialUser.partial); -expectType(partialUser.username); -expectType(partialUser.tag); -expectType(partialUser.discriminator); - -declare const emoji: Emoji; -{ - expectType(resolvePartialEmoji('12345678901234567')); - expectType(resolvePartialEmoji(emoji)); -} - -declare const application: ClientApplication; -declare const entitlement: Entitlement; -declare const sku: SKU; -{ - expectType>(await application.fetchSKUs()); - expectType>(await application.entitlements.fetch()); - - await application.entitlements.fetch({ - guild, - skus: ['12345678901234567', sku], - user, - excludeEnded: true, - limit: 10, - }); - - await application.entitlements.createTest({ sku: '12345678901234567', user }); - await application.entitlements.createTest({ sku, guild }); - - await application.entitlements.deleteTest(entitlement); - - await application.entitlements.consume(snowflake); - - expectType(entitlement.isActive()); - - if (entitlement.isUserSubscription()) { - expectType(entitlement.userId); - expectType(await entitlement.fetchUser()); - expectType(entitlement.guildId); - expectType(entitlement.guild); - - await application.entitlements.deleteTest(entitlement); - } else if (entitlement.isGuildSubscription()) { - expectType(entitlement.guildId); - expectType(entitlement.guild); - - await application.entitlements.deleteTest(entitlement); - } - - if (entitlement.isTest()) { - expectType(entitlement.startsTimestamp); - expectType(entitlement.endsTimestamp); - expectType(entitlement.startsAt); - expectType(entitlement.endsAt); - } - - client.on(Events.InteractionCreate, async interaction => { - expectType>(interaction.entitlements); - - if (interaction.isRepliable()) { - await interaction.sendPremiumRequired(); - } - }); -} - -await textChannel.send({ - poll: { - question: { - text: 'Question', - }, - duration: 60, - answers: [{ text: 'Answer 1' }, { text: 'Answer 2', emoji: '<:1blade:874989932983238726>' }], - allowMultiselect: false, - }, -}); - -declare const poll: Poll; -{ - expectType(await poll.end()); - - const answer = poll.answers.first()!; - expectType(answer.voteCount); - - expectType>(await answer.fetchVoters({ after: snowflake, limit: 10 })); - - await messageManager.endPoll(snowflake); - await messageManager.fetchPollAnswerVoters({ - messageId: snowflake, - answerId: 1, - }); -} - -expectType>(await client.fetchStickerPacks()); -expectType>(await client.fetchStickerPacks({})); -expectType(await client.fetchStickerPacks({ packId: snowflake })); +console.log('The real tests are the builds we failed along the way.'); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2aea244c6..7615b8d54 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -680,8 +680,8 @@ importers: specifier: ^4.0.0 version: 4.0.0 discord-api-types: - specifier: ^0.38.16 - version: 0.38.16 + specifier: ^0.38.26 + version: 0.38.26 fast-deep-equal: specifier: ^3.1.3 version: 3.1.3 @@ -2601,12 +2601,12 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@definitelytyped/header-parser@0.2.19': - resolution: {integrity: sha512-zu+RxQpUCgorYUQZoyyrRIn9CljL1CeM4qak3NDeMO1r7tjAkodfpAGnVzx/6JR2OUk0tAgwmZxNMSwd9LVgxw==} + '@definitelytyped/header-parser@0.2.20': + resolution: {integrity: sha512-97YPAlUo8XjWNtZ+6k+My+50/ljE2iX6KEPjOZ1Az1RsZdKwJ6taAX3F5g6SY1SJr50bzdm2RZzyQNdRmHcs4w==} engines: {node: '>=18.18.0'} - '@definitelytyped/typescript-versions@0.1.8': - resolution: {integrity: sha512-iz6q9aTwWW7CzN2g8jFQfZ955D63LA+wdIAKz4+2pCc/7kokmEHie1/jVWSczqLFOlmH+69bWQxIurryBP/sig==} + '@definitelytyped/typescript-versions@0.1.9': + resolution: {integrity: sha512-Qjalw9eNlcTjXhzx0Q6kHKuRCOUt/M5RGGRGKsiYlm/nveGvPX9liZSQlGXZVwyQ5I9qvq/GdaWiPchQ+ZXOrQ==} engines: {node: '>=18.18.0'} '@definitelytyped/utils@0.1.8': @@ -7490,6 +7490,15 @@ packages: supports-color: optional: true + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -7644,6 +7653,9 @@ packages: discord-api-types@0.38.16: resolution: {integrity: sha512-Cz42dC5WqJD17Yk0bRy7YLTJmh3NKo4FGpxZuA8MHqT0RPxKSrll5YhlODZ2z5DiEV/gpHMeTSrTFTWpSXjT1Q==} + discord-api-types@0.38.26: + resolution: {integrity: sha512-xpmPviHjIJ6dFu1eNwNDIGQ3N6qmPUUYFVAx/YZ64h7ZgPkTcKjnciD8bZe8Vbeji7yS5uYljyciunpq0J5NSw==} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -8656,8 +8668,8 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-tsconfig@4.10.0: - resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} get-tsconfig@4.7.6: resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} @@ -11434,6 +11446,11 @@ packages: engines: {node: '>=14'} hasBin: true + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + pretty-format@24.9.0: resolution: {integrity: sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==} engines: {node: '>= 6'} @@ -12078,6 +12095,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} @@ -12817,6 +12839,9 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tslint@5.14.0: resolution: {integrity: sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==} engines: {node: '>=4.8.0'} @@ -14686,7 +14711,7 @@ snapshots: '@commitlint/is-ignored@19.2.2': dependencies: '@commitlint/types': 19.0.3 - semver: 7.6.3 + semver: 7.7.2 '@commitlint/lint@19.2.2': dependencies: @@ -14855,13 +14880,13 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@definitelytyped/header-parser@0.2.19': + '@definitelytyped/header-parser@0.2.20': dependencies: - '@definitelytyped/typescript-versions': 0.1.8 + '@definitelytyped/typescript-versions': 0.1.9 '@definitelytyped/utils': 0.1.8 - semver: 7.6.3 + semver: 7.7.2 - '@definitelytyped/typescript-versions@0.1.8': {} + '@definitelytyped/typescript-versions@0.1.9': {} '@definitelytyped/utils@0.1.8': dependencies: @@ -14887,7 +14912,7 @@ snapshots: '@vladfrangu/async_event_emitter': 2.4.6 discord-api-types: 0.37.83 magic-bytes.js: 1.10.0 - tslib: 2.6.3 + tslib: 2.8.1 undici: 6.13.0 '@discordjs/util@1.1.0': {} @@ -14901,7 +14926,7 @@ snapshots: '@types/ws': 8.5.12 '@vladfrangu/async_event_emitter': 2.4.6 discord-api-types: 0.37.83 - tslib: 2.6.3 + tslib: 2.8.1 ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4) transitivePeerDependencies: - bufferutil @@ -14952,7 +14977,7 @@ snapshots: '@emnapi/runtime@1.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 optional: true '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1)': @@ -14968,7 +14993,7 @@ snapshots: '@esbuild-plugins/node-resolve@0.1.4(esbuild@0.18.20)': dependencies: '@types/resolve': 1.20.6 - debug: 4.4.0 + debug: 4.4.3 esbuild: 0.18.20 escape-string-regexp: 4.0.0 resolve: 1.22.10 @@ -15264,26 +15289,26 @@ snapshots: '@formatjs/ecma402-abstract@2.0.0': dependencies: '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.6.3 + tslib: 2.8.1 '@formatjs/fast-memoize@2.2.0': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@formatjs/icu-messageformat-parser@2.7.8': dependencies: '@formatjs/ecma402-abstract': 2.0.0 '@formatjs/icu-skeleton-parser': 1.8.2 - tslib: 2.6.3 + tslib: 2.8.1 '@formatjs/icu-skeleton-parser@1.8.2': dependencies: '@formatjs/ecma402-abstract': 2.0.0 - tslib: 2.6.3 + tslib: 2.8.1 '@formatjs/intl-localematcher@0.5.4': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@grpc/grpc-js@1.11.1': dependencies: @@ -15454,14 +15479,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.19.45 + '@types/node': 18.19.74 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.45)(ts-node@10.9.2(@types/node@16.18.105)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@18.19.74)(ts-node@10.9.2(@types/node@16.18.105)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -15489,14 +15514,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 18.19.45 + '@types/node': 18.19.74 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.45)(ts-node@10.9.2(@types/node@18.19.45)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@18.19.74)(ts-node@10.9.2(@types/node@18.19.45)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -15637,7 +15662,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 18.19.45 + '@types/node': 18.19.74 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -15683,7 +15708,7 @@ snapshots: '@js-temporal/polyfill@0.4.4': dependencies: jsbi: 4.3.0 - tslib: 2.6.3 + tslib: 2.8.1 '@jsdoc/salty@0.2.8': dependencies: @@ -18432,7 +18457,7 @@ snapshots: globby: 14.0.2 jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) lodash: 4.17.21 - prettier: 3.3.3 + prettier: 3.6.2 recast: 0.23.9 tiny-invariant: 1.3.3 transitivePeerDependencies: @@ -18468,7 +18493,7 @@ snapshots: '@storybook/node-logger': 7.6.20 '@storybook/types': 7.6.20 '@types/find-cache-dir': 3.2.1 - '@types/node': 18.19.45 + '@types/node': 18.19.74 '@types/node-fetch': 2.6.11 '@types/pretty-hrtime': 1.0.3 chalk: 4.1.2 @@ -18503,7 +18528,7 @@ snapshots: dependencies: '@storybook/csf': 0.1.11 '@types/express': 4.17.21 - '@types/node': 18.19.45 + '@types/node': 18.19.74 browser-assert: 1.2.1 esbuild: 0.21.5 esbuild-register: 3.6.0(esbuild@0.21.5) @@ -18645,7 +18670,7 @@ snapshots: '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))(bufferutil@4.0.8)(utf-8-validate@6.0.4)) '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 18.19.45 + '@types/node': 18.19.74 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -18740,16 +18765,16 @@ snapshots: '@swc/helpers@0.5.11': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@swc/helpers@0.5.12': dependencies: - tslib: 2.6.3 + tslib: 2.8.1 '@swc/helpers@0.5.5': dependencies: '@swc/counter': 0.1.3 - tslib: 2.6.3 + tslib: 2.8.1 '@tailwindcss/typography@0.5.14(tailwindcss@3.4.10(ts-node@10.9.2(@types/node@18.19.45)(typescript@5.5.4)))': dependencies: @@ -19116,7 +19141,7 @@ snapshots: '@types/prompts@2.4.9': dependencies: - '@types/node': 18.19.45 + '@types/node': 18.19.74 kleur: 3.0.3 '@types/prop-types@15.7.12': {} @@ -19155,7 +19180,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 18.19.45 + '@types/node': 18.19.74 form-data: 4.0.0 '@types/supertest@6.0.2': @@ -19181,7 +19206,7 @@ snapshots: '@types/ws@8.5.12': dependencies: - '@types/node': 16.18.105 + '@types/node': 18.19.74 '@types/yargs-parser@21.0.3': {} @@ -19331,7 +19356,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.4.0 + debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 @@ -19345,11 +19370,11 @@ snapshots: dependencies: '@typescript-eslint/types': 7.11.0 '@typescript-eslint/visitor-keys': 7.11.0 - debug: 4.4.0 + debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.3 + semver: 7.7.2 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 @@ -20090,7 +20115,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -20214,7 +20239,7 @@ snapshots: aria-hidden@1.2.4: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 aria-query@5.1.3: dependencies: @@ -20342,11 +20367,11 @@ snapshots: ast-types@0.13.4: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 ast-types@0.16.1: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 astring@1.8.6: {} @@ -20681,7 +20706,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.6.3 + tslib: 2.8.1 camelcase-css@2.0.1: {} @@ -21384,6 +21409,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 @@ -21522,6 +21551,8 @@ snapshots: discord-api-types@0.38.16: {} + discord-api-types@0.38.26: {} + dlv@1.1.3: {} dmd@6.2.3: @@ -21571,7 +21602,7 @@ snapshots: dts-critic@3.3.11(typescript@5.5.4): dependencies: - '@definitelytyped/header-parser': 0.2.19 + '@definitelytyped/header-parser': 0.2.20 command-exists: 1.2.9 rimraf: 3.0.2 semver: 6.3.1 @@ -21581,8 +21612,8 @@ snapshots: dtslint@4.2.1(typescript@5.5.4): dependencies: - '@definitelytyped/header-parser': 0.2.19 - '@definitelytyped/typescript-versions': 0.1.8 + '@definitelytyped/header-parser': 0.2.20 + '@definitelytyped/typescript-versions': 0.1.9 '@definitelytyped/utils': 0.1.8 dts-critic: 3.3.11(typescript@5.5.4) fs-extra: 6.0.1 @@ -22105,7 +22136,7 @@ snapshots: remark-parse: 11.0.0 remark-stringify: 11.0.0 synckit: 0.9.1 - tslib: 2.6.3 + tslib: 2.8.1 unified: 11.0.5 unified-engine: 11.2.1 unist-util-visit: 5.0.0 @@ -22164,12 +22195,12 @@ snapshots: eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: - debug: 4.4.0 + debug: 4.4.3 doctrine: 3.0.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0) - get-tsconfig: 4.10.0 + get-tsconfig: 4.10.1 is-glob: 4.0.3 minimatch: 3.1.2 semver: 7.5.4 @@ -22231,7 +22262,7 @@ snapshots: remark-mdx: 3.0.1 remark-parse: 11.0.0 remark-stringify: 11.0.0 - tslib: 2.6.3 + tslib: 2.8.1 unified: 11.0.5 vfile: 6.0.2 transitivePeerDependencies: @@ -22290,7 +22321,7 @@ snapshots: eslint: 8.57.0 eslint-etc: 5.2.1(eslint@8.57.0)(typescript@5.5.4) requireindex: 1.2.0 - tslib: 2.6.3 + tslib: 2.8.1 typescript: 5.5.4 transitivePeerDependencies: - supports-color @@ -22304,7 +22335,7 @@ snapshots: eslint-etc: 5.2.1(eslint@8.57.0)(typescript@5.5.4) requireindex: 1.2.0 rxjs-report-usage: 1.0.6 - tslib: 2.6.3 + tslib: 2.8.1 tsutils: 3.21.0(typescript@5.5.4) tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.5.4))(typescript@5.5.4) typescript: 5.5.4 @@ -22965,7 +22996,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-tsconfig@4.10.0: + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -22977,7 +23008,7 @@ snapshots: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 fs-extra: 11.2.0 transitivePeerDependencies: - supports-color @@ -23437,7 +23468,7 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -23457,7 +23488,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -23587,7 +23618,7 @@ snapshots: '@formatjs/ecma402-abstract': 2.0.0 '@formatjs/fast-memoize': 2.2.0 '@formatjs/icu-messageformat-parser': 2.7.8 - tslib: 2.6.3 + tslib: 2.8.1 invariant@2.2.4: dependencies: @@ -23875,7 +23906,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.4.0 + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -24015,37 +24046,6 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@18.19.45)(ts-node@10.9.2(@types/node@16.18.105)(typescript@5.5.4)): - dependencies: - '@babel/core': 7.25.2 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.25.2) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.7 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 18.19.45 - ts-node: 10.9.2(@types/node@16.18.105)(typescript@5.5.4) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - jest-config@29.7.0(@types/node@18.19.45)(ts-node@10.9.2(@types/node@18.19.45)(typescript@5.5.4)): dependencies: '@babel/core': 7.25.2 @@ -24077,6 +24077,68 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@29.7.0(@types/node@18.19.74)(ts-node@10.9.2(@types/node@16.18.105)(typescript@5.5.4)): + dependencies: + '@babel/core': 7.25.2 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.7 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 18.19.74 + ts-node: 10.9.2(@types/node@16.18.105)(typescript@5.5.4) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@29.7.0(@types/node@18.19.74)(ts-node@10.9.2(@types/node@18.19.45)(typescript@5.5.4)): + dependencies: + '@babel/core': 7.25.2 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.7 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 18.19.74 + ts-node: 10.9.2(@types/node@18.19.45)(typescript@5.5.4) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + jest-diff@29.7.0: dependencies: chalk: 4.1.2 @@ -24699,7 +24761,7 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 lru-cache@10.4.3: {} @@ -25708,7 +25770,7 @@ snapshots: micromark@2.11.4: dependencies: - debug: 4.4.0 + debug: 4.4.3 parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -25716,7 +25778,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0 + debug: 4.4.3 decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -25738,7 +25800,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0 + debug: 4.4.3 decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -26006,7 +26068,7 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.3 + tslib: 2.8.1 node-dir@0.1.17: dependencies: @@ -26453,7 +26515,7 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.6.3 + tslib: 2.8.1 path-browserify@1.0.1: {} @@ -26692,6 +26754,8 @@ snapshots: prettier@3.3.3: {} + prettier@3.6.2: {} + pretty-format@24.9.0: dependencies: '@jest/types': 24.9.0 @@ -26987,7 +27051,7 @@ snapshots: dependencies: react: 18.3.1 react-style-singleton: 2.2.1(@types/react@18.3.4)(react@18.3.1) - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -26995,7 +27059,7 @@ snapshots: dependencies: react: 19.0.0-rc-f994737d14-20240522 react-style-singleton: 2.2.1(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -27004,7 +27068,7 @@ snapshots: react: 18.3.1 react-remove-scroll-bar: 2.3.6(@types/react@18.3.4)(react@18.3.1) react-style-singleton: 2.2.1(@types/react@18.3.4)(react@18.3.1) - tslib: 2.6.3 + tslib: 2.8.1 use-callback-ref: 1.3.2(@types/react@18.3.4)(react@18.3.1) use-sidecar: 1.1.2(@types/react@18.3.4)(react@18.3.1) optionalDependencies: @@ -27015,7 +27079,7 @@ snapshots: react: 19.0.0-rc-f994737d14-20240522 react-remove-scroll-bar: 2.3.6(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) react-style-singleton: 2.2.1(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) - tslib: 2.6.3 + tslib: 2.8.1 use-callback-ref: 1.3.2(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) use-sidecar: 1.1.2(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) optionalDependencies: @@ -27026,7 +27090,7 @@ snapshots: react: 19.0.0-rc-f994737d14-20240522 react-remove-scroll-bar: 2.3.6(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) react-style-singleton: 2.2.1(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) - tslib: 2.6.3 + tslib: 2.8.1 use-callback-ref: 1.3.2(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) use-sidecar: 1.1.2(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522) optionalDependencies: @@ -27064,7 +27128,7 @@ snapshots: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.3.1 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -27073,7 +27137,7 @@ snapshots: get-nonce: 1.0.1 invariant: 2.2.4 react: 19.0.0-rc-f994737d14-20240522 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -27149,7 +27213,7 @@ snapshots: esprima: 4.0.1 source-map: 0.6.1 tiny-invariant: 1.3.3 - tslib: 2.6.3 + tslib: 2.8.1 redent@3.0.0: dependencies: @@ -27524,7 +27588,7 @@ snapshots: rxjs@7.8.1: dependencies: - tslib: 2.6.3 + tslib: 2.8.1 sade@1.8.1: dependencies: @@ -27592,6 +27656,8 @@ snapshots: semver@7.6.3: {} + semver@7.7.2: {} + send@0.18.0: dependencies: debug: 2.6.9 @@ -27758,7 +27824,7 @@ snapshots: socks-proxy-agent@7.0.0: dependencies: agent-base: 6.0.2 - debug: 4.4.0 + debug: 4.4.3 socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -27895,7 +27961,7 @@ snapshots: jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) leven: 3.1.0 ora: 5.4.1 - prettier: 3.3.3 + prettier: 3.6.2 prompts: 2.4.2 semver: 7.5.4 strip-json-comments: 3.1.1 @@ -28156,7 +28222,7 @@ snapshots: synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.3 + tslib: 2.8.1 table-layout@0.4.5: dependencies: @@ -28474,6 +28540,8 @@ snapshots: tslib@2.6.3: {} + tslib@2.8.1: {} + tslint@5.14.0(typescript@5.5.4): dependencies: babel-code-frame: 6.26.0 @@ -29073,14 +29141,14 @@ snapshots: use-callback-ref@1.3.2(@types/react@18.3.4)(react@18.3.1): dependencies: react: 18.3.1 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 use-callback-ref@1.3.2(@types/react@18.3.4)(react@19.0.0-rc-f994737d14-20240522): dependencies: react: 19.0.0-rc-f994737d14-20240522 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -29094,7 +29162,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 18.3.1 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4 @@ -29102,7 +29170,7 @@ snapshots: dependencies: detect-node-es: 1.1.0 react: 19.0.0-rc-f994737d14-20240522 - tslib: 2.6.3 + tslib: 2.8.1 optionalDependencies: '@types/react': 18.3.4