Drift KV Configuration Guide
This guide provides a comprehensive overview of Drift KV's configuration options and how to use them effectively.
Configuration Overview
The Drift KV configuration is passed to the Drift constructor and consists of several key sections:
interface DriftConfig<
TEntities extends Record<string, DriftEntity<any, any, any>> = {},
TQueues extends Record<string, DriftQueue<any, any, any, any, any>> = {}
> {
client: Kv;
schemas: DriftSchemas<TEntities, TQueues>;
hooks?: DriftHooks<TEntities, TQueues>;
}
Database Configuration
Client Setup
// Basic client setup
const client = await Deno.openKv();
const drift = new Drift({
client,
// Additional configuration...
});
Connection Options
The client connection can be customized with various options:
// Default client
const kv = await Deno.openKv();
// KV Connect URL
const kv = await openKv("<KV Connect URL>");
// In-memory database
const kv = await openKv(":memory:");
// Custom database path (SQLite)
const kv = await openKv("./my-database.sqlite");
Schema Configuration
Entity Schemas
Define your entity schemas using Zod for type safety and validation:
const drift = new Drift({
schemas: {
entities: {
user: (drift) => new DriftEntity(drift, {
name: "user",
schema: (z) => {
name: z.string().min(3),
email: z.string().email(),
role: z.enum(["user", "admin"]).default("user"),
},
options: {
timestamps: true
},
}),
},
},
});
Queue Schemas
Define queue schemas for background processing:
const drift = new Drift({
schemas: {
queues: {
emailQueue: (drift) => new DriftQueue(drift, {
name: "email",
schema: z.object({
to: z.string().email(),
subject: z.string(),
body: z.string(),
}),
handler: async (data) => {
// Queue processing logic
},
}),
},
},
});
Lifecycle Hooks
Available Hooks
Drift KV provides various hooks for different lifecycle events:
interface DriftHooks {
/** Called when database connection is made. */
onConnect?: (client: Kv) => Promise<void>;
/** Called when an error occurs. */
onError?: (error: Error) => Promise<void>;
/** Called before executing a query. */
beforeQuery?: (query: DriftQueryArgs<TEntities[keyof TEntities]>) => Promise<void>;
/** Called during query execution. */
onQuery?: (query: DriftQueryArgs<TEntities[keyof TEntities]>) => Promise<void>;
/** Called after query execution. */
afterQuery?: (result: QueryResponse<TEntities[keyof TEntities]>) => Promise<void>;
/** Called before a job is scheduled */
onJobBeforeSchedule?: (job: DriftQueueJob<TQueues[keyof TQueues]>) => Promise<void>;
/** Called after a job is scheduled */
onJobSchedule?: (job: DriftQueueJob<TQueues[keyof TQueues]>) => Promise<void>;
/** Called when a job encounters an error */
onJobError?: (error: Error, job: DriftQueueJob<TQueues[keyof TQueues]>) => Promise<void>;
/** Called after a job is processed */
onJobEnd?: (result: DriftQueueJob<TQueues[keyof TQueues]>) => Promise<void>;
}
Implementing Hooks
Example of implementing various hooks:
const drift = new Drift({
client,
schemas: {
entities: {
user: (drift) => new DriftEntity(drift, {
name: "user",
schema: (z) => {
name: z.string().min(3),
email: z.string().email(),
role: z.enum(["user", "admin"]).default("user"),
},
}),
},
},
hooks: {
onConnect: async (client) => {
console.log("Database connected successfully");
// Initialize post-connection resources
},
onError: async (error) => {
console.error("Database error:", error);
// Log error to monitoring service
},
beforeQuery: async (query) => {
console.log("Executing query:", query);
// Validate or modify query
},
afterQuery: async (result) => {
console.log("Query result:", result);
// Process or transform results
},
onJobBeforeSchedule: async (job) => {
console.log("Scheduling job:", job);
// Prepare job context
},
onJobSchedule: async (job) => {
console.log("Job scheduled:", job);
// Initialize post-scheduling resources
},
onJobError: async (error, job) => {
console.error("Job error:", error, job);
// Log error to monitoring service
},
onJobEnd: async (result) => {
console.log("Job result:", result);
// Process or transform results
},
},
});
Advanced Configuration
Entity Options
Configure individual entities with specific options:
new DriftEntity(drift, {
name: "user",
schema: (z) => {
name: z.string().min(3),
email: z.string().email(),
role: z.enum(["user", "admin"]).default("user"),
},
options: {
timestamps: true,
},
hooks: {
beforeCreate: async (data) => {
// Pre-creation logic
},
afterUpdate: async (result) => {
// Post-update logic
},
},
});
Queue Options
Configure job queues with specific options:
new DriftQueue(drift, {
name: "emailQueue",
schema: emailSchema,
hooks: {
onError: async (error, data) => {
// Error handling logic
},
},
});
Environment-Specific Configuration
Development Configuration
const isDev = process.env.NODE_ENV === "development";
const getHooks = () => {
if (isDev) {
return {
beforeQuery: async (query) => {
console.log("DEV MODE - Query:", query);
},
};
}
};
const drift = new Drift({
// rest of config,
hooks: getHooks(),
});
Production Configuration
const isProd = process.env.NODE_ENV === "production";
const drift = new Drift({
// rest of config,
hooks: {
onError: async (error) => {
// Send to error monitoring service
await sendToErrorMonitoring(error);
},
afterQuery: isProd ? async (result) => {
// Performance monitoring in production
await measureQueryPerformance(result);
} : undefined,
},
});
Best Practices
-
Configuration Organization
- Keep configuration modular and environment-specific
- Use environment variables for sensitive information
- Implement proper error handling in hooks
-
Schema Design
- Use strict types with Zod
- Implement proper validation
- Consider indexing strategy
-
Hook Implementation
- Keep hooks focused and lightweight
- Implement proper error handling
- Consider performance impact
Next Steps
- Learn about Architecture
- Explore Entity Management
- Implement Real-time Features
Discover Drift KV: The Ultimate Type-Safe ORM for Deno KV
Experience a powerful ORM with real-time subscriptions, job queues, and seamless compatibility across Deno KV, Node.js, Bun.js, and Edge environments.