Migration from v1
Handler options
Mapping every v1 CommandHandler option to v2
Handler options
Every option you passed to new CommandHandler({ … }) in v1 has a mapping in v2.
| v1 option | v2 equivalent |
|---|---|
client | client (unchanged) |
mongoUri | storage: mongooseStorage(connection) from @djs-commands/adapter-mongoose |
commandDir | commandDir (unchanged — fs-autoloader is still the default) |
featuresDir | plugins: [...] — see Events and plugins |
events.dir | eventDir |
defaultPrefix | legacy: { enabled: true, defaultPrefix: "!" } |
botOwners | botOwners (unchanged) |
cooldownConfig | per-command cooldown: { type, duration } (no global config) |
testServers | dropped — handle via your own deploy logic per guild |
defaultCommand | dropped — built-in admin commands removed; build your own |
antiCrash | dropped — use process-level unhandledRejection / uncaughtException |
Worked example
// v1
import CommandHandler from "@d3oxy/djs-commands";
import { Client, IntentsBitField } from "discord.js";
const client = new Client({
intents: [
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMessages,
IntentsBitField.Flags.MessageContent,
],
});
client.on("ready", () => {
new CommandHandler({
client,
mongoUri: process.env.MONGO_URI,
commandDir: path.join(__dirname, "commands"),
featuresDir: path.join(__dirname, "features"),
defaultPrefix: "!",
botOwners: ["123…"],
events: { dir: path.join(__dirname, "events") },
cooldownConfig: { dbRequired: 300 },
});
});
client.login(process.env.TOKEN);// v2
import { createCommandHandler } from "@djs-commands/core";
import { mongooseStorage } from "@djs-commands/adapter-mongoose";
import { Client, GatewayIntentBits } from "discord.js";
import { fileURLToPath } from "node:url";
import mongoose from "mongoose";
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});
const connection = mongoose.createConnection(process.env.MONGO_URI!);
createCommandHandler({
client,
storage: mongooseStorage(connection),
commandDir: fileURLToPath(new URL("./commands", import.meta.url)),
eventDir: fileURLToPath(new URL("./events", import.meta.url)),
legacy: { enabled: true, defaultPrefix: "!" },
botOwners: ["123…"],
// cooldowns are per-command in v2 — no global config
});
await client.login(process.env.TOKEN!);Notes:
- v2 doesn't wait for
readyto wire up — you callcreateCommandHandlersynchronously after constructing theClient. - v2's
commandDiraccepts a path string. We usefileURLToPath(new URL(...))so it works under both Bun and Node + tsx; v1'spath.join(__dirname, ...)worked because v1 was CJS — v2 is ESM. cooldownConfig.dbRequired(v1's "use DB if duration ≥ 5min") doesn't exist. Cooldowns default to in-memory; provide acacheAdapter(e.g.@djs-commands/adapter-redis) for distributed cooldowns.