mirror of
https://github.com/discordjs/discord.js.git
synced 2026-06-01 16:40:07 +00:00
refactor: builders (#10448)
BREAKING CHANGE: formatters export removed (prev. deprecated) BREAKING CHANGE: `SelectMenuBuilder` and `SelectMenuOptionBuilder` have been removed (prev. deprecated) BREAKING CHANGE: `EmbedBuilder` no longer takes camalCase options BREAKING CHANGE: `ActionRowBuilder` now has specialized `[add/set]X` methods as opposed to the current `[add/set]Components` BREAKING CHANGE: Removed `equals` methods BREAKING CHANGE: Sapphire -> zod for validation BREAKING CHANGE: Removed the ability to pass `null`/`undefined` to clear fields, use `clearX()` instead BREAKING CHANGE: Renamed all "slash command" symbols to instead use "chat input command" BREAKING CHANGE: Removed `ContextMenuCommandBuilder` in favor of `MessageCommandBuilder` and `UserCommandBuilder` BREAKING CHANGE: Removed support for passing the "string key"s of enums BREAKING CHANGE: Removed `Button` class in favor for specialized classes depending on the style BREAKING CHANGE: Removed nested `addX` styled-methods in favor of plural `addXs` Co-authored-by: Vlad Frangu <me@vladfrangu.dev> Co-authored-by: Almeida <github@almeidx.dev>
This commit is contained in:
@@ -1,18 +1,30 @@
|
||||
/* eslint-disable jsdoc/check-param-names */
|
||||
|
||||
import { ComponentType } from 'discord-api-types/v10';
|
||||
import type { APIStringSelectComponent, APISelectMenuOption } from 'discord-api-types/v10';
|
||||
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
||||
import { jsonOptionValidator, optionsLengthValidator, validateRequiredSelectMenuParameters } from '../Assertions.js';
|
||||
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
||||
import { isValidationEnabled } from '../../util/validation.js';
|
||||
import { selectMenuStringPredicate } from '../Assertions.js';
|
||||
import { BaseSelectMenuBuilder } from './BaseSelectMenu.js';
|
||||
import { StringSelectMenuOptionBuilder } from './StringSelectMenuOption.js';
|
||||
|
||||
export interface StringSelectMenuData extends Partial<Omit<APIStringSelectComponent, 'options'>> {
|
||||
options: StringSelectMenuOptionBuilder[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder that creates API-compatible JSON data for string select menus.
|
||||
*/
|
||||
export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSelectComponent> {
|
||||
protected override readonly data: StringSelectMenuData;
|
||||
|
||||
/**
|
||||
* The options within this select menu.
|
||||
* The options for this select menu.
|
||||
*/
|
||||
public readonly options: StringSelectMenuOptionBuilder[];
|
||||
public get options(): readonly StringSelectMenuOptionBuilder[] {
|
||||
return this.data.options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new select menu from API data.
|
||||
@@ -45,10 +57,13 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
public constructor(data?: Partial<APIStringSelectComponent>) {
|
||||
const { options, ...initData } = data ?? {};
|
||||
super({ ...initData, type: ComponentType.StringSelect });
|
||||
this.options = options?.map((option: APISelectMenuOption) => new StringSelectMenuOptionBuilder(option)) ?? [];
|
||||
public constructor({ options = [], ...data }: Partial<APIStringSelectComponent> = {}) {
|
||||
super();
|
||||
this.data = {
|
||||
...structuredClone(data),
|
||||
options: options.map((option) => new StringSelectMenuOptionBuilder(option)),
|
||||
type: ComponentType.StringSelect,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,16 +71,18 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
|
||||
*
|
||||
* @param options - The options to add
|
||||
*/
|
||||
public addOptions(...options: RestOrArray<APISelectMenuOption | StringSelectMenuOptionBuilder>) {
|
||||
public addOptions(
|
||||
...options: RestOrArray<
|
||||
| APISelectMenuOption
|
||||
| StringSelectMenuOptionBuilder
|
||||
| ((builder: StringSelectMenuOptionBuilder) => StringSelectMenuOptionBuilder)
|
||||
>
|
||||
) {
|
||||
const normalizedOptions = normalizeArray(options);
|
||||
optionsLengthValidator.parse(this.options.length + normalizedOptions.length);
|
||||
this.options.push(
|
||||
...normalizedOptions.map((normalizedOption) =>
|
||||
normalizedOption instanceof StringSelectMenuOptionBuilder
|
||||
? normalizedOption
|
||||
: new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(normalizedOption)),
|
||||
),
|
||||
);
|
||||
const resolved = normalizedOptions.map((option) => resolveBuilder(option, StringSelectMenuOptionBuilder));
|
||||
|
||||
this.data.options.push(...resolved);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -74,8 +91,14 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
|
||||
*
|
||||
* @param options - The options to set
|
||||
*/
|
||||
public setOptions(...options: RestOrArray<APISelectMenuOption | StringSelectMenuOptionBuilder>) {
|
||||
return this.spliceOptions(0, this.options.length, ...options);
|
||||
public setOptions(
|
||||
...options: RestOrArray<
|
||||
| APISelectMenuOption
|
||||
| StringSelectMenuOptionBuilder
|
||||
| ((builder: StringSelectMenuOptionBuilder) => StringSelectMenuOptionBuilder)
|
||||
>
|
||||
) {
|
||||
return this.spliceOptions(0, this.options.length, ...normalizeArray(options));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,36 +131,35 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
|
||||
public spliceOptions(
|
||||
index: number,
|
||||
deleteCount: number,
|
||||
...options: RestOrArray<APISelectMenuOption | StringSelectMenuOptionBuilder>
|
||||
...options: (
|
||||
| APISelectMenuOption
|
||||
| StringSelectMenuOptionBuilder
|
||||
| ((builder: StringSelectMenuOptionBuilder) => StringSelectMenuOptionBuilder)
|
||||
)[]
|
||||
) {
|
||||
const normalizedOptions = normalizeArray(options);
|
||||
const resolved = options.map((option) => resolveBuilder(option, StringSelectMenuOptionBuilder));
|
||||
|
||||
const clone = [...this.options];
|
||||
this.data.options ??= [];
|
||||
this.data.options.splice(index, deleteCount, ...resolved);
|
||||
|
||||
clone.splice(
|
||||
index,
|
||||
deleteCount,
|
||||
...normalizedOptions.map((normalizedOption) =>
|
||||
normalizedOption instanceof StringSelectMenuOptionBuilder
|
||||
? normalizedOption
|
||||
: new StringSelectMenuOptionBuilder(jsonOptionValidator.parse(normalizedOption)),
|
||||
),
|
||||
);
|
||||
|
||||
optionsLengthValidator.parse(clone.length);
|
||||
this.options.splice(0, this.options.length, ...clone);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc BaseSelectMenuBuilder.toJSON}
|
||||
* {@inheritDoc ComponentBuilder.toJSON}
|
||||
*/
|
||||
public override toJSON(): APIStringSelectComponent {
|
||||
validateRequiredSelectMenuParameters(this.options, this.data.custom_id);
|
||||
public override toJSON(validationOverride?: boolean): APIStringSelectComponent {
|
||||
const { options, ...rest } = this.data;
|
||||
const data = {
|
||||
...(structuredClone(rest) as APIStringSelectComponent),
|
||||
// selectMenuStringPredicate covers the validation of options
|
||||
options: options.map((option) => option.toJSON(false)),
|
||||
};
|
||||
|
||||
return {
|
||||
...this.data,
|
||||
options: this.options.map((option) => option.toJSON()),
|
||||
} as APIStringSelectComponent;
|
||||
if (validationOverride ?? isValidationEnabled()) {
|
||||
selectMenuStringPredicate.parse(data);
|
||||
}
|
||||
|
||||
return data as APIStringSelectComponent;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user