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:
Denis Cristea
2024-10-01 19:11:56 +03:00
committed by GitHub
parent c633d5c7f6
commit ab32f26cbb
91 changed files with 3772 additions and 3824 deletions

View File

@@ -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;
}
}