feat(01-02): create EntryRepository with typed CRUD operations
- Implement EntryRepository interface with create, getById, getAll, update, delete, count - SQLiteEntryRepository class using Drizzle ORM - Automatic ID generation with nanoid - Automatic timestamp management (createdAt, updatedAt) - Pagination support via limit/offset - Singleton pattern for consistent access
This commit is contained in:
68
src/lib/server/db/repository.ts
Normal file
68
src/lib/server/db/repository.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { eq, desc } from 'drizzle-orm';
|
||||||
|
import { db } from './index';
|
||||||
|
import { entries, type Entry, type NewEntry } from './schema';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
|
|
||||||
|
export interface EntryRepository {
|
||||||
|
create(entry: Omit<NewEntry, 'id' | 'createdAt' | 'updatedAt'>): Entry;
|
||||||
|
getById(id: string): Entry | undefined;
|
||||||
|
getAll(options?: { limit?: number; offset?: number }): Entry[];
|
||||||
|
update(id: string, updates: Partial<Omit<Entry, 'id' | 'createdAt'>>): Entry | undefined;
|
||||||
|
delete(id: string): boolean;
|
||||||
|
count(): number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SQLiteEntryRepository implements EntryRepository {
|
||||||
|
create(entry: Omit<NewEntry, 'id' | 'createdAt' | 'updatedAt'>): Entry {
|
||||||
|
const now = new Date().toISOString();
|
||||||
|
const newEntry: NewEntry = {
|
||||||
|
...entry,
|
||||||
|
id: nanoid(),
|
||||||
|
createdAt: now,
|
||||||
|
updatedAt: now
|
||||||
|
};
|
||||||
|
|
||||||
|
db.insert(entries).values(newEntry).run();
|
||||||
|
return this.getById(newEntry.id)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
getById(id: string): Entry | undefined {
|
||||||
|
return db.select().from(entries).where(eq(entries.id, id)).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll(options: { limit?: number; offset?: number } = {}): Entry[] {
|
||||||
|
const { limit = 100, offset = 0 } = options;
|
||||||
|
return db.select().from(entries).orderBy(desc(entries.createdAt)).limit(limit).offset(offset).all();
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: string, updates: Partial<Omit<Entry, 'id' | 'createdAt'>>): Entry | undefined {
|
||||||
|
const existing = this.getById(id);
|
||||||
|
if (!existing) return undefined;
|
||||||
|
|
||||||
|
db.update(entries)
|
||||||
|
.set({
|
||||||
|
...updates,
|
||||||
|
updatedAt: new Date().toISOString()
|
||||||
|
})
|
||||||
|
.where(eq(entries.id, id))
|
||||||
|
.run();
|
||||||
|
|
||||||
|
return this.getById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id: string): boolean {
|
||||||
|
const existing = this.getById(id);
|
||||||
|
if (!existing) return false;
|
||||||
|
|
||||||
|
db.delete(entries).where(eq(entries.id, id)).run();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
count(): number {
|
||||||
|
const result = db.select().from(entries).all();
|
||||||
|
return result.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Singleton instance
|
||||||
|
export const entryRepository: EntryRepository = new SQLiteEntryRepository();
|
||||||
Reference in New Issue
Block a user