djs-commandsv2 docs
Migration from v1

Persistence

Mongoose schemas → Storage adapters

Persistence

v1 baked Mongoose into the framework with 7 hardcoded schemas. v2 splits storage out behind a generic Storage contract — pick @djs-commands/adapter-drizzle, @djs-commands/adapter-prisma, or @djs-commands/adapter-mongoose (the v1 continuity path).

Mongoose continuity

If you want to keep using Mongoose:

bun add @djs-commands/adapter-mongoose mongoose
import { mongooseStorage } from "@djs-commands/adapter-mongoose";
import mongoose from "mongoose";

const connection = mongoose.createConnection(process.env.MONGO_URI!);

createCommandHandler({
    client,
    storage: mongooseStorage(connection),
    // …
});

The collections (guild_prefix, disabled_commands, channel_locks) are auto-created by Mongoose when first written. You can swap to Drizzle/Postgres or Prisma later just by changing the adapter import — your bot code doesn't move.

Schema mapping

v1 collectionv2 modelWhat changed
cooldowns(in-memory + optional CacheAdapter)Cooldowns no longer hit the DB by default. Use @djs-commands/adapter-redis for sharded bots.
guild-prefix-schemaGuildPrefix modelResolved automatically when legacy.enabled + storage are set.
disabled-commands-schemaDisabledCommands modelSame shape, now part of the framework's gate chain.
channel-commands-schemaChannelLocks modelSame shape.
custom-command-schemadroppedThe custom-commands feature is gone.
required-permissions-schemadroppedUse the permissions property on defineCommand (static) or canRunCommand for runtime gating.
required-roles-schemadroppedUse the roles property on defineCommand (static) or canRunCommand.

Programmatic prefix / disabled / locks

v1 commands like /prefix, /togglecommand, /channelonly were built into the framework. v2 ships them as helpers so you can build admin commands of your own:

import {
    setGuildPrefix,
    disableCommand,
    enableCommand,
    lockCommandToChannel,
    unlockCommandFromChannel,
} from "@djs-commands/core";

await setGuildPrefix(storage, guildId, "?");
await disableCommand(storage, guildId, "ban");
await lockCommandToChannel(storage, guildId, "ban", channelId);

Switching adapters later

Because the Storage contract is the same across adapters, moving from Mongo to Postgres later means changing two lines:

- import { mongooseStorage } from "@djs-commands/adapter-mongoose";
- const connection = mongoose.createConnection(process.env.MONGO_URI!);
+ import { drizzleStorage } from "@djs-commands/adapter-drizzle";
+ import { drizzle } from "drizzle-orm/node-postgres";
+ import pg from "pg";
+ const db = drizzle(new pg.Pool({ connectionString: process.env.DATABASE_URL }));

  createCommandHandler({
      client,
-     storage: mongooseStorage(connection),
+     storage: drizzleStorage(db),
  });

Plus, of course, copying the framework's tables into your new schema (each adapter's README has the schema fragment).

On this page