REFERENCEAPI reference

API reference

Complete reference for the @theminesastudios/mini-interaction package.

createApp

Creates the main application instance. This is the entry point that wires together verification, routing, and response handling.

typescript
createApp(config: AppConfig): App

interface AppConfig {
  publicKey: string;
  applicationId: string;
  onError?: (error: unknown) => Response | Promise<Response>;
  logger?: Logger;
}

interface App {
  use(...routers: Router[]): void;
  handle(): (req: Request) => Promise<Response>;
}

command

Define a single slash command with typed options and a handler.

typescript
command<T extends Record<string, unknown> = Record<string, unknown>>(
  config: CommandConfig<T>
): Command<T>

interface CommandConfig<T> {
  name: string;
  description: string;
  options?: ApplicationCommandOption[];
  handler: (ctx: CommandContext<T>) => Promise<InteractionResponse> | InteractionResponse;
  dmPermission?: boolean;
  defaultMemberPermissions?: string;
}

Router classes

CommandRouter

typescript
class CommandRouter {
  add(command: Command): this;
  use(middleware: Middleware): this;
  remove(name: string): boolean;
  commands(): Command[];
}

// Middleware signature
type Middleware = (
  ctx: CommandContext,
  next: (ctx: CommandContext) => Promise<InteractionResponse>,
) => Promise<InteractionResponse>;

ComponentRouter

typescript
class ComponentRouter {
  add(handler: ComponentHandler): this;
  remove(pattern: RegExp): boolean;
}

interface ComponentHandler {
  pattern: RegExp;
  handler: (ctx: ComponentContext) => Promise<InteractionResponse>;
}

interface ComponentContext {
  interaction: APIMessageComponentInteraction;
  params: Record<string, string>;
  respond(data: InteractionCallbackData): Promise<InteractionResponse>;
  deferUpdate(): Promise<void>;
  timestamp: Date;
}
typescript
class ModalRouter {
  add(handler: ModalHandler): this;
  remove(customId: string): boolean;
}

interface ModalHandler {
  customId: string;
  handler: (ctx: ModalContext) => Promise<InteractionResponse>;
}

interface ModalContext {
  interaction: APIModalSubmitInteraction;
  getField(customId: string): string;
  respond(data: InteractionCallbackData): Promise<InteractionResponse>;
  timestamp: Date;
}

Builder classes

EmbedBuilder

typescript
class EmbedBuilder {
  setTitle(title: string): this;
  setDescription(desc: string): this;
  setColor(color: number): this;
  setTimestamp(date?: Date): this;
  setFooter(footer: EmbedFooter): this;
  setImage(url: string): this;
  setThumbnail(url: string): this;
  setAuthor(author: EmbedAuthor): this;
  addFields(fields: EmbedField[]): this;
  toJSON(): APIEmbed;
}

ButtonBuilder

typescript
class ButtonBuilder {
  setCustomId(id: string): this;
  setLabel(text: string): this;
  setStyle(style: ButtonStyle): this;
  setEmoji(emoji: PartialEmoji): this;
  setUrl(url: string): this;
  setDisabled(disabled: boolean): this;
  toJSON(): APIButtonComponent;
}

SelectMenuBuilder

typescript
class SelectMenuBuilder {
  setCustomId(id: string): this;
  setPlaceholder(text: string): this;
  addOptions(options: SelectOption[]): this;
  setMinValues(min: number): this;
  setMaxValues(max: number): this;
  setDisabled(disabled: boolean): this;
  toJSON(): APISelectMenuComponent;
}

interface SelectOption {
  label: string;
  value: string;
  description?: string;
  emoji?: PartialEmoji;
  default?: boolean;
}

ActionRowBuilder

typescript
class ActionRowBuilder {
  addComponents(...components: ComponentBuilder[]): this;
  toJSON(): APIActionRowComponent;
}

OAuth2

typescript
createOAuth2Handler(config: OAuth2Config): OAuth2Handler;

interface OAuth2Config {
  clientId: string;
  clientSecret: string;
  redirectUri: string;
  scopes?: string[];
  store?: TokenStore;
}

interface OAuth2Handler {
  authorizeUrl(params: AuthorizeParams): string;
  callbackHandler(fn: CallbackFn): (req: Request) => Promise<Response>;
  exchangeCode(code: string): Promise<TokenSet>;
  refreshToken(refresh: string): Promise<TokenSet>;
  getUser(accessToken: string): Promise<DiscordUser>;
  getUserGuilds(accessToken: string): Promise<GuildPreview[]>;
  hasScope(tokens: TokenSet, scope: string): boolean;
  validateScopes(tokens: TokenSet, scopes: string[]): boolean;
  getOrRefresh(userId: string): Promise<TokenSet | null>;
}

interface TokenSet {
  accessToken: string;
  refreshToken: string;
  expiresAt: Date;
  scope: string;
  tokenType: string;
}

Type exports

The framework re-exports key Discord API types for convenience:

typescript
// Discord API types (re-exported from discord-api-types)
ApplicationCommandOptionType
ApplicationCommandType
ButtonStyle
ComponentType
InteractionType
InteractionResponseType
MessageFlags
MessageComponentType

// Framework types
type InteractionResponse
type CommandContext
type ComponentContext
type ModalContext
type InteractionCallbackData

// Logger interface
interface Logger {
  info(msg: string, meta?: Record<string, unknown>): void;
  warn(msg: string, meta?: Record<string, unknown>): void;
  error(msg: string, meta?: Record<string, unknown>): void;
  debug(msg: string, meta?: Record<string, unknown>): void;
}

Error handling

The framework provides typed errors for common failure modes:

typescript
class VerificationError extends Error {
  readonly code: "INVALID_SIGNATURE" | "MISSING_HEADERS";
  constructor(code: string, message: string);
}

class RouterError extends Error {
  readonly code: "NOT_FOUND" | "AMBIGUOUS_MATCH";
  constructor(code: string, message: string);
}

class OAuthError extends Error {
  readonly code: "INVALID_STATE" | "TOKEN_EXPIRED" | "INVALID_SCOPE";
  constructor(code: string, message: string, status?: number);
}