Eris Command Framework
The Eris Command Framework (version 3.0.0) is a library designed to streamline the creation of command-based bots for the Eris Discord API library. It facilitates defining commands and plugins using TypeScript decorators (`@Command()`) and relies heavily on `reflect-metadata`, `TypeORM` for database interactions, and `Inversify` for dependency injection. The framework's architecture centers around `PluginInterface` and `CommandInterface` concepts. While functional, the project's README explicitly advises users to transition to Eris's native slash commands, indicating that this framework is no longer the recommended or actively developed approach for modern Eris bot development. As such, its release cadence is likely slow or halted, and users should consider alternatives for new projects. Its reliance on specific versions of TypeORM and Inversify can also lead to compatibility challenges with newer versions of those libraries or Eris itself.
Common errors
-
TypeError: Reflect.getMetadata is not a function
cause The `reflect-metadata` polyfill was not imported or `emitDecoratorMetadata` is false in `tsconfig.json`.fixAdd `import 'reflect-metadata';` to the very top of your application's entry file and ensure `"emitDecoratorMetadata": true` and `"experimentalDecorators": true` are set in `tsconfig.json`. -
Error: CommandFramework options must contain a prefix!
cause The `prefix` option was not provided when initializing `CommandFramework`.fixWhen creating `new CommandFramework(container, { prefix: '|' })`, ensure the `prefix` property is set in the options object. -
Error: Cannot find module 'eris-command-framework' or Cannot find name 'CommandFramework'.
cause Attempting to use CommonJS `require()` syntax with an ESM-only package (v3+) or a TypeScript configuration issue preventing module resolution.fixEnsure your project uses `"type": "module"` in `package.json`, use `import { CommandFramework } from 'eris-command-framework';`, and verify your `tsconfig.json` `module` and `moduleResolution` settings (e.g., `"module": "NodeNext"`, `"moduleResolution": "NodeNext"`). -
QueryFailedError: SQLITE_ERROR: no such table: my_bot_entity
cause TypeORM entities were not correctly registered with the database connection, or `synchronize: true` was not set/ran during development.fixEnsure your entity classes are included in the `entities` array passed to `createConnection()` (e.g., `entities: [MyBotEntity, ...commandFramework.GetEntities()]`). For development, ensure `synchronize: true` is enabled or migrations are run.
Warnings
- deprecated The README explicitly states, 'You should probably just use slash commands now...' This indicates the framework is no longer the recommended solution for new Eris bots and users should transition to native Discord slash commands for future development.
- breaking Version 3.0.0 moved to a full ESM-only distribution. Projects using CommonJS (require()) will experience 'Cannot find module' errors.
- gotcha The framework heavily relies on TypeScript decorators and `reflect-metadata`. Misconfiguration of `tsconfig.json` (specifically `emitDecoratorMetadata` and `experimentalDecorators`) will prevent commands from being discovered.
- gotcha This framework has tight peer dependencies on specific major versions of `eris`, `typeorm`, `inversify`, and `winston`. Upgrading these peer dependencies in your project without testing against the framework can lead to runtime errors or unexpected behavior.
Install
-
npm install eris-command-framework -
yarn add eris-command-framework -
pnpm add eris-command-framework
Imports
- CommandFramework
const CommandFramework = require('eris-command-framework').CommandFramework;import { CommandFramework } from 'eris-command-framework'; - Command
import Command from 'eris-command-framework/decorators/command';
import { Command } from 'eris-command-framework'; - Interfaces
import * as Interfaces from 'eris-command-framework/interfaces';
import { Interfaces } from 'eris-command-framework'; - Container
import Container from 'inversify';
import { Container } from 'inversify'; - createConnection
import createConnection from 'typeorm';
import { createConnection } from 'typeorm';
Quickstart
import { CommandFramework, Interfaces, types, Command } from 'eris-command-framework';
import { Client, Message } from 'eris';
import { Container } from 'inversify';
import { createConnection, Connection, Entity, PrimaryColumn, Column } from 'typeorm';
import 'reflect-metadata'; // Must be imported once at the top level
const token = process.env.DISCORD_BOT_TOKEN ?? 'YOUR_DISCORD_BOT_TOKEN';
// --- Dummy TypeORM Entity ---
@Entity()
class MyBotEntity {
@PrimaryColumn()
id!: string;
@Column()
value!: string;
}
// --- Example Plugin and Command ---
@Command({
name: 'ping',
category: 'General',
description: 'Responds with pong!',
args: []
})
class PingCommand implements Interfaces.CommandInterface {
name: string = 'ping';
async run(message: Message, _args: string[]): Promise<any> {
await message.channel.createMessage('Pong!');
}
}
class MyPlugin implements Interfaces.PluginInterface {
name: string = 'MyPlugin';
commands: Interfaces.CommandInterface[] = [
new PingCommand()
];
// You might inject dependencies here using Inversify
constructor() {}
}
async function bootstrap() {
const client = new Client(token);
const container = new Container({ defaultScope: 'singleton' });
const commandFramework = new CommandFramework(container, { prefix: '|' }); // Prefix is required
const connection: Connection = await createConnection(
{
type: 'sqlite',
database: ':memory:', // Use in-memory for quick demo
synchronize: true,
entities: [
MyBotEntity,
...commandFramework.GetEntities() // Include framework's internal entities
]
}
);
container.bind<Connection>(types.Connection).toConstantValue(connection);
const plugins: Interfaces.PluginInterface[] = [
new MyPlugin() // Your array of PluginInterfaces
];
await commandFramework.Initialize(plugins);
client.on('ready', () => {
console.log('Bot is ready and connected!');
});
client.on('messageCreate', async (message: Message) => {
// Check if the message starts with the command prefix
if (message.author.bot || !message.content.startsWith(commandFramework.getOptions().prefix)) {
return;
}
await commandFramework.Handle(message);
});
client.on('error', (err: Error) => console.error('Eris client error:', err));
client.connect().catch(console.error);
console.log('Bot is attempting to connect to Discord...');
}
bootstrap().catch(console.error);