aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/server/repositories
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/repositories')
-rw-r--r--src/server/repositories/deck.ts95
-rw-r--r--src/server/repositories/index.ts1
-rw-r--r--src/server/repositories/types.ts33
3 files changed, 129 insertions, 0 deletions
diff --git a/src/server/repositories/deck.ts b/src/server/repositories/deck.ts
new file mode 100644
index 0000000..77985a7
--- /dev/null
+++ b/src/server/repositories/deck.ts
@@ -0,0 +1,95 @@
+import { and, eq, isNull, sql } from "drizzle-orm";
+import { db } from "../db/index.js";
+import { decks } from "../db/schema.js";
+import type { Deck, DeckRepository } from "./types.js";
+
+export const deckRepository: DeckRepository = {
+ async findByUserId(userId: string): Promise<Deck[]> {
+ const result = await db
+ .select()
+ .from(decks)
+ .where(and(eq(decks.userId, userId), isNull(decks.deletedAt)));
+ return result;
+ },
+
+ async findById(id: string, userId: string): Promise<Deck | undefined> {
+ const result = await db
+ .select()
+ .from(decks)
+ .where(
+ and(
+ eq(decks.id, id),
+ eq(decks.userId, userId),
+ isNull(decks.deletedAt),
+ ),
+ );
+ return result[0];
+ },
+
+ async create(data: {
+ userId: string;
+ name: string;
+ description?: string | null;
+ newCardsPerDay?: number;
+ }): Promise<Deck> {
+ const [deck] = await db
+ .insert(decks)
+ .values({
+ userId: data.userId,
+ name: data.name,
+ description: data.description ?? null,
+ newCardsPerDay: data.newCardsPerDay ?? 20,
+ })
+ .returning();
+ if (!deck) {
+ throw new Error("Failed to create deck");
+ }
+ return deck;
+ },
+
+ async update(
+ id: string,
+ userId: string,
+ data: {
+ name?: string;
+ description?: string | null;
+ newCardsPerDay?: number;
+ },
+ ): Promise<Deck | undefined> {
+ const result = await db
+ .update(decks)
+ .set({
+ ...data,
+ updatedAt: new Date(),
+ syncVersion: sql`${decks.syncVersion} + 1`,
+ })
+ .where(
+ and(
+ eq(decks.id, id),
+ eq(decks.userId, userId),
+ isNull(decks.deletedAt),
+ ),
+ )
+ .returning();
+ return result[0];
+ },
+
+ async softDelete(id: string, userId: string): Promise<boolean> {
+ const result = await db
+ .update(decks)
+ .set({
+ deletedAt: new Date(),
+ updatedAt: new Date(),
+ syncVersion: sql`${decks.syncVersion} + 1`,
+ })
+ .where(
+ and(
+ eq(decks.id, id),
+ eq(decks.userId, userId),
+ isNull(decks.deletedAt),
+ ),
+ )
+ .returning({ id: decks.id });
+ return result.length > 0;
+ },
+};
diff --git a/src/server/repositories/index.ts b/src/server/repositories/index.ts
index 04b1f35..9a703ab 100644
--- a/src/server/repositories/index.ts
+++ b/src/server/repositories/index.ts
@@ -1,3 +1,4 @@
+export { deckRepository } from "./deck.js";
export { refreshTokenRepository } from "./refresh-token.js";
export * from "./types.js";
export { userRepository } from "./user.js";
diff --git a/src/server/repositories/types.ts b/src/server/repositories/types.ts
index 1ab4bdc..740fa29 100644
--- a/src/server/repositories/types.ts
+++ b/src/server/repositories/types.ts
@@ -44,3 +44,36 @@ export interface RefreshTokenRepository {
}): Promise<void>;
deleteById(id: string): Promise<void>;
}
+
+export interface Deck {
+ id: string;
+ userId: string;
+ name: string;
+ description: string | null;
+ newCardsPerDay: number;
+ createdAt: Date;
+ updatedAt: Date;
+ deletedAt: Date | null;
+ syncVersion: number;
+}
+
+export interface DeckRepository {
+ findByUserId(userId: string): Promise<Deck[]>;
+ findById(id: string, userId: string): Promise<Deck | undefined>;
+ create(data: {
+ userId: string;
+ name: string;
+ description?: string | null;
+ newCardsPerDay?: number;
+ }): Promise<Deck>;
+ update(
+ id: string,
+ userId: string,
+ data: {
+ name?: string;
+ description?: string | null;
+ newCardsPerDay?: number;
+ },
+ ): Promise<Deck | undefined>;
+ softDelete(id: string, userId: string): Promise<boolean>;
+}