Skip to content

Commit

Permalink
feat(builders): update to @sapphire/shapeshift v4 (#10291)
Browse files Browse the repository at this point in the history
feat: update to @sapphire/shapeshift v4
  • Loading branch information
favna authored Aug 19, 2024
1 parent bbef68d commit 2d5531f
Show file tree
Hide file tree
Showing 14 changed files with 136 additions and 86 deletions.
2 changes: 1 addition & 1 deletion packages/builders/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"dependencies": {
"@discordjs/formatters": "workspace:^",
"@discordjs/util": "workspace:^",
"@sapphire/shapeshift": "^3.9.7",
"@sapphire/shapeshift": "^4.0.0",
"discord-api-types": "0.37.94",
"fast-deep-equal": "^3.1.3",
"ts-mixer": "^6.0.4",
Expand Down
47 changes: 29 additions & 18 deletions packages/builders/src/components/Assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,42 @@ import { ButtonStyle, ChannelType, type APIMessageComponentEmoji } from 'discord
import { isValidationEnabled } from '../util/validation.js';
import { StringSelectMenuOptionBuilder } from './selectMenu/StringSelectMenuOption.js';

export const customIdValidator = s.string
export const customIdValidator = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(100)
.setValidationEnabled(isValidationEnabled);

export const emojiValidator = s
.object({
id: s.string,
name: s.string,
animated: s.boolean,
id: s.string(),
name: s.string(),
animated: s.boolean(),
})
.partial.strict.setValidationEnabled(isValidationEnabled);
.partial()
.strict()
.setValidationEnabled(isValidationEnabled);

export const disabledValidator = s.boolean;
export const disabledValidator = s.boolean();

export const buttonLabelValidator = s.string
export const buttonLabelValidator = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(80)
.setValidationEnabled(isValidationEnabled);

export const buttonStyleValidator = s.nativeEnum(ButtonStyle);

export const placeholderValidator = s.string.lengthLessThanOrEqual(150).setValidationEnabled(isValidationEnabled);
export const minMaxValidator = s.number.int
export const placeholderValidator = s.string().lengthLessThanOrEqual(150).setValidationEnabled(isValidationEnabled);
export const minMaxValidator = s
.number()
.int()
.greaterThanOrEqual(0)
.lessThanOrEqual(25)
.setValidationEnabled(isValidationEnabled);

export const labelValueDescriptionValidator = s.string
export const labelValueDescriptionValidator = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(100)
.setValidationEnabled(isValidationEnabled);
Expand All @@ -40,18 +47,21 @@ export const jsonOptionValidator = s
.object({
label: labelValueDescriptionValidator,
value: labelValueDescriptionValidator,
description: labelValueDescriptionValidator.optional,
emoji: emojiValidator.optional,
default: s.boolean.optional,
description: labelValueDescriptionValidator.optional(),
emoji: emojiValidator.optional(),
default: s.boolean().optional(),
})
.setValidationEnabled(isValidationEnabled);

export const optionValidator = s.instance(StringSelectMenuOptionBuilder).setValidationEnabled(isValidationEnabled);

export const optionsValidator = optionValidator.array
export const optionsValidator = optionValidator
.array()
.lengthGreaterThanOrEqual(0)
.setValidationEnabled(isValidationEnabled);
export const optionsLengthValidator = s.number.int
export const optionsLengthValidator = s
.number()
.int()
.greaterThanOrEqual(0)
.lessThanOrEqual(25)
.setValidationEnabled(isValidationEnabled);
Expand All @@ -61,16 +71,17 @@ export function validateRequiredSelectMenuParameters(options: StringSelectMenuOp
optionsValidator.parse(options);
}

export const defaultValidator = s.boolean;
export const defaultValidator = s.boolean();

export function validateRequiredSelectMenuOptionParameters(label?: string, value?: string) {
labelValueDescriptionValidator.parse(label);
labelValueDescriptionValidator.parse(value);
}

export const channelTypesValidator = s.nativeEnum(ChannelType).array.setValidationEnabled(isValidationEnabled);
export const channelTypesValidator = s.nativeEnum(ChannelType).array().setValidationEnabled(isValidationEnabled);

export const urlValidator = s.string
export const urlValidator = s
.string()
.url({
allowedProtocols: ['http:', 'https:', 'discord:'],
})
Expand Down
17 changes: 11 additions & 6 deletions packages/builders/src/components/textInput/Assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import { isValidationEnabled } from '../../util/validation.js';
import { customIdValidator } from '../Assertions.js';

export const textInputStyleValidator = s.nativeEnum(TextInputStyle);
export const minLengthValidator = s.number.int
export const minLengthValidator = s
.number()
.int()
.greaterThanOrEqual(0)
.lessThanOrEqual(4_000)
.setValidationEnabled(isValidationEnabled);
export const maxLengthValidator = s.number.int
export const maxLengthValidator = s
.number()
.int()
.greaterThanOrEqual(1)
.lessThanOrEqual(4_000)
.setValidationEnabled(isValidationEnabled);
export const requiredValidator = s.boolean;
export const valueValidator = s.string.lengthLessThanOrEqual(4_000).setValidationEnabled(isValidationEnabled);
export const placeholderValidator = s.string.lengthLessThanOrEqual(100).setValidationEnabled(isValidationEnabled);
export const labelValidator = s.string
export const requiredValidator = s.boolean();
export const valueValidator = s.string().lengthLessThanOrEqual(4_000).setValidationEnabled(isValidationEnabled);
export const placeholderValidator = s.string().lengthLessThanOrEqual(100).setValidationEnabled(isValidationEnabled);
export const labelValidator = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(45)
.setValidationEnabled(isValidationEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { ApplicationCommandType, ApplicationIntegrationType, InteractionContextT
import { isValidationEnabled } from '../../util/validation.js';
import type { ContextMenuCommandType } from './ContextMenuCommandBuilder.js';

const namePredicate = s.string
const namePredicate = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(32)
// eslint-disable-next-line prefer-named-capture-group
.regex(/^( *[\p{P}\p{L}\p{N}\p{sc=Devanagari}\p{sc=Thai}]+ *)+$/u)
.setValidationEnabled(isValidationEnabled);
const typePredicate = s
.union(s.literal(ApplicationCommandType.User), s.literal(ApplicationCommandType.Message))
.union([s.literal(ApplicationCommandType.User), s.literal(ApplicationCommandType.Message)])
.setValidationEnabled(isValidationEnabled);
const booleanPredicate = s.boolean;
const booleanPredicate = s.boolean();

export function validateDefaultPermission(value: unknown): asserts value is boolean {
booleanPredicate.parse(value);
Expand All @@ -34,17 +35,22 @@ export function validateRequiredParameters(name: string, type: number) {
validateType(type);
}

const dmPermissionPredicate = s.boolean.nullish;
const dmPermissionPredicate = s.boolean().nullish();

export function validateDMPermission(value: unknown): asserts value is boolean | null | undefined {
dmPermissionPredicate.parse(value);
}

const memberPermissionPredicate = s.union(
s.bigint.transform((value) => value.toString()),
s.number.safeInt.transform((value) => value.toString()),
s.string.regex(/^\d+$/),
).nullish;
const memberPermissionPredicate = s
.union([
s.bigint().transform((value) => value.toString()),
s
.number()
.safeInt()
.transform((value) => value.toString()),
s.string().regex(/^\d+$/),
])
.nullish();

export function validateDefaultMemberPermissions(permissions: unknown) {
return memberPermissionPredicate.parse(permissions);
Expand Down
6 changes: 4 additions & 2 deletions packages/builders/src/interactions/modals/Assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { ActionRowBuilder, type ModalActionRowComponentBuilder } from '../../com
import { customIdValidator } from '../../components/Assertions.js';
import { isValidationEnabled } from '../../util/validation.js';

export const titleValidator = s.string
export const titleValidator = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(45)
.setValidationEnabled(isValidationEnabled);
export const componentsValidator = s
.instance(ActionRowBuilder)
.array.lengthGreaterThanOrEqual(1)
.array()
.lengthGreaterThanOrEqual(1)
.setValidationEnabled(isValidationEnabled);

export function validateRequiredParameters(
Expand Down
35 changes: 22 additions & 13 deletions packages/builders/src/interactions/slashCommands/Assertions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import type { ToAPIApplicationCommandOptions } from './SlashCommandBuilder.js';
import type { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } from './SlashCommandSubcommands.js';
import type { ApplicationCommandOptionBase } from './mixins/ApplicationCommandOptionBase.js';

const namePredicate = s.string
const namePredicate = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(32)
.regex(/^[\p{Ll}\p{Lm}\p{Lo}\p{N}\p{sc=Devanagari}\p{sc=Thai}_-]+$/u)
Expand All @@ -21,7 +22,8 @@ export function validateName(name: unknown): asserts name is string {
namePredicate.parse(name);
}

const descriptionPredicate = s.string
const descriptionPredicate = s
.string()
.lengthGreaterThanOrEqual(1)
.lengthLessThanOrEqual(100)
.setValidationEnabled(isValidationEnabled);
Expand All @@ -31,7 +33,7 @@ export function validateDescription(description: unknown): asserts description i
descriptionPredicate.parse(description);
}

const maxArrayLengthPredicate = s.unknown.array.lengthLessThanOrEqual(25).setValidationEnabled(isValidationEnabled);
const maxArrayLengthPredicate = s.unknown().array().lengthLessThanOrEqual(25).setValidationEnabled(isValidationEnabled);
export function validateLocale(locale: unknown) {
return localePredicate.parse(locale);
}
Expand All @@ -55,7 +57,7 @@ export function validateRequiredParameters(
validateMaxOptionsLength(options);
}

const booleanPredicate = s.boolean;
const booleanPredicate = s.boolean();

export function validateDefaultPermission(value: unknown): asserts value is boolean {
booleanPredicate.parse(value);
Expand All @@ -65,7 +67,7 @@ export function validateRequired(required: unknown): asserts required is boolean
booleanPredicate.parse(required);
}

const choicesLengthPredicate = s.number.lessThanOrEqual(25).setValidationEnabled(isValidationEnabled);
const choicesLengthPredicate = s.number().lessThanOrEqual(25).setValidationEnabled(isValidationEnabled);

export function validateChoicesLength(amountAdding: number, choices?: APIApplicationCommandOptionChoice[]): void {
choicesLengthPredicate.parse((choices?.length ?? 0) + amountAdding);
Expand All @@ -78,24 +80,31 @@ export function assertReturnOfBuilder<
}

export const localizationMapPredicate = s
.object<LocalizationMap>(Object.fromEntries(Object.values(Locale).map((locale) => [locale, s.string.nullish])))
.strict.nullish.setValidationEnabled(isValidationEnabled);
.object<LocalizationMap>(Object.fromEntries(Object.values(Locale).map((locale) => [locale, s.string().nullish()])))
.strict()
.nullish()
.setValidationEnabled(isValidationEnabled);

export function validateLocalizationMap(value: unknown): asserts value is LocalizationMap {
localizationMapPredicate.parse(value);
}

const dmPermissionPredicate = s.boolean.nullish;
const dmPermissionPredicate = s.boolean().nullish();

export function validateDMPermission(value: unknown): asserts value is boolean | null | undefined {
dmPermissionPredicate.parse(value);
}

const memberPermissionPredicate = s.union(
s.bigint.transform((value) => value.toString()),
s.number.safeInt.transform((value) => value.toString()),
s.string.regex(/^\d+$/),
).nullish;
const memberPermissionPredicate = s
.union([
s.bigint().transform((value) => value.toString()),
s
.number()
.safeInt()
.transform((value) => value.toString()),
s.string().regex(/^\d+$/),
])
.nullish();

export function validateDefaultMemberPermissions(permissions: unknown) {
return memberPermissionPredicate.parse(permissions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const allowedChannelTypes = [
*/
export type ApplicationCommandOptionAllowedChannelTypes = (typeof allowedChannelTypes)[number];

const channelTypesPredicate = s.array(s.union(...allowedChannelTypes.map((type) => s.literal(type))));
const channelTypesPredicate = s.array(s.union(allowedChannelTypes.map((type) => s.literal(type))));

/**
* This mixin holds channel type symbols used for options.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { s } from '@sapphire/shapeshift';
import type { ApplicationCommandOptionType } from 'discord-api-types/v10';

const booleanPredicate = s.boolean;
const booleanPredicate = s.boolean();

/**
* This mixin holds choices and autocomplete symbols used for options.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { ApplicationCommandOptionType, type APIApplicationCommandOptionChoice }
import { normalizeArray, type RestOrArray } from '../../../util/normalizeArray.js';
import { localizationMapPredicate, validateChoicesLength } from '../Assertions.js';

const stringPredicate = s.string.lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(100);
const numberPredicate = s.number.greaterThan(Number.NEGATIVE_INFINITY).lessThan(Number.POSITIVE_INFINITY);
const choicesPredicate = s.object({
name: stringPredicate,
name_localizations: localizationMapPredicate,
value: s.union(stringPredicate, numberPredicate),
}).array;
const stringPredicate = s.string().lengthGreaterThanOrEqual(1).lengthLessThanOrEqual(100);
const numberPredicate = s.number().greaterThan(Number.NEGATIVE_INFINITY).lessThan(Number.POSITIVE_INFINITY);
const choicesPredicate = s
.object({
name: stringPredicate,
name_localizations: localizationMapPredicate,
value: s.union([stringPredicate, numberPredicate]),
})
.array();

/**
* This mixin holds choices and autocomplete symbols used for options.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOption
import { ApplicationCommandOptionWithAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithAutocompleteMixin.js';
import { ApplicationCommandOptionWithChoicesMixin } from '../mixins/ApplicationCommandOptionWithChoicesMixin.js';

const numberValidator = s.number.int;
const numberValidator = s.number().int();

/**
* A slash command integer option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOption
import { ApplicationCommandOptionWithAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithAutocompleteMixin.js';
import { ApplicationCommandOptionWithChoicesMixin } from '../mixins/ApplicationCommandOptionWithChoicesMixin.js';

const numberValidator = s.number;
const numberValidator = s.number();

/**
* A slash command number option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOption
import { ApplicationCommandOptionWithAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithAutocompleteMixin.js';
import { ApplicationCommandOptionWithChoicesMixin } from '../mixins/ApplicationCommandOptionWithChoicesMixin.js';

const minLengthValidator = s.number.greaterThanOrEqual(0).lessThanOrEqual(6_000);
const maxLengthValidator = s.number.greaterThanOrEqual(1).lessThanOrEqual(6_000);
const minLengthValidator = s.number().greaterThanOrEqual(0).lessThanOrEqual(6_000);
const maxLengthValidator = s.number().greaterThanOrEqual(1).lessThanOrEqual(6_000);

/**
* A slash command string option.
Expand Down
Loading

0 comments on commit 2d5531f

Please sign in to comment.