From ed0e62d4c9c37aaba30e2c6f65c182ccef6c8f39 Mon Sep 17 00:00:00 2001 From: Walter Jenkins Date: Sun, 28 Jan 2024 17:06:21 -0600 Subject: [PATCH] updated with drizzle --- app/models/note.server.ts | 57 +++++++++---------------- app/models/user.server.ts | 74 ++++++++++++++++----------------- app/session.server.ts | 5 +-- app/utils.ts | 12 +++--- drizzle/schema.ts | 4 +- app/seed2.ts => drizzle/seed.ts | 27 ------------ package.json | 2 +- 7 files changed, 68 insertions(+), 113 deletions(-) rename app/seed2.ts => drizzle/seed.ts (61%) diff --git a/app/models/note.server.ts b/app/models/note.server.ts index f385491..675bde1 100644 --- a/app/models/note.server.ts +++ b/app/models/note.server.ts @@ -1,52 +1,33 @@ -import type { User, Note } from "@prisma/client"; +import { eq } from "drizzle-orm"; -import { prisma } from "~/db.server"; +import { db } from "drizzle/config"; +import { note } from "drizzle/schema"; +import { dbDate } from "~/utils"; -export function getNote({ - id, - userId, -}: Pick & { - userId: User["id"]; -}) { - return prisma.note.findFirst({ - select: { id: true, body: true, title: true }, - where: { id, userId }, - }); +export async function getNote({ id }: { id: string }) { + const [note] = await db.select().from(note).where(eq(note.id, id)).limit(1); + return note; } -export function getNoteListItems({ userId }: { userId: User["id"] }) { - return prisma.note.findMany({ - where: { userId }, - select: { id: true, title: true }, - orderBy: { updatedAt: "desc" }, - }); +export function getNoteListItems() { + return db + .select({ id: note.id, title: note.title }) + .from(note) + .orderBy(note.createdAt); } export function createNote({ body, title, userId, -}: Pick & { - userId: User["id"]; +}: { + body: string; + title: string; + userId: string; }) { - return prisma.note.create({ - data: { - title, - body, - user: { - connect: { - id: userId, - }, - }, - }, - }); + return db.insert(note).values([{ body, title, userId, updatedAt: dbDate() }]); } -export function deleteNote({ - id, - userId, -}: Pick & { userId: User["id"] }) { - return prisma.note.deleteMany({ - where: { id, userId }, - }); +export function deleteNote({ id }: { id: string }) { + return db.delete(note).where(eq(note.id, id)); } diff --git a/app/models/user.server.ts b/app/models/user.server.ts index 42be9b7..f37cd83 100644 --- a/app/models/user.server.ts +++ b/app/models/user.server.ts @@ -1,63 +1,63 @@ -import type { Password, User } from "@prisma/client"; import bcrypt from "bcryptjs"; +import { eq } from "drizzle-orm"; -import { prisma } from "~/db.server"; +import { db } from "drizzle/config"; +import { password, user } from "drizzle/schema"; -export type { User } from "@prisma/client"; - -export async function getUserById(id: User["id"]) { - return prisma.user.findUnique({ where: { id } }); +export async function getUserById(id: string) { + const [_user] = await db.select().from(user).where(eq(user.id, id)).limit(1); + return _user; } -export async function getUserByEmail(email: User["email"]) { - return prisma.user.findUnique({ where: { email } }); +export async function getUserByEmail(email: string) { + const [_user] = await db.select().from(user).where(eq(user.email, email)); + return _user; } -export async function createUser(email: User["email"], password: string) { - const hashedPassword = await bcrypt.hash(password, 10); +export async function createUser(email: string, _password: string) { + const hashedPassword = await bcrypt.hash(_password, 10); - return prisma.user.create({ - data: { - email, - password: { - create: { - hash: hashedPassword, + return await db.transaction(async (tx) => { + const [createdUser] = await tx + .insert(user) + .values([ + { + email, + updatedAt: new Date().toLocaleDateString(), }, - }, - }, + ]) + .returning({ id: user.id, email: user.email }); + await tx.insert(password).values({ + userId: createdUser.id, + hash: hashedPassword, + }); + return createdUser; }); } -export async function deleteUserByEmail(email: User["email"]) { - return prisma.user.delete({ where: { email } }); +export async function deleteUserByEmail(email: string) { + return await db.delete(user).where(eq(user.email, email)); } -export async function verifyLogin( - email: User["email"], - password: Password["hash"], -) { - const userWithPassword = await prisma.user.findUnique({ - where: { email }, - include: { - password: true, - }, - }); +export async function verifyLogin(email: string, _password: string) { + const [userWithPassword] = await db + .select() + .from(user) + .leftJoin(password, eq(password.userId, user.id)) + .where(eq(user.email, email)); - if (!userWithPassword || !userWithPassword.password) { + if (!userWithPassword || !userWithPassword.Password) { return null; } const isValid = await bcrypt.compare( - password, - userWithPassword.password.hash, + _password, + userWithPassword.Password.hash, ); if (!isValid) { return null; } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { password: _password, ...userWithoutPassword } = userWithPassword; - - return userWithoutPassword; + return userWithPassword.User; } diff --git a/app/session.server.ts b/app/session.server.ts index 10cebe5..2352813 100644 --- a/app/session.server.ts +++ b/app/session.server.ts @@ -1,7 +1,6 @@ import { createCookieSessionStorage, redirect } from "@remix-run/node"; import invariant from "tiny-invariant"; -import type { User } from "~/models/user.server"; import { getUserById } from "~/models/user.server"; invariant(process.env.SESSION_SECRET, "SESSION_SECRET must be set"); @@ -24,9 +23,7 @@ export async function getSession(request: Request) { return sessionStorage.getSession(cookie); } -export async function getUserId( - request: Request, -): Promise { +export async function getUserId(request: Request) { const session = await getSession(request); const userId = session.get(USER_SESSION_KEY); return userId; diff --git a/app/utils.ts b/app/utils.ts index f6da6bd..fc3a1f4 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -1,8 +1,6 @@ import { useMatches } from "@remix-run/react"; import { useMemo } from "react"; -import type { User } from "~/models/user.server"; - const DEFAULT_REDIRECT = "/"; /** @@ -44,7 +42,7 @@ export function useMatchesData( return route?.data as Record; } -function isUser(user: unknown): user is User { +function isUser(user: unknown) { return ( user != null && typeof user === "object" && @@ -53,7 +51,7 @@ function isUser(user: unknown): user is User { ); } -export function useOptionalUser(): User | undefined { +export function useOptionalUser() { const data = useMatchesData("root"); if (!data || !isUser(data.user)) { return undefined; @@ -61,7 +59,7 @@ export function useOptionalUser(): User | undefined { return data.user; } -export function useUser(): User { +export function useUser() { const maybeUser = useOptionalUser(); if (!maybeUser) { throw new Error( @@ -74,3 +72,7 @@ export function useUser(): User { export function validateEmail(email: unknown): email is string { return typeof email === "string" && email.length > 3 && email.includes("@"); } + +export function dbDate() { + return new Date().toLocaleDateString(); +} diff --git a/drizzle/schema.ts b/drizzle/schema.ts index 843c303..a961f8c 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -59,7 +59,9 @@ export const password = sqliteTable( ); export const note = sqliteTable("Note", { - id: text("id").primaryKey().notNull(), + id: text("id") + .primaryKey() + .$defaultFn(() => createId()), title: text("title").notNull(), body: text("body").notNull(), createdAt: numeric("createdAt") diff --git a/app/seed2.ts b/drizzle/seed.ts similarity index 61% rename from app/seed2.ts rename to drizzle/seed.ts index 5196442..acc2d04 100644 --- a/app/seed2.ts +++ b/drizzle/seed.ts @@ -27,33 +27,6 @@ async function seed() { hash: hashedPassword, }); }); - // const user = await prisma.user.create({ - // data: { - // email, - // password: { - // create: { - // hash: hashedPassword, - // }, - // }, - // }, - // }); - // - // await prisma.note.create({ - // data: { - // title: "My first note", - // body: "Hello, world!", - // userId: user.id, - // }, - // }); - // - // await prisma.note.create({ - // data: { - // title: "My second note", - // body: "Hello, world!", - // userId: user.id, - // }, - // }); - // console.log(`Database has been seeded. 🌱`); } diff --git a/package.json b/package.json index 3f0ca57..8293b0a 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "start": "remix-serve ./build/index.js", "start:mocks": "binode --require ./mocks -- @remix-run/serve:remix-serve ./build/index.js", "test": "vitest", - "seed": "tsx ./app/seed2.ts", + "seed": "tsx ./drizzle/seed.ts", "gtfs": "tsx ./app/gtfs/index.ts", "test:e2e:dev": "start-server-and-test dev http://localhost:3000 \"npx cypress open\"", "pretest:e2e:run": "npm run build",