Sub-Zero (Sub Commands)
We’ve covered the basics of creating a command, but what if we want to create a command that has subcommands? For example, we want to create a command with a create
subcommand and a delete
subcommand. This is where subcommands come into play.
Creating a Subcommand
To create a subcommand, we need to create a new class that extends SubCommand
and implement the run
method. Then, we need to add the subcommand to the main command.
Let’s assume you have the following directory structure:
- src
Directorycommands
Directoryaccount
- create.command.ts
- delete.command.ts
- parent.ts
- index.ts
- seyfert.config.mjs
- package.json
- tsconfig.json
import { Declare, Command, Options } from "seyfert";import { CreateCommand } from "./create.command";import { DeleteCommand } from "./delete.command";
@Declare({ name: "account", description: "account command"})// Being in the same folder with @AutoLoad() you can save this step@Options([CreateCommand, DeleteCommand])export default class AccountCommand extends Command {}
import { type CommandContext, Declare, SubCommand } from "seyfert";
@Declare({ name: "create", description: "create a new something"})export class CreateCommand extends SubCommand { run(ctx: CommandContext) { // some logic here
return ctx.write({ content: "create command executed" }); }}
import { type CommandContext, Declare, SubCommand } from "seyfert";
@Declare({ name: "delete", description: "delete something"})export class DeleteCommand extends SubCommand { run(ctx: CommandContext) { // some logic here
return ctx.write({ content: "delete command executed" }); }}
In the example above, we created a create
subcommand and a delete
subcommand. Then, we added the subcommands to the main command using the @Options
decorator.
Subcommand Groups
For a more divided structure, you can create groups for subcommands using the @Group
and @Groups
decorators in the main command.
import { class Command
Command, function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare, function Options(options: (new () => SubCommand)[] | OptionsRecord): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { options: SubCommand[] | CommandOption[]; };} & T
Options, function Groups(groups: Record<string, { name?: [language: LocaleString, value: string][]; description?: [language: LocaleString, value: string][]; defaultDescription: string; aliases?: string[];}>): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { groups: Record<string, { name?: [language: LocaleString, value: string][]; description?: [language: LocaleString, value: string][]; defaultDescription: string; aliases?: string[]; }>; groupsAliases: Record<string, string>; };} & T
Groups } from 'seyfert';import import MySubCommand
MySubCommand from './sub';
@function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare({ name: string
name: 'parent', description: string
description: 'My main command',})@function Options(options: (new () => SubCommand)[] | OptionsRecord): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { options: SubCommand[] | CommandOption[]; };} & T
Options([import MySubCommand
MySubCommand])@function Groups(groups: Record<string, { name?: [language: LocaleString, value: string][]; description?: [language: LocaleString, value: string][]; defaultDescription: string; aliases?: string[];}>): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { groups: Record<string, { name?: [language: LocaleString, value: string][]; description?: [language: LocaleString, value: string][]; defaultDescription: string; aliases?: string[]; }>; groupsAliases: Record<string, string>; };} & T
Groups({ 'my-group': { defaultDescription: string
defaultDescription: 'A subcommand group', }})export default class class ParentCommand
ParentCommand extends class Command
Command {}
import { class SubCommand
SubCommand, function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare, class CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>interface CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
CommandContext, function Group(groupName: string): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { group: string; };} & T
Group } from 'seyfert';
@function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare({ name: string
name: 'subcommand', description: string
description: 'One of my subcommands within the my-group group',})@function Group(groupName: string): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { group: string; };} & T
Group('my-group')export default class class GroupMySubCommand
GroupMySubCommand extends class SubCommand
SubCommand { GroupMySubCommand.run(ctx: CommandContext): Promise<void | WebhookMessage>
run(ctx: CommandContext<{}, never>
ctx: class CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>interface CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
CommandContext) { return ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.write<false>(body: InteractionCreateBodyRequest, withResponse?: false | undefined): Promise<void | WebhookMessage>
write({ content?: string | undefined
The message contents (up to 2000 characters)
content: 'Hello from the subcommand!', }); }}