Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 61x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | // Data Access Layer for Homeowner accounts (ho_users)
import { eq, sql } from "drizzle-orm";
import type { DrizzleD1Database } from "drizzle-orm/d1";
import * as schema from "../db/schema";
export class HoUsersDal {
constructor(private db: DrizzleD1Database<typeof schema>) {}
async findById(id: string) {
const rows = await this.db
.select()
.from(schema.hoUsers)
.where(eq(schema.hoUsers.id, id))
.limit(1);
return rows[0];
}
// Case-insensitive lookup — migration 0005 swapped the unique index from
// (email) to (LOWER(email)) because Better Auth's adapter does
// case-sensitive binary equality (issue #636). Matching that here means a
// row written as "Foo@gmail.com" is still found when someone types
// "foo@gmail.com" during a change-email uniqueness check.
async findByEmail(email: string) {
const rows = await this.db
.select()
.from(schema.hoUsers)
.where(eq(sql`lower(${schema.hoUsers.email})`, email.toLowerCase()))
.limit(1);
return rows[0];
}
async update(
id: string,
data: Partial<
Pick<
typeof schema.hoUsers.$inferSelect,
"email" | "emailVerified" | "image"
>
>,
) {
const rows = await this.db
.update(schema.hoUsers)
.set({ ...data, updatedAt: new Date() })
.where(eq(schema.hoUsers.id, id))
.returning();
return rows[0];
}
// Keep the auth-user display name in step with the homeowner profile.
// Session-derived UI (header avatar initials, "Welcome back, {name}") reads
// ho_users.name, so a profile-only update left those showing the signup
// placeholder ("New Homeowner") forever.
async updateName(id: string, name: string) {
const rows = await this.db
.update(schema.hoUsers)
.set({ name, updatedAt: new Date() })
.where(eq(schema.hoUsers.id, id))
.returning();
return rows[0];
}
// Hard-delete a homeowner account. FK ON DELETE CASCADE on the homeowner
// child tables (favorites, mood boards, profile, etc.) cleans up dependents.
async deleteById(id: string): Promise<boolean> {
const result = await this.db
.delete(schema.hoUsers)
.where(eq(schema.hoUsers.id, id))
.returning();
return result.length > 0;
}
}
|