mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-02 04:56:07 +00:00
feat: option.value typing with choices (#278)
This commit is contained in:
parent
517b940bfe
commit
b059fa14b3
@ -5,6 +5,9 @@ import type {
|
|||||||
MenuCommandContext,
|
MenuCommandContext,
|
||||||
ModalContext,
|
ModalContext,
|
||||||
PermissionStrings,
|
PermissionStrings,
|
||||||
|
SeyfertBaseChoiceableOption,
|
||||||
|
SeyfertBasicOption,
|
||||||
|
SeyfertChoice,
|
||||||
SeyfertNumberOption,
|
SeyfertNumberOption,
|
||||||
SeyfertStringOption,
|
SeyfertStringOption,
|
||||||
} from '../..';
|
} from '../..';
|
||||||
@ -15,7 +18,7 @@ import type {
|
|||||||
OptionResolverStructure,
|
OptionResolverStructure,
|
||||||
UserStructure,
|
UserStructure,
|
||||||
} from '../../client/transformers';
|
} from '../../client/transformers';
|
||||||
import { type Awaitable, type FlatObjectKeys, magicImport } from '../../common';
|
import { magicImport } from '../../common';
|
||||||
import type { AllChannels, AutocompleteInteraction } from '../../structures';
|
import type { AllChannels, AutocompleteInteraction } from '../../structures';
|
||||||
import {
|
import {
|
||||||
type APIApplicationCommandBasicOption,
|
type APIApplicationCommandBasicOption,
|
||||||
@ -30,10 +33,8 @@ import {
|
|||||||
import type { Groups, RegisteredMiddlewares } from '../decorators';
|
import type { Groups, RegisteredMiddlewares } from '../decorators';
|
||||||
import type { CommandContext } from './chatcontext';
|
import type { CommandContext } from './chatcontext';
|
||||||
import type {
|
import type {
|
||||||
DefaultLocale,
|
|
||||||
ExtraProps,
|
ExtraProps,
|
||||||
IgnoreCommand,
|
IgnoreCommand,
|
||||||
OKFunction,
|
|
||||||
OnOptionsReturnObject,
|
OnOptionsReturnObject,
|
||||||
PassFunction,
|
PassFunction,
|
||||||
StopFunction,
|
StopFunction,
|
||||||
@ -54,47 +55,22 @@ export interface ReturnOptionsTypes {
|
|||||||
11: Attachment;
|
11: Attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Wrap<N extends ApplicationCommandOptionType> = N extends
|
|
||||||
| ApplicationCommandOptionType.Subcommand
|
|
||||||
| ApplicationCommandOptionType.SubcommandGroup
|
|
||||||
? never
|
|
||||||
: {
|
|
||||||
required?: boolean;
|
|
||||||
value?(
|
|
||||||
data: { context: CommandContext; value: ReturnOptionsTypes[N] },
|
|
||||||
ok: OKFunction<any>,
|
|
||||||
fail: StopFunction,
|
|
||||||
): Awaitable<void>;
|
|
||||||
} & {
|
|
||||||
description: string;
|
|
||||||
description_localizations?: APIApplicationCommandBasicOption['description_localizations'];
|
|
||||||
name_localizations?: APIApplicationCommandBasicOption['name_localizations'];
|
|
||||||
locales?: {
|
|
||||||
name?: FlatObjectKeys<DefaultLocale>;
|
|
||||||
description?: FlatObjectKeys<DefaultLocale>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type __TypeWrapper<T extends ApplicationCommandOptionType> = Wrap<T>;
|
|
||||||
|
|
||||||
export type __TypesWrapper = {
|
|
||||||
[P in keyof typeof ApplicationCommandOptionType]: `${(typeof ApplicationCommandOptionType)[P]}` extends `${infer D extends
|
|
||||||
number}`
|
|
||||||
? Wrap<D>
|
|
||||||
: never;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AutocompleteCallback = (interaction: AutocompleteInteraction) => any;
|
export type AutocompleteCallback = (interaction: AutocompleteInteraction) => any;
|
||||||
export type OnAutocompleteErrorCallback = (interaction: AutocompleteInteraction, error: unknown) => any;
|
export type OnAutocompleteErrorCallback = (interaction: AutocompleteInteraction, error: unknown) => any;
|
||||||
export type CommandBaseOption = __TypesWrapper[keyof __TypesWrapper];
|
export type CommandBaseOption =
|
||||||
export type CommandBaseAutocompleteOption = __TypesWrapper[keyof __TypesWrapper] & {
|
| SeyfertBaseChoiceableOption<ApplicationCommandOptionType>
|
||||||
|
| SeyfertBasicOption<ApplicationCommandOptionType>;
|
||||||
|
export type CommandBaseAutocompleteOption = (
|
||||||
|
| SeyfertBasicOption<ApplicationCommandOptionType>
|
||||||
|
| SeyfertBaseChoiceableOption<ApplicationCommandOptionType>
|
||||||
|
) & {
|
||||||
autocomplete: AutocompleteCallback;
|
autocomplete: AutocompleteCallback;
|
||||||
onAutocompleteError?: OnAutocompleteErrorCallback;
|
onAutocompleteError?: OnAutocompleteErrorCallback;
|
||||||
};
|
};
|
||||||
export type CommandAutocompleteOption = CommandBaseAutocompleteOption & { name: string };
|
export type CommandAutocompleteOption = CommandBaseAutocompleteOption & { name: string };
|
||||||
export type __CommandOption = CommandBaseOption; //| CommandBaseAutocompleteOption;
|
export type CommandOptionWithoutName = CommandBaseOption;
|
||||||
export type CommandOption = __CommandOption & { name: string };
|
export type CommandOption = CommandOptionWithoutName & { name: string };
|
||||||
export type OptionsRecord = Record<string, __CommandOption & { type: ApplicationCommandOptionType }>;
|
export type OptionsRecord = Record<string, CommandOptionWithoutName & { type: ApplicationCommandOptionType }>;
|
||||||
|
|
||||||
type KeysWithoutRequired<T extends OptionsRecord> = {
|
type KeysWithoutRequired<T extends OptionsRecord> = {
|
||||||
[K in keyof T]-?: T[K]['required'] extends true ? never : K;
|
[K in keyof T]-?: T[K]['required'] extends true ? never : K;
|
||||||
@ -104,16 +80,16 @@ type ContextOptionsAux<T extends OptionsRecord> = {
|
|||||||
[K in Exclude<keyof T, KeysWithoutRequired<T>>]: T[K]['value'] extends (...args: any) => any
|
[K in Exclude<keyof T, KeysWithoutRequired<T>>]: T[K]['value'] extends (...args: any) => any
|
||||||
? Parameters<Parameters<T[K]['value']>[1]>[0]
|
? Parameters<Parameters<T[K]['value']>[1]>[0]
|
||||||
: T[K] extends SeyfertStringOption | SeyfertNumberOption
|
: T[K] extends SeyfertStringOption | SeyfertNumberOption
|
||||||
? T[K]['choices'] extends NonNullable<SeyfertStringOption['choices'] | SeyfertNumberOption['choices']>
|
? NonNullable<T[K]['choices']> extends SeyfertChoice<string | number>[]
|
||||||
? T[K]['choices'][number]['value']
|
? NonNullable<T[K]['choices']>[number]['value']
|
||||||
: ReturnOptionsTypes[T[K]['type']]
|
: ReturnOptionsTypes[T[K]['type']]
|
||||||
: ReturnOptionsTypes[T[K]['type']];
|
: ReturnOptionsTypes[T[K]['type']];
|
||||||
} & {
|
} & {
|
||||||
[K in KeysWithoutRequired<T>]?: T[K]['value'] extends (...args: any) => any
|
[K in KeysWithoutRequired<T>]?: T[K]['value'] extends (...args: any) => any
|
||||||
? Parameters<Parameters<T[K]['value']>[1]>[0]
|
? Parameters<Parameters<T[K]['value']>[1]>[0]
|
||||||
: T[K] extends SeyfertStringOption | SeyfertNumberOption
|
: T[K] extends SeyfertStringOption | SeyfertNumberOption
|
||||||
? T[K]['choices'] extends NonNullable<SeyfertStringOption['choices'] | SeyfertNumberOption['choices']>
|
? NonNullable<T[K]['choices']> extends SeyfertChoice<string | number>[]
|
||||||
? T[K]['choices'][number]['value']
|
? NonNullable<T[K]['choices']>[number]['value']
|
||||||
: ReturnOptionsTypes[T[K]['type']]
|
: ReturnOptionsTypes[T[K]['type']]
|
||||||
: ReturnOptionsTypes[T[K]['type']];
|
: ReturnOptionsTypes[T[K]['type']];
|
||||||
};
|
};
|
||||||
@ -159,7 +135,7 @@ export class BaseCommand {
|
|||||||
let errored = false;
|
let errored = false;
|
||||||
for (const i of this.options ?? []) {
|
for (const i of this.options ?? []) {
|
||||||
try {
|
try {
|
||||||
const option = this.options!.find(x => x.name === i.name) as __CommandOption;
|
const option = this.options!.find(x => x.name === i.name) as CommandOptionWithoutName;
|
||||||
const value =
|
const value =
|
||||||
resolver.getHoisted(i.name)?.value !== undefined
|
resolver.getHoisted(i.name)?.value !== undefined
|
||||||
? await new Promise(async (res, rej) => {
|
? await new Promise(async (res, rej) => {
|
||||||
|
@ -4,57 +4,139 @@ import type {
|
|||||||
MenuCommandContext,
|
MenuCommandContext,
|
||||||
OnAutocompleteErrorCallback,
|
OnAutocompleteErrorCallback,
|
||||||
ReturnOptionsTypes,
|
ReturnOptionsTypes,
|
||||||
__TypesWrapper,
|
|
||||||
} from '..';
|
} from '..';
|
||||||
|
import type { Awaitable, FlatObjectKeys } from '../../common';
|
||||||
import type { ModalContext } from '../../components';
|
import type { ModalContext } from '../../components';
|
||||||
import type { ComponentContext } from '../../components/componentcontext';
|
import type { ComponentContext } from '../../components/componentcontext';
|
||||||
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
|
import type { MessageCommandInteraction, UserCommandInteraction } from '../../structures';
|
||||||
import { type APIApplicationCommandOptionChoice, ApplicationCommandOptionType, type ChannelType } from '../../types';
|
import {
|
||||||
|
type APIApplicationCommandBasicOption,
|
||||||
|
type APIApplicationCommandOptionChoice,
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
type ChannelType,
|
||||||
|
} from '../../types';
|
||||||
import type { CommandContext } from './chatcontext';
|
import type { CommandContext } from './chatcontext';
|
||||||
import type { MiddlewareContext } from './shared';
|
import type { DefaultLocale, MiddlewareContext, OKFunction, StopFunction } from './shared';
|
||||||
|
|
||||||
export type SeyfertBasicOption<T extends keyof __TypesWrapper, D = object> = __TypesWrapper[T] & D;
|
export interface SeyfertBasicOption<T extends keyof ReturnOptionsTypes> {
|
||||||
|
required?: boolean;
|
||||||
|
value?(
|
||||||
|
data: { context: CommandContext; value: ReturnOptionsTypes[T] },
|
||||||
|
ok: OKFunction<any>,
|
||||||
|
fail: StopFunction,
|
||||||
|
): Awaitable<void>;
|
||||||
|
description: string;
|
||||||
|
description_localizations?: APIApplicationCommandBasicOption['description_localizations'];
|
||||||
|
name_localizations?: APIApplicationCommandBasicOption['name_localizations'];
|
||||||
|
locales?: {
|
||||||
|
name?: FlatObjectKeys<DefaultLocale>;
|
||||||
|
description?: FlatObjectKeys<DefaultLocale>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export type SeyfertStringOption = SeyfertBasicOption<'String'> & {
|
export interface SeyfertBaseChoiceableOption<
|
||||||
|
T extends keyof ReturnOptionsTypes,
|
||||||
|
C = T extends ChoiceableTypes ? SeyfertChoice<ChoiceableValues[T]>[] : never,
|
||||||
|
> {
|
||||||
|
required?: boolean;
|
||||||
|
choices?: C;
|
||||||
|
value?: ValueCallback<T, C>;
|
||||||
|
description: string;
|
||||||
|
description_localizations?: APIApplicationCommandBasicOption['description_localizations'];
|
||||||
|
name_localizations?: APIApplicationCommandBasicOption['name_localizations'];
|
||||||
|
locales?: {
|
||||||
|
name?: FlatObjectKeys<DefaultLocale>;
|
||||||
|
description?: FlatObjectKeys<DefaultLocale>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SeyfertChoice<T extends string | number> =
|
||||||
|
| { readonly name: string; readonly value: T }
|
||||||
|
| APIApplicationCommandOptionChoice<T>;
|
||||||
|
|
||||||
|
export type ChoiceableTypes =
|
||||||
|
| ApplicationCommandOptionType.String
|
||||||
|
| ApplicationCommandOptionType.Integer
|
||||||
|
| ApplicationCommandOptionType.Number;
|
||||||
|
|
||||||
|
export interface ChoiceableValues {
|
||||||
|
[ApplicationCommandOptionType.String]: string;
|
||||||
|
[ApplicationCommandOptionType.Number]: number;
|
||||||
|
[ApplicationCommandOptionType.Integer]: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ValueCallback<
|
||||||
|
T extends keyof ReturnOptionsTypes,
|
||||||
|
C = T extends ChoiceableTypes ? SeyfertChoice<ChoiceableValues[T]>[] : never,
|
||||||
|
> = (
|
||||||
|
data: {
|
||||||
|
context: CommandContext;
|
||||||
|
value: T extends ChoiceableTypes
|
||||||
|
? C extends SeyfertChoice<ChoiceableValues[T]>[]
|
||||||
|
? C[number]['value'] extends ReturnOptionsTypes[T]
|
||||||
|
? C[number]['value']
|
||||||
|
: ReturnOptionsTypes[T]
|
||||||
|
: ReturnOptionsTypes[T]
|
||||||
|
: ReturnOptionsTypes[T];
|
||||||
|
},
|
||||||
|
ok: OKFunction<any>,
|
||||||
|
fail: StopFunction,
|
||||||
|
) => Awaitable<void>;
|
||||||
|
|
||||||
|
export type SeyfertStringOption<T = SeyfertChoice<string>[]> = SeyfertBaseChoiceableOption<
|
||||||
|
ApplicationCommandOptionType.String,
|
||||||
|
T
|
||||||
|
> & {
|
||||||
autocomplete?: AutocompleteCallback;
|
autocomplete?: AutocompleteCallback;
|
||||||
onAutocompleteError?: OnAutocompleteErrorCallback;
|
onAutocompleteError?: OnAutocompleteErrorCallback;
|
||||||
choices?:
|
|
||||||
| readonly { readonly name: string; readonly value: string }[]
|
|
||||||
| APIApplicationCommandOptionChoice<ReturnOptionsTypes[ApplicationCommandOptionType.String]>[];
|
|
||||||
min_length?: number;
|
min_length?: number;
|
||||||
max_length?: number;
|
max_length?: number;
|
||||||
};
|
};
|
||||||
export type SeyfertIntegerOption = SeyfertBasicOption<'Integer'> & {
|
export type SeyfertIntegerOption<T = SeyfertChoice<number>[]> = SeyfertBaseChoiceableOption<
|
||||||
|
ApplicationCommandOptionType.Integer,
|
||||||
|
T
|
||||||
|
> & {
|
||||||
autocomplete?: AutocompleteCallback;
|
autocomplete?: AutocompleteCallback;
|
||||||
onAutocompleteError?: OnAutocompleteErrorCallback;
|
onAutocompleteError?: OnAutocompleteErrorCallback;
|
||||||
choices?: APIApplicationCommandOptionChoice<ReturnOptionsTypes[ApplicationCommandOptionType.Integer]>[];
|
|
||||||
min_value?: number;
|
min_value?: number;
|
||||||
max_value?: number;
|
max_value?: number;
|
||||||
};
|
};
|
||||||
export type SeyfertBooleanOption = SeyfertBasicOption<'Boolean'>;
|
export type SeyfertNumberOption<T = SeyfertChoice<number>[]> = SeyfertBaseChoiceableOption<
|
||||||
export type SeyfertUserOption = SeyfertBasicOption<'User'>;
|
ApplicationCommandOptionType.Number,
|
||||||
export type SeyfertChannelOption = SeyfertBasicOption<'Channel'> & {
|
T
|
||||||
|
> & {
|
||||||
|
autocomplete?: AutocompleteCallback;
|
||||||
|
onAutocompleteError?: OnAutocompleteErrorCallback;
|
||||||
|
min_value?: number;
|
||||||
|
max_value?: number;
|
||||||
|
};
|
||||||
|
export type SeyfertBooleanOption = SeyfertBasicOption<ApplicationCommandOptionType.Boolean>;
|
||||||
|
export type SeyfertUserOption = SeyfertBasicOption<ApplicationCommandOptionType.User>;
|
||||||
|
export type SeyfertChannelOption = SeyfertBasicOption<ApplicationCommandOptionType.Channel> & {
|
||||||
channel_types?: ChannelType[];
|
channel_types?: ChannelType[];
|
||||||
};
|
};
|
||||||
export type SeyfertRoleOption = SeyfertBasicOption<'Role'>;
|
export type SeyfertRoleOption = SeyfertBasicOption<ApplicationCommandOptionType.Role>;
|
||||||
export type SeyfertMentionableOption = SeyfertBasicOption<'Mentionable'>;
|
export type SeyfertMentionableOption = SeyfertBasicOption<ApplicationCommandOptionType.Mentionable>;
|
||||||
export type SeyfertNumberOption = SeyfertBasicOption<'Number'> & {
|
export type SeyfertAttachmentOption = SeyfertBasicOption<ApplicationCommandOptionType.Attachment>;
|
||||||
autocomplete?: AutocompleteCallback;
|
|
||||||
onAutocompleteError?: OnAutocompleteErrorCallback;
|
|
||||||
choices?: APIApplicationCommandOptionChoice<ReturnOptionsTypes[ApplicationCommandOptionType.Number]>[];
|
|
||||||
min_value?: number;
|
|
||||||
max_value?: number;
|
|
||||||
};
|
|
||||||
export type SeyfertAttachmentOption = SeyfertBasicOption<'Attachment'>;
|
|
||||||
|
|
||||||
export function createStringOption<T extends SeyfertStringOption = SeyfertStringOption>(data: T) {
|
export function createStringOption<C extends SeyfertChoice<string>[] = SeyfertChoice<string>[]>(
|
||||||
|
data: SeyfertStringOption<C>,
|
||||||
|
) {
|
||||||
return { ...data, type: ApplicationCommandOptionType.String } as const;
|
return { ...data, type: ApplicationCommandOptionType.String } as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createIntegerOption<T extends SeyfertIntegerOption = SeyfertIntegerOption>(data: T) {
|
export function createIntegerOption<C extends SeyfertChoice<number>[] = SeyfertChoice<number>[]>(
|
||||||
|
data: SeyfertIntegerOption<C>,
|
||||||
|
) {
|
||||||
return { ...data, type: ApplicationCommandOptionType.Integer } as const;
|
return { ...data, type: ApplicationCommandOptionType.Integer } as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createNumberOption<C extends SeyfertChoice<number>[] = SeyfertChoice<number>[]>(
|
||||||
|
data: SeyfertNumberOption<C>,
|
||||||
|
) {
|
||||||
|
return { ...data, type: ApplicationCommandOptionType.Number } as const;
|
||||||
|
}
|
||||||
|
|
||||||
export function createBooleanOption<T extends SeyfertBooleanOption = SeyfertBooleanOption>(data: T) {
|
export function createBooleanOption<T extends SeyfertBooleanOption = SeyfertBooleanOption>(data: T) {
|
||||||
return { ...data, type: ApplicationCommandOptionType.Boolean } as const;
|
return { ...data, type: ApplicationCommandOptionType.Boolean } as const;
|
||||||
}
|
}
|
||||||
@ -75,10 +157,6 @@ export function createMentionableOption<T extends SeyfertMentionableOption = Sey
|
|||||||
return { ...data, type: ApplicationCommandOptionType.Mentionable } as const;
|
return { ...data, type: ApplicationCommandOptionType.Mentionable } as const;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createNumberOption<T extends SeyfertNumberOption = SeyfertNumberOption>(data: T) {
|
|
||||||
return { ...data, type: ApplicationCommandOptionType.Number } as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createAttachmentOption<T extends SeyfertAttachmentOption = SeyfertAttachmentOption>(data: T) {
|
export function createAttachmentOption<T extends SeyfertAttachmentOption = SeyfertAttachmentOption>(data: T) {
|
||||||
return { ...data, type: ApplicationCommandOptionType.Attachment } as const;
|
return { ...data, type: ApplicationCommandOptionType.Attachment } as const;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user