diff --git a/src/db/actions/modules.ts b/src/db/actions/modules.ts new file mode 100644 index 00000000..66d69261 --- /dev/null +++ b/src/db/actions/modules.ts @@ -0,0 +1,79 @@ +import { and, desc, eq } from 'drizzle-orm'; +import { createInsertSchema } from 'drizzle-zod'; +import { db } from '..'; +import { modulesTable } from '../schema'; +import type { z } from 'zod'; + +export const getModuleById = (id: string, userId: string) => + db.query.modulesTable.findFirst({ + where: and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId)), + }); + +export const getModulesByUserId = (userId: string) => + db + .select() + .from(modulesTable) + .where(eq(modulesTable.user_id, userId)) + .orderBy(desc(modulesTable.lastVisited)); + +const insertModuleSchema = createInsertSchema(modulesTable).omit({ + id: true, + createdAt: true, + modifiedAt: true, + lastVisited: true, +}); + +export const createModule = (data: z.infer) => + db.insert(modulesTable).values({ + ...data, + color: data.color ?? 'default', + icon: data.icon ?? 'default', + archived: data.archived ?? false, + credits: data.credits ?? 0, + }); + +export const archiveModule = (id: string, userId: string) => + db + .update(modulesTable) + .set({ archived: true }) + .where(and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId))); + +export const recoverModule = (id: string, userId: string) => + db + .update(modulesTable) + .set({ archived: false }) + .where(and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId))); + +export const updateModule = async ( + id: string, + userId: string, + data: z.infer, +) => { + const existingModule = await getModuleById(id, userId); + + if (!existingModule) { + throw new Error('Module not found'); + } + + return db + .update(modulesTable) + .set({ + ...data, + color: data.color ?? existingModule.color, + icon: data.icon ?? existingModule.icon, + archived: data.archived ?? existingModule.archived, + credits: data.credits ?? existingModule.credits, + }) + .where(and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId))); +}; + +export const deleteModule = (id: string, userId: string) => + db + .delete(modulesTable) + .where(and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId))); + +export const updateLastVisited = (id: string, userId: string) => + db + .update(modulesTable) + .set({ lastVisited: new Date() }) + .where(and(eq(modulesTable.id, id), eq(modulesTable.user_id, userId))); diff --git a/src/db/schema/index.ts b/src/db/schema/index.ts index 889dc30b..a33f9fde 100644 --- a/src/db/schema/index.ts +++ b/src/db/schema/index.ts @@ -1 +1,2 @@ export * from './early-access'; +export * from './modules'; diff --git a/src/db/schema/modules.ts b/src/db/schema/modules.ts new file mode 100644 index 00000000..7f63eaa5 --- /dev/null +++ b/src/db/schema/modules.ts @@ -0,0 +1,23 @@ +import { + boolean, + integer, + pgTable, + text, + timestamp, + uuid, +} from 'drizzle-orm/pg-core'; + +export const modulesTable = pgTable('modules', { + id: uuid('id').primaryKey().unique().defaultRandom().notNull(), + user_id: text('user_id').notNull(), + name: text('name').notNull(), + description: text('description').notNull(), + code: text('code').notNull(), + icon: text('icon').default('default').notNull(), + color: text('color').default('default').notNull(), + archived: boolean('archived').default(false).notNull(), + credits: integer('credits').default(0).notNull(), + createdAt: timestamp('created_at').notNull().defaultNow(), + modifiedAt: timestamp('modified_at').notNull().defaultNow(), + lastVisited: timestamp('last_visited').notNull().defaultNow(), +});