aifordiscord-components-v2
v1.0.4
Published
Advanced Discord Components v2 library for creating interactive UIs with TypeScript support
Maintainers
Readme
AIForDiscord Components
🚀 Production-ready Discord Components v2 library with TypeScript support, advanced interaction handling, and comprehensive error management.
An enterprise-grade npm package that revolutionizes Discord bot development by providing intuitive builders, automatic handler management, and robust component interactions with zero configuration.
✨ Features
🎯 Core Features
- 🔷 Full TypeScript Support - Complete type safety with IntelliSense
- ⚡ Zero Configuration - Works out of the box with sensible defaults
- 🎨 All Component Types - Buttons, Select Menus, Modals, and Forms
- 🔄 Smart Handler Routing - Automatic interaction management and routing
- 🆔 Collision-Free IDs - Automatic custom ID generation with scoping
- 📋 Advanced Pagination - Built-in pagination with customizable controls
- 🛡️ Error Resilience - Comprehensive error handling with recovery
🚀 Advanced Features
- 📊 Performance Monitoring - Built-in metrics and handler statistics
- ⏰ Timeout Management - Automatic cleanup of expired interactions
- 🔐 Permission Guards - Role and permission-based access control
- 🎛️ Middleware System - Extensible middleware for custom logic
- 📝 Form Validation - Advanced form validation with custom rules
- 🔄 State Management - Persistent component state across interactions
- 🌐 i18n Support - Multi-language support for global bots
- 📈 Analytics Ready - Built-in hooks for analytics integration
📦 Installation
# Using npm
npm install aifordiscord-components discord.js
# Using yarn
yarn add aifordiscord-components discord.js
# Using pnpm
pnpm add aifordiscord-components discord.jsRequirements
- Node.js 16.9.0 or higher
- Discord.js v14.0.0 or higher
- TypeScript 5.0+ (for TypeScript projects)
🚀 Quick Start
Basic Setup
import { Client, GatewayIntentBits } from 'discord.js';
import {
createComponentApp,
createPrimaryButton,
createStringSelectMenu,
createModalForm
} from 'aifordiscord-components-v2';
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
});
// Initialize component handling with advanced options
const componentApp = createComponentApp({
errorHandler: async (error, interaction) => {
console.error('Component error:', error);
await interaction.reply({
content: '⚠️ Something went wrong. Please try again.',
ephemeral: true
});
},
defaultTimeout: 300000, // 5 minutes
enableMetrics: true
});
client.once('ready', () => {
console.log(`✅ ${client.user?.tag} is ready!`);
componentApp.initialize(client);
// Log component statistics
setInterval(() => {
const stats = componentApp.getStats();
console.log(`📊 Active handlers: ${stats.totalHandlers}`);
}, 60000);
});
client.login(process.env.DISCORD_TOKEN);Advanced Component Examples
🔘 Smart Buttons with Permissions
import { createPrimaryButton, createDangerButton } from 'aifordiscord-components';
// Button with permission check
const adminButton = createPrimaryButton(
'🛡️ Admin Panel',
async (interaction) => {
if (!interaction.member?.permissions.has('Administrator')) {
return interaction.reply({
content: '❌ Administrator permission required!',
ephemeral: true
});
}
await interaction.reply({
content: '🎛️ Admin panel opened!',
ephemeral: true
});
}
).setEmoji('🛡️');
// Confirmation button with state
const deleteButton = createDangerButton(
'Delete Server',
async (interaction) => {
const confirmButton = createDangerButton(
'Yes, Delete Forever',
async (confirmInteraction) => {
await confirmInteraction.reply('🗑️ Server deletion initiated...');
// Actual deletion logic here
}
);
await interaction.reply({
content: '⚠️ **Are you absolutely sure?** This action cannot be undone!',
components: [{ type: 1, components: [confirmButton.build()] }],
ephemeral: true
});
}
);📋 Advanced Select Menus
import { createStringSelectMenu, createRoleSelectMenu } from 'aifordiscord-components-v2';
// Multi-select with custom validation
const skillsMenu = createStringSelectMenu()
.setPlaceholder('🎯 Select your skills (max 3)')
.setMinValues(1)
.setMaxValues(3)
.setOptions([
{
label: 'JavaScript',
value: 'js',
description: 'Frontend & Backend development',
emoji: '🟡'
},
{
label: 'TypeScript',
value: 'ts',
description: 'Type-safe development',
emoji: '🔷'
},
{
label: 'Python',
value: 'py',
description: 'AI & Data Science',
emoji: '🐍'
},
{
label: 'React',
value: 'react',
description: 'Frontend framework',
emoji: '⚛️'
}
])
.onInteraction(async (interaction) => {
const skills = interaction.values;
const skillNames = skills.map(skill => {
const option = interaction.component.options.find(opt => opt.value === skill);
return option?.label;
}).join(', ');
await interaction.reply({
content: `🎉 Great! Your selected skills: **${skillNames}**`,
ephemeral: true
});
});
// Role management select menu
const roleMenu = createRoleSelectMenu()
.setPlaceholder('👥 Assign roles to user')
.setMaxValues(5)
.onInteraction(async (interaction) => {
const member = interaction.guild?.members.cache.get('USER_ID');
const roles = interaction.values;
if (member) {
await member.roles.add(roles);
await interaction.reply(`✅ Assigned ${roles.length} role(s) successfully!`);
}
});📝 Advanced Modal Forms
import { createModalForm } from 'aifordiscord-components-v2';
// Complex form with validation and conditional logic
const applicationForm = createModalForm('💼 Job Application')
.addShortTextField('name', 'Full Name', {
placeholder: 'Enter your full name',
required: true,
maxLength: 100
})
.addShortTextField('email', 'Email Address', {
placeholder: '[email protected]',
required: true,
maxLength: 255
})
.addShortTextField('experience', 'Years of Experience', {
placeholder: 'e.g., 3',
required: true,
maxLength: 2
})
.addParagraphField('motivation', 'Why do you want to join us?', {
placeholder: 'Tell us about your motivation...',
required: true,
maxLength: 1000
})
.addParagraphField('portfolio', 'Portfolio/GitHub Links', {
placeholder: 'Share your work (optional)',
required: false,
maxLength: 500
})
// Advanced validation
.addValidation('email', (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) return 'Please enter a valid email address';
return true;
})
.addValidation('experience', (value) => {
const years = parseInt(value);
if (isNaN(years) || years < 0 || years > 50) {
return 'Experience must be a number between 0 and 50';
}
return true;
})
.addValidation('motivation', (value) => {
if (value.length < 50) return 'Please provide at least 50 characters';
if (value.split(' ').length < 10) return 'Please provide a more detailed response';
return true;
})
// Custom validation error handling
.setValidationErrorHandler(async (fieldId, error, interaction) => {
await interaction.reply({
content: `❌ **${fieldId.toUpperCase()}**: ${error}`,
ephemeral: true
});
})
.onSubmit(async (interaction) => {
const data = {
name: interaction.fields.getTextInputValue('name'),
email: interaction.fields.getTextInputValue('email'),
experience: interaction.fields.getTextInputValue('experience'),
motivation: interaction.fields.getTextInputValue('motivation'),
portfolio: interaction.fields.getTextInputValue('portfolio') || 'Not provided'
};
// Store application data
await storeApplication(data);
// Send confirmation
await interaction.reply({
content: `✅ **Application Submitted Successfully!**\n\nThank you, **${data.name}**! We'll review your application and get back to you soon.`,
ephemeral: true
});
// Notify admins
const adminChannel = interaction.guild?.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel?.isTextBased()) {
await adminChannel.send(`📋 New job application from **${data.name}** (${data.experience} years experience)`);
}
});📖 Smart Pagination System
import { createPagination } from 'aifordiscord-components-v2';
// Advanced pagination with custom controls
const helpPages = [
{
embeds: [{
title: '📚 Help - Getting Started',
description: 'Learn the basics of using our bot...',
color: 0x00AE86,
fields: [
{ name: '🚀 Quick Start', value: 'Run `/help` to see all commands', inline: false }
]
}]
},
{
embeds: [{
title: '🎮 Help - Commands',
description: 'Available commands and their usage...',
color: 0x00AE86,
fields: [
{ name: '💬 Chat Commands', value: '`/chat` - Start a conversation', inline: true },
{ name: '🎵 Music Commands', value: '`/play` - Play music', inline: true }
]
}]
},
{
embeds: [{
title: '⚙️ Help - Settings',
description: 'Customize your experience...',
color: 0x00AE86,
fields: [
{ name: '🔧 Server Settings', value: 'Configure bot behavior', inline: false }
]
}]
}
];
const pagination = createPagination({
pages: helpPages,
timeout: 600000, // 10 minutes
showPageNumbers: true,
customButtons: {
first: { emoji: '⏮️', style: 'Secondary' },
prev: { emoji: '◀️', style: 'Primary' },
next: { emoji: '▶️', style: 'Primary' },
last: { emoji: '⏭️', style: 'Secondary' },
stop: { emoji: '⏹️', style: 'Danger', label: 'Close' }
}
});
// Usage in command
const paginationMessage = await pagination.start();
await interaction.reply(paginationMessage);🏗️ Architecture & Best Practices
Component App Configuration
import { createComponentApp } from 'aifordiscord-components-v2';
const componentApp = createComponentApp({
// Error handling
errorHandler: async (error, interaction) => {
console.error(`[${new Date().toISOString()}] Component Error:`, error);
// Send user-friendly error message
const message = {
content: '⚠️ An unexpected error occurred. Our team has been notified.',
ephemeral: true
};
if (!interaction.replied && !interaction.deferred) {
await interaction.reply(message);
} else if (interaction.deferred) {
await interaction.editReply(message);
}
// Log to external service (optional)
// await logError(error, interaction);
},
// Performance settings
defaultTimeout: 300000, // 5 minutes
cleanupInterval: 600000, // 10 minutes
maxHandlers: 10000,
// Monitoring
enableMetrics: true,
metricsInterval: 30000, // 30 seconds
// Custom ID settings
customIdSeparator: ':',
scopePrefix: 'app'
});ID Management & Scoping
import { idManager } from 'aifordiscord-components-v2';
// Create feature-specific scopes
const ticketScope = idManager.createScope('tickets');
const musicScope = idManager.createScope('music');
// Generate collision-free IDs
const ticketButton = idManager.generateId('create', ticketScope);
const musicButton = idManager.generateId('play', musicScope);
// Advanced ID patterns
const userScopedId = idManager.generateId('profile', ticketScope, interaction.user.id);
const channelScopedId = idManager.generateId('settings', musicScope, interaction.channel?.id);Middleware System
// Custom middleware for logging
const loggingMiddleware = async (interaction, next) => {
console.log(`[${interaction.type}] ${interaction.customId} by ${interaction.user.tag}`);
const start = Date.now();
await next();
const duration = Date.now() - start;
console.log(`Completed in ${duration}ms`);
};
// Permission middleware
const adminMiddleware = async (interaction, next) => {
if (!interaction.member?.permissions.has('Administrator')) {
await interaction.reply({
content: '❌ Administrator permission required!',
ephemeral: true
});
return;
}
await next();
};
// Apply middleware to components
const adminButton = createPrimaryButton('Admin Action', async (interaction) => {
await interaction.reply('✅ Admin action completed!');
})
.addMiddleware(loggingMiddleware)
.addMiddleware(adminMiddleware);📊 Monitoring & Analytics
Performance Metrics
// Get detailed statistics
const stats = componentApp.getStats();
console.log(`
📊 Component Statistics:
├─ Total Handlers: ${stats.totalHandlers}
├─ Active Interactions: ${stats.activeInteractions}
├─ Memory Usage: ${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB
├─ Uptime: ${(process.uptime() / 3600).toFixed(2)} hours
└─ Response Time: ${stats.averageResponseTime}ms
`);
// Monitor specific component performance
const buttonMetrics = componentApp.getMetrics('button');
const modalMetrics = componentApp.getMetrics('modal');Error Tracking Integration
// Sentry integration example
import * as Sentry from '@sentry/node';
const componentApp = createComponentApp({
errorHandler: async (error, interaction) => {
// Track error with context
Sentry.withScope((scope) => {
scope.setTag('component', 'discord-interaction');
scope.setUser({
id: interaction.user.id,
username: interaction.user.tag
});
scope.setContext('interaction', {
customId: interaction.customId,
type: interaction.type,
guildId: interaction.guildId,
channelId: interaction.channelId
});
Sentry.captureException(error);
});
await interaction.reply({
content: '⚠️ Something went wrong. We\'ve been notified!',
ephemeral: true
});
}
});🌐 Internationalization (i18n)
import { createComponentApp, createPrimaryButton } from 'aifordiscord-components';
// i18n configuration
const translations = {
en: {
welcome: 'Welcome!',
button_clicked: 'Button clicked!',
error_occurred: 'An error occurred'
},
es: {
welcome: '¡Bienvenido!',
button_clicked: '¡Botón presionado!',
error_occurred: 'Ocurrió un error'
},
fr: {
welcome: 'Bienvenue!',
button_clicked: 'Bouton cliqué!',
error_occurred: 'Une erreur s\'est produite'
}
};
// Locale detection helper
const getUserLocale = (interaction) => {
return interaction.locale?.split('-')[0] || 'en';
};
// Localized button
const welcomeButton = createPrimaryButton(
'Welcome',
async (interaction) => {
const locale = getUserLocale(interaction);
const message = translations[locale]?.button_clicked || translations.en.button_clicked;
await interaction.reply({
content: message,
ephemeral: true
});
}
);🧪 Testing
Unit Testing with Jest
// tests/components.test.ts
import { createPrimaryButton, createStringSelectMenu } from 'aifordiscord-components';
describe('AIForDiscord Components', () => {
test('should create button with handler', () => {
const handler = jest.fn();
const button = createPrimaryButton('Test Button', handler);
expect(button).toBeDefined();
expect(button.build().data.label).toBe('Test Button');
expect(button.build().data.style).toBe(1); // Primary
});
test('should create select menu with options', () => {
const handler = jest.fn();
const select = createStringSelectMenu()
.setPlaceholder('Choose...')
.setOptions([
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' }
])
.onInteraction(handler);
expect(select.build().data.placeholder).toBe('Choose...');
expect(select.build().data.options).toHaveLength(2);
});
});📚 Examples & Use Cases
🎫 Complete Support Ticket System
- Ticket Panel Example - Full-featured support system
- Advanced form validation and data persistence
- Role-based access control and staff notifications
🤖 Interactive Bot Dashboard
- Bot Management Example - Complete bot with all features
- Server configuration, user management, and analytics
- Multi-language support and custom themes
📊 Data Collection & Surveys
- Survey System Example - Interactive data collection
- Multi-step forms, conditional logic, and data export
- Real-time validation and progress tracking
🔧 Configuration Options
Advanced Component App Settings
interface ComponentAppOptions {
errorHandler?: ErrorHandler;
defaultTimeout?: number;
cleanupInterval?: number;
maxHandlers?: number;
enableMetrics?: boolean;
metricsInterval?: number;
customIdSeparator?: string;
scopePrefix?: string;
middleware?: Middleware[];
rateLimiting?: RateLimitOptions;
persistence?: PersistenceOptions;
}Performance Tuning
// High-performance configuration
const componentApp = createComponentApp({
maxHandlers: 50000,
cleanupInterval: 300000, // 5 minutes
enableMetrics: true,
rateLimiting: {
maxRequests: 100,
windowMs: 60000 // 1 minute
}
});🚀 Deployment & Production
Environment Variables
# .env
DISCORD_TOKEN=your_bot_token
NODE_ENV=production
LOG_LEVEL=info
SENTRY_DSN=your_sentry_dsn
DATABASE_URL=your_database_urlProduction Checklist
- ✅ Error Handling: Comprehensive error handling implemented
- ✅ Rate Limiting: Protection against abuse
- ✅ Monitoring: Metrics and logging configured
- ✅ Security: Permission checks and input validation
- ✅ Performance: Optimized for high-traffic servers
- ✅ Scalability: Horizontal scaling support
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/aifordiscord/aifordiscord-components.git
cd aifordiscord-components
# Install dependencies
npm install
# Build the project
npm run build
# Run tests
npm test
# Start development
npm run devCommit Convention
We use Conventional Commits:
feat: add new modal validation system
fix: resolve button interaction timeout
docs: update API documentation
test: add pagination unit tests📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Discord.js Team - For the excellent Discord library
- TypeScript Team - For type safety and developer experience
- Open Source Community - For inspiration and contributions
- Our Contributors - Thank you for making this project better!
📞 Support & Community
- 🐛 Bug Reports: GitHub Issues
- 💡 Feature Requests: GitHub Discussions
- 📖 Documentation: Full Documentation
- 💬 Discord Server: Join our community
🗺️ Roadmap
Upcoming Features
- 🔄 v2.0: React-like component composition
- 🎨 Theme System: Pre-built UI themes and templates
- 🔌 Plugin Architecture: Extensible plugin system
- 📱 Mobile Optimization: Enhanced mobile Discord support -integrations**: Webhook and API integrations
- 🤖 AI Components: AI-powered interactive components
Made with ❤️ by the AIForDiscord Team
⭐ Star us on GitHub • 📦 View on NPM • 🐦 Follow us on Twitter
