Loaders
The entire ZombieClient framework is driven by loaders. A loader is essentially a plugin or module that handles a specific domain of logic.
Built-in Loaders
FileLoader
The FileLoader is responsible for finding .ts and .js files within your project recursively, while respecting an advanced ignore system.
The FileLoader is created internally by ZombieClient during login() and shared across all loaders via LoaderContext. You do not need to create it yourself.
Ignore path initialization is lazy and memoized - it happens automatically on the first loadFiles() call.
Ignore System:
- Filename Prefix: Any file starting with
#(e.g.,#ping.ts) is automatically ignored. .ignore.json: If you create a*.ignore.jsonfile anywhere in your project, it can contain an array of files or directories to ignore.
["old_commands/", "test.ts"]CommandLoader
The CommandLoader handles your slash commands and context menu commands. It no longer requires client or fileLoader in the constructor - those are provided via LoaderContext when load() is called.
new CommandLoader(path.resolve(process.cwd(), 'src/commands'), {
autoDeploy: true,
useGlobal: false,
defaultGuilds: ['123456789'],
defaultCooldown: 5,
});Key behavior:
deploy(): Compares local commands with Discord's API and updates them intelligently without hitting rate limits.listen(): Called automatically insideload()- registers theinteractionCreateevent to route commands and handle cooldowns. You do not need to call this yourself.
EventLoader
The EventLoader automatically registers all your Discord.js events. Like CommandLoader, it only requires the directory path in the constructor.
new EventLoader(path.resolve(process.cwd(), 'src/events'));It wraps all handlers in a safe try/catch block so that your bot never crashes from an unhandled exception inside an event.
Creating Custom Loaders
You can create your own loader by implementing the ILoader interface. The load() method receives a LoaderContext with the client and shared FileLoader. This is perfect for setting up a Database connection, a Redis cache, or an Express API server alongside your bot.
import type { ILoader, LoaderContext } from '@thezombiepl/zombieclient/interfaces';
export class DatabaseLoader implements ILoader {
public readonly name = 'DatabaseLoader';
async load(ctx: LoaderContext): Promise<void> {
const { client } = ctx;
// e.g., await mongoose.connect(process.env.MONGO_URI);
console.log('[DatabaseLoader] Connected to database');
}
}Register it alongside the built-in loaders in the constructor:
const client = new ZombieClient({
intents: [...],
loaders: [
new CommandLoader(...),
new EventLoader(...),
new DatabaseLoader(),
],
});Or dynamically for conditional registration:
if (isDev) {
client.registerLoaders([new DebugLoader()]);
}