Skip to content

Commit 37c2d5c

Browse files
committed
refactor: drop db.query
We need typesafe queries, so we can't use sql templates. However, I want to stay close to raw sql as possible for readability. (Also LLMs are better at raw sql than typesafe query builders.) This switches us to db.select().from().where() style queries everywhere.
1 parent 9f83a06 commit 37c2d5c

5 files changed

Lines changed: 55 additions & 67 deletions

File tree

src/lib/remote/notes.remote.ts

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@ import { getEncryptedSnapshot } from "$lib/loro.ts";
1717
export const getNotes = query(async (): Promise<NoteOrFolder[]> => {
1818
const { user } = requireLogin();
1919

20-
const userNotes = await db.query.notes.findMany({
21-
where: {
22-
ownerId: user.id,
23-
},
24-
});
20+
const userNotes = await db
21+
.select()
22+
.from(notes)
23+
.where(eq(notes.ownerId, user.id));
2524

2625
return userNotes.map(
2726
(n) =>
@@ -66,11 +65,7 @@ export const createNote = command(
6665
updatedAt: new Date(),
6766
} satisfies typeof notes.$inferInsert);
6867

69-
const note = await db.query.notes.findFirst({
70-
where: {
71-
id: id,
72-
},
73-
});
68+
const [note] = await db.select().from(notes).where(eq(notes.id, id));
7469

7570
if (!note) throw new Error("Failed to find newly created note!");
7671

@@ -90,11 +85,7 @@ export const deleteNote = command(
9085

9186
try {
9287
// Verify ownership
93-
const note = await db.query.notes.findFirst({
94-
where: {
95-
id: noteId,
96-
},
97-
});
88+
const [note] = await db.select().from(notes).where(eq(notes.id, noteId));
9889

9990
if (!note || note.ownerId !== user.id) error(404, "Not found");
10091

@@ -118,11 +109,10 @@ export const updateNote = command(
118109

119110
try {
120111
// Verify ownership
121-
const existingNote = await db.query.notes.findFirst({
122-
where: {
123-
id: noteId,
124-
},
125-
});
112+
const [existingNote] = await db
113+
.select()
114+
.from(notes)
115+
.where(eq(notes.id, noteId));
126116

127117
if (!existingNote || existingNote.ownerId !== user.id) {
128118
error(404, "Not found");
@@ -139,11 +129,10 @@ export const updateNote = command(
139129
})
140130
.where(eq(notes.id, noteId));
141131

142-
const updated = await db.query.notes.findFirst({
143-
where: {
144-
id: noteId,
145-
},
146-
});
132+
const [updated] = await db
133+
.select()
134+
.from(notes)
135+
.where(eq(notes.id, noteId));
147136

148137
if (!updated) throw new Error("Failed to find newly created note!");
149138

src/lib/remote/sync.remote.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { command, getRequestEvent } from "$app/server";
22
import { db } from "$lib/server/db/index.ts";
3+
import * as table from "$lib/server/db/schema.ts";
34
import { broadcast } from "$lib/server/real-time.ts";
45
import { error } from "@sveltejs/kit";
6+
import { eq } from "drizzle-orm";
57
import { Schema } from "effect";
68
import { syncSchema, syncSchemaJson } from "./notes.schemas.ts";
79

@@ -13,11 +15,11 @@ export const sync = command(syncSchema, async ({ noteId, updates }) => {
1315

1416
try {
1517
// Verify access
16-
const note = await db.query.notes.findFirst({
17-
where: {
18-
id: noteId,
19-
},
20-
});
18+
const note = await db
19+
.select()
20+
.from(table.notes)
21+
.where(eq(table.notes.id, noteId))
22+
.get();
2123

2224
if (!note || note.ownerId !== user.id) error(404, "Not found");
2325

src/routes/+layout.server.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { User } from "$lib/schema.ts";
22
import { db } from "$lib/server/db";
3+
import * as table from "$lib/server/db/schema.ts";
4+
import { eq } from "drizzle-orm";
35

46
export interface Data {
57
user: User | undefined;
@@ -11,22 +13,15 @@ export const load = async ({ locals }): Promise<Data> => {
1113
if (!localUser) {
1214
return { user: undefined };
1315
}
16+
const [user] = await db
17+
.select({
18+
id: table.users.id,
19+
username: table.users.username,
20+
publicKey: table.users.publicKey,
21+
privateKeyEncrypted: table.users.privateKeyEncrypted,
22+
})
23+
.from(table.users)
24+
.where(eq(table.users.id, localUser.id));
1425

15-
// Get user with private key from database
16-
const user = await db.query.users.findFirst({
17-
where: {
18-
id: localUser.id,
19-
},
20-
});
21-
22-
return {
23-
user: user
24-
? {
25-
id: user.id,
26-
username: user.username,
27-
publicKey: user.publicKey,
28-
privateKeyEncrypted: user.privateKeyEncrypted,
29-
}
30-
: undefined,
31-
};
26+
return { user };
3227
};

src/routes/+page.server.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { db } from "$lib/server/db";
2-
import { notes } from "$lib/server/db/schema";
2+
import * as table from "$lib/server/db/schema";
33
import { and, count, eq } from "drizzle-orm";
44

55
// TODO: Make this a remote function instead.
@@ -28,25 +28,26 @@ export const load = async ({ locals }): Promise<Data> => {
2828
// Get total notes count (excluding folders)
2929
const totalNotesResult = await db
3030
.select({ count: count() })
31-
.from(notes)
32-
.where(and(eq(notes.ownerId, user.id), eq(notes.isFolder, false)));
31+
.from(table.notes)
32+
.where(
33+
and(eq(table.notes.ownerId, user.id), eq(table.notes.isFolder, false)),
34+
);
3335

3436
const totalNotes = totalNotesResult[0]?.count ?? 0;
3537

3638
// Get a random note (excluding folders)
3739
let randomNote = null;
3840
if (totalNotes > 0) {
39-
const userNotes = await db.query.notes.findMany({
40-
where: {
41-
ownerId: user.id,
42-
isFolder: false,
43-
},
44-
columns: {
45-
id: true,
46-
title: true,
47-
updatedAt: true,
48-
},
49-
});
41+
const userNotes = await db
42+
.select({
43+
id: table.notes.id,
44+
title: table.notes.title,
45+
updatedAt: table.notes.updatedAt,
46+
})
47+
.from(table.notes)
48+
.where(
49+
and(eq(table.notes.ownerId, user.id), eq(table.notes.isFolder, false)),
50+
);
5051

5152
if (userNotes.length > 0) {
5253
const randomIndex = Math.floor(Math.random() * userNotes.length);

src/routes/api/sync/[noteId]/+server.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { syncSchemaJson } from "$lib/remote/notes.schemas.ts";
22
import { db } from "$lib/server/db";
3+
import * as table from "$lib/server/db/schema.ts";
34
import { addClient, removeClient } from "$lib/server/real-time";
45
import { json } from "@sveltejs/kit";
6+
import { eq } from "drizzle-orm";
57
import { Schema } from "effect";
68

79
export const GET = async ({ params, locals }) => {
@@ -15,12 +17,11 @@ export const GET = async ({ params, locals }) => {
1517
}
1618

1719
// Verify access
18-
const note = await db.query.notes.findFirst({
19-
where: {
20-
id: noteId,
21-
},
22-
});
23-
20+
const note = await db
21+
.select()
22+
.from(table.notes)
23+
.where(eq(table.notes.id, noteId))
24+
.get();
2425
if (!note || note.ownerId !== locals.user.id) {
2526
// TODO: Add check for shared notes when federation via ATProto is implemented
2627
return json({ error: "Not found or unauthorized" }, { status: 404 });

0 commit comments

Comments
 (0)