TypeScript Discord Framework

WingetCord

A next-generation, high-performance Discord framework built for TypeScript. Fast, expressive, and zero-config by default.

MIT License TypeScript 5.0+ v2.0.0 Discord API v10

Introduction overview

WingetCord is a modern Discord library built from the ground up with TypeScript-first design, offering a fluent API, smart caching, zero-config handlers, and powerful plugin/middleware systems.

Ultra-Fast REST

Uses undici for persistent connection pooling and per-route queuing.

🛡️

Resilient Gateway

Automatic session resume and internal packet rate limiting.

💎

Expressiveness

Modern, fluent API that reduces boilerplate code significantly.

🧩

Zero-Config Handlers

Automated command and event discovery with one line.

🔌

Plugin System

Reusable, independent plugins with full dependency management.

Scheduler

Cron-based and interval task scheduling built-in.

🎵

Audio Player

Multi-channel audio queue with advanced playback control.

📊

Metrics & Logging

Professional logging with correlation IDs and real-time metrics.

Installation setup

Install WingetCord via npm or directly from GitHub.

Package Manager

bash
# Install from npm
npm install @wingetcord/wingetcord

# Or install latest from GitHub
npm install github:wingetcord/WingetCord

Requires Node.js 18+ and TypeScript 5.0+. Enable experimentalDecorators and emitDecoratorMetadata in your tsconfig.json to use the decorator API.

tsconfig.json

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "strict": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Quick Start example

Get a bot running in under 10 lines.

typescript
import { Client, Intents } from '@wingetcord/wingetcord';

const client = new Client({
  token: 'YOUR_BOT_TOKEN',
  intents: ['GUILDS', 'GUILD_MESSAGES', 'MESSAGE_CONTENT']
});

client.onReady((user) => {
  console.log(`🚀 Logged in as ${user.tag}`);
});

client.onMessage(async (msg) => {
  if (msg.content === '!ping') {
    await msg.reply('🏓 Pong!');
  }
});

client.login();

Client class

The Client class is the main entry point. It manages REST, Gateway, caching, commands, events, interactions, plugins, and more.

typescript
import { Client, IntentBits } from '@wingetcord/wingetcord';

const client = new Client({
  token: process.env.DISCORD_TOKEN,
  intents: [
    IntentBits.GUILDS,
    IntentBits.GUILD_MESSAGES,
    IntentBits.MESSAGE_CONTENT
  ]
});

Properties

PropertyTypeDescription
tokenstringBot authentication token
restRESTManagerHandles all REST API requests
gatewayGatewayManagerManages WebSocket connections
cacheCacheManagerIn-memory caching system
commandsCommandManagerManages prefix commands
eventsEventManagerManages event listeners
pluginsPluginManagerPlugin system
interactionsInteractionManagerHandles slash commands & components
handlerHandlerManagerAutomated resource discovery
voiceVoiceManagerVoice channel management
storeReactiveStoreReactive state management
userUser | nullThe current bot user

Methods

login()

Logs the bot in and establishes a gateway connection.

typescript
await client.login();

say(channelId, content)

High-level shortcut to send a message to a channel by ID.

typescript
await client.say('123456789', 'Hello, World!');
await client.say('123456789', { embeds: [embed], components: [] });

pulse()

Returns an instant health snapshot of the bot runtime.

typescript
const health = client.pulse();
// Returns: { status, ping, uptime, memory, guilds }
KeyTypeDescription
statusstring"healthy" | "degraded" | "down"
pingnumberGateway latency in ms
uptimenumberProcess uptime in seconds
memoryobjectHeap and RSS memory usage
guildsnumberTotal connected guilds

IntentBits enum

Bitfield flags to declare which events your bot will receive from the Discord Gateway.

GUILDS1 << 0
GUILD_MEMBERS1 << 1
GUILD_MODERATION1 << 2
GUILD_EMOJIS_AND_STICKERS1 << 3
GUILD_INTEGRATIONS1 << 4
GUILD_WEBHOOKS1 << 5
GUILD_INVITES1 << 6
GUILD_VOICE_STATES1 << 7
GUILD_PRESENCES1 << 8
GUILD_MESSAGES1 << 9
GUILD_MESSAGE_REACTIONS1 << 10
GUILD_MESSAGE_TYPING1 << 11
DIRECT_MESSAGES1 << 12
MESSAGE_CONTENT1 << 15
GUILD_SCHEDULED_EVENTS1 << 16
AUTO_MODERATION_EXECUTION1 << 21

Privileged IntentsGUILD_MEMBERS, GUILD_PRESENCES, and MESSAGE_CONTENT require explicit enabling in the Discord Developer Portal.

Commands & Events handlers

Register commands by extending the Command base class, or use decorators for a declarative style.

Command Class

typescript
import { Command, CommandContext } from '@wingetcord/wingetcord';

class PingCommand extends Command {
  options = {
    name: 'ping',
    description: 'Responds with pong',
    aliases: ['p'],
    cooldown: 5000,
    permissions: ['SendMessages']
  };

  async execute(ctx: CommandContext) {
    await ctx.message.reply('🏓 Pong!');
  }
}

client.commands.register(new PingCommand());
OptionTypeRequiredDescription
namestringrequiredCommand trigger name
descriptionstringoptionalCommand description
aliasesstring[]optionalAlternative trigger names
cooldownnumberoptionalCooldown in milliseconds
permissionsstring[]optionalRequired permissions

Event Class

typescript
class ReadyEvent extends Event {
  name = 'READY';
  once = true;
  execute() { console.log('Bot is ready!'); }
}
client.events.register(new ReadyEvent());

HandlerManager

Automatically discover and load all commands, events, and interactions from directories.

typescript
await client.handler.setup({
  commands:     './src/commands',
  events:       './src/events',
  interactions: './src/interactions'
});

Fluent Listeners events

Shorthand helpers for the most common events directly on the client.

typescript
client.onMessage((msg) => { /* MESSAGE_CREATE */ });
client.onInteraction((i) => { /* INTERACTION_CREATE */ });
client.onReady((user) => { /* READY */ });

Middleware advanced

Intercept and transform events with priority-based async middleware chains.

typescript
client.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  console.log(`[${ctx.event}] ${Date.now() - start}ms`);
});

Structures classes

Message

Property / MethodTypeDescription
idReadonly<string>Message snowflake ID
channelIdReadonly<string>Channel snowflake ID
guildIdstring | undefinedGuild ID (undefined in DMs)
contentstringMessage text content
authorUserMessage author
timestampDateSent timestamp
embedsEmbed[]Array of embed objects
attachmentsAttachment[]Attached files
reply(content)Promise<Message>Reply to this message
delete()Promise<void>Delete this message
pin()Promise<void>Pin this message
crosspost()Promise<Message>Crosspost to following channels

User

PropertyTypeDescription
idstringUser snowflake ID
usernamestringUsername
discriminatorstringUser discriminator
globalNamestring | nullDisplay name
avatarstring | nullAvatar hash
botbooleanWhether this user is a bot
tagstring"username#0000"
displayAvatarURLstringFull avatar CDN URL

Guild

PropertyTypeDescription
idstringGuild snowflake ID
namestringGuild name
iconstring | nullIcon hash
ownerIdstringOwner user ID
rolesCollectionMap of Role objects
emojisEmoji[]Array of emoji objects
featuresstring[]Enabled guild features

Member

PropertyTypeDescription
userUserUser object
nickstring | nullServer nickname
rolesstring[]Array of role IDs
joinedAtDateJoin timestamp
deafbooleanServer deafened
mutebooleanServer muted
permissionsPermissionsBitFieldCalculated permissions

Collection utility

An extended Map with utility methods for common data operations.

typescript
const col = new Collection<string, User>();
col.find(u => u.bot);    col.filter(u => u.bot);
col.map(u => u.tag);     col.some(u => u.bot);
col.every(u => !u.bot);  col.random();   col.first();

PermissionsBitField utility

typescript
const perms = new PermissionsBitField('SendMessages');
perms.has('SendMessages');     // true
perms.add('ManageMessages');
perms.remove('SendMessages');
perms.toJSON();

Builders components

EmbedBuilder

typescript
const embed = new EmbedBuilder()
  .setTitle('Hello World')
  .setDescription('This is an embed')
  .setColor('#6366f1')
  .addField('Field 1', 'Value 1', true)
  .setTimestamp()
  .setFooter('Footer text', 'https://example.com/icon.png');

ButtonBuilder

typescript
const button = new ButtonBuilder()
  .setCustomId('my-btn')
  .setLabel('Click Me')
  .setStyle(ButtonStyle.Primary)
  .setEmoji({ name: '👋' })
  .onAction(async (i) => { await i.reply('Clicked!'); });

SelectMenuBuilder

typescript
const select = new SelectMenuBuilder()
  .setCustomId('my-select')
  .setPlaceholder('Select an option')
  .addOptions(
    { label: 'Option 1', value: 'option1' },
    { label: 'Option 2', value: 'option2' }
  )
  .onAction(async (i) => { await i.reply(`Selected: ${i.values}`); });

ActionRowBuilder

typescript
const row = new ActionRowBuilder().addComponents(button, select);
await channel.send({ content: 'Choose:', components: [row] });

Enums & Constants enums

ButtonStyle

Primary1 — Blurple
Secondary2 — Grey
Success3 — Green
Danger4 — Red
Link5 — URL button

ComponentType

ActionRowtype: 1
Buttontype: 2
StringSelecttype: 3
TextInputtype: 4
UserSelecttype: 5
RoleSelecttype: 6

TextInputStyle

Short1 — Single line
Paragraph2 — Multi line

Advanced advanced

ReactiveStore

Proxy-based reactive state container. Subscribe to any property change with fine-grained listeners.

typescript
const store = new ReactiveStore({ count: 0 });
store.state.count = 5;

store.on('change', ({ property, oldValue, newValue }) => {
  console.log(`${property}: ${oldValue} → ${newValue}`);
});
store.on('change:count', ({ newValue }) => console.log(newValue));

Collector

Collect and filter interactions with built-in max/timeout limits.

typescript
const collector = client.interactions.createCollector({
  filter: (i) => i.customId === 'verify',
  max: 10, time: 60000
});
collector.on('collect', (i) => console.log(i.id));
collector.on('end', (collected, reason) => console.log(reason));

Decorators

Class-based command and event handlers using TypeScript decorators.

typescript
@Command({ name: 'ban', description: 'Ban a user' })
@Permissions('BAN_MEMBERS')
@Cooldown(1000)
@Option('user', { description: 'User to ban', required: true })
export class BanCommand {
  async execute(ctx: CommandContext) {
    const user = ctx.getUser('user');
  }
}

@Once('ready')
export class ReadyHandler {
  execute() { console.log('Ready!'); }
}

Caching

StrategyDescription
LRULeast Recently Used — evicts least recently accessed entries
LFULeast Frequently Used — evicts entries accessed least often
TTLTime To Live — entries expire after a set duration
MemoryFull in-memory caching, no automatic eviction

Color Utility

typescript
Color.resolve('#FF5733');       // hex string
Color.resolve(0xFF5733);        // hex number
Color.resolve([255, 87, 51]);   // RGB array
Color.resolve('random');        // random color
Color.toHex(16737203);          // → "#FF5733"
Color.toRGB(16737203);          // → [255, 87, 51]

Full Example reference

A complete bot with middleware, message commands, embeds, buttons, and slash command interactions.

typescript
import {
  Client, IntentBits, EmbedBuilder,
  ButtonBuilder, ButtonStyle, ActionRowBuilder
} from '@wingetcord/wingetcord';

const client = new Client({
  token: process.env.DISCORD_TOKEN,
  intents: [IntentBits.GUILDS, IntentBits.GUILD_MESSAGES, IntentBits.MESSAGE_CONTENT]
});

client.use(async (ctx, next) => {
  console.log(`[${ctx.event}]`); await next();
});

client.onReady((user) => console.log(`🚀 ${user.tag}`));

client.onMessage(async (msg) => {
  if (msg.content === '!help') {
    const embed = new EmbedBuilder()
      .setTitle('📖 Help')
      .setDescription('Available: !ping, !stats, !help')
      .setColor('#6366f1');

    const btn = new ButtonBuilder()
      .setLabel('Ping').setStyle(ButtonStyle.Primary)
      .setCustomId('ping')
      .onAction(async (i) => await i.reply('Pong!'));

    await msg.reply({
      embeds: [embed],
      components: [new ActionRowBuilder().addComponents(btn)]
    });
  }
  if (msg.content === '!ping')
    await msg.reply(`🏓 Pong! (${client.gateway.ping}ms)`);
});

client.interactions.on('command', async (i) => {
  if (i.commandName === 'stats') {
    const h = client.pulse();
    await i.reply({ embeds: [{
      title: '📊 Stats',
      fields: [
        { name: 'Ping',   value: `${h.ping}ms`,            inline: true },
        { name: 'Uptime', value: `${Math.floor(h.uptime)}s`, inline: true },
        { name: 'Guilds', value: `${h.guilds}`,             inline: true }
      ]
    }]});
  }
});

client.login();

Build & Run cli

bash
npm install          # Install dependencies
npm run build        # Compile TypeScript
npm run dev          # Run in development
npm run typecheck    # Type checking only
npm run clean        # Clean dist output