Recipes
Database Integration
Seyfert is database-agnostic — you can attach any database client (Prisma, Drizzle, Mongoose, etc.) to your bot. Here are the two recommended patterns.
Pattern 1: Module Augmentation
The simplest approach. Attach the database client to the Seyfert client instance and declare its type:
import { , type } from 'seyfert';
// Replace with your actual database client (Prisma, Drizzle, etc.)
declare class {
(): <void>;
(: string): <{ : string; : number } | null>;
}
const = new () as & { : };
. = new ();
await ..();
await .();
await .();
declare module 'seyfert' {
interface UsingClient extends <<true>> {}
interface {
: ;
}
}Pattern 2: Extended Client Class
A more structured approach using class inheritance:
class extends <true> {
= new ();
async () {
await this..();
this.({
// middlewares, cache, etc.
});
await this.();
await this.();
}
}
const = new ();
await .();
declare module 'seyfert' {
interface UsingClient extends <> {}
}Usage in Commands
Once the database client is attached, access it from any command via ctx.client.db:
import { Command, Declare, type CommandContext } from 'seyfert';
@Declare({
name: 'balance',
description: 'Check your balance',
})
export default class BalanceCommand extends Command {
async run(ctx: CommandContext) {
const user = await ctx.client.db.findUser(ctx.author.id);
if (!user) {
return ctx.write({ content: 'You have no account yet.' });
}
await ctx.write({
content: `Your balance: **${user.balance}** coins`,
});
}
}Usage in Events
The same pattern works in events, since the client is always available:
import { createEvent } from 'seyfert';
export default createEvent({
data: { name: 'guildMemberAdd' },
async run(member, client) {
await client.db.createUser(member.id, {
guildId: member.guildId,
joinedAt: new Date(),
});
},
});Usage in Middlewares
import { createMiddleware } from 'seyfert';
interface UserData {
id: string;
isPremium: boolean;
}
export const withUser = createMiddleware<UserData>(async ({ context, next, stop }) => {
const user = await context.client.db.findUser(context.author.id);
if (!user) {
return stop('You need to create an account first. Use /register.');
}
next(user);
});Then access the data in your command with type safety:
import { Command, Declare, Middlewares, type CommandContext } from 'seyfert';
@Declare({
name: 'premium',
description: 'Check premium status',
})
@Middlewares(['withUser'])
export default class PremiumCommand extends Command {
async run(ctx: CommandContext<never, 'withUser'>) {
const user = ctx.metadata.withUser;
await ctx.write({
content: user.isPremium ? 'You are a premium user!' : 'You are not premium.',
});
}
}