Skip to content

Commit 730c909

Browse files
committed
added offset pagination
1 parent 7ab3079 commit 730c909

File tree

3 files changed

+133
-54
lines changed

3 files changed

+133
-54
lines changed

apps/server/src/routers/posts.ts

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,67 @@ import { authenticateUser } from "./auth";
1313
export async function postRoutes(fastify: FastifyInstance) {
1414

1515
fastify.get(
16-
"/threads/:id/posts",
17-
{ preHandler: authenticateUser },
18-
async (request, reply) => {
19-
const userId = request.userId;
20-
if (!userId) {
21-
return reply.status(401).send({ error: "Unauthorized", success: false });
22-
}
23-
const user = await DrizzleClient.query.users.findFirst({
24-
where: (u, { eq }) => eq(u.id, userId),
25-
});
26-
if (!user) {
27-
return reply.status(404).send({ error: "User not found", success: false });
28-
}
29-
const params = threadIdParamsSchema.safeParse(request.params);
30-
if (!params.success) {
31-
return reply.status(400).send({ success: false, error: "Invalid thread ID" });
32-
}
33-
const threadId = params.data.id;
34-
try {
35-
const threadPosts = await DrizzleClient.query.posts.findMany({
36-
where: (p, { eq }) => eq(p.threadId, threadId),
37-
orderBy: (p, { asc }) => [asc(p.createdAt)],
38-
});
39-
return reply.status(200).send({ success: true, posts: threadPosts });
40-
} catch (error) {
41-
fastify.log.error("Error fetching posts for thread:", error);
42-
return reply.status(500).send({ success: false, error: "Failed to fetch posts" });
43-
}
44-
}
45-
);
16+
"/threads/:id/posts",
17+
{
18+
preHandler: authenticateUser,
19+
schema: {
20+
querystring: {
21+
type: "object",
22+
properties: {
23+
page: { type: "integer", minimum: 1, default: 1 },
24+
limit: { type: "integer", minimum: 1, maximum: 100, default: 20 },
25+
},
26+
},
27+
},
28+
},
29+
async (request, reply) => {
30+
const userId = request.userId;
31+
if (!userId) {
32+
return reply
33+
.status(401)
34+
.send({ error: "Unauthorized", success: false });
35+
}
36+
const user = await DrizzleClient.query.users.findFirst({
37+
where: (u, { eq }) => eq(u.id, userId),
38+
});
39+
if (!user) {
40+
return reply
41+
.status(404)
42+
.send({ error: "User not found", success: false });
43+
}
44+
const params = threadIdParamsSchema.safeParse(request.params);
45+
if (!params.success) {
46+
return reply
47+
.status(400)
48+
.send({ success: false, error: "Invalid thread ID" });
49+
}
50+
const threadId = params.data.id;
51+
const { page = 1, limit = 20 } = request.query as { page?: number; limit?: number };
52+
const offset = (page - 1) * limit;
53+
try {
54+
const threadPosts = await DrizzleClient.query.posts.findMany({
55+
where: (p, { eq }) => eq(p.threadId, threadId),
56+
orderBy: (p, { asc }) => [asc(p.createdAt)],
57+
limit: limit,
58+
offset: offset,
59+
});
60+
return reply.status(200).send({
61+
success: true,
62+
posts: threadPosts,
63+
pagination: {
64+
page,
65+
limit,
66+
count: threadPosts.length,
67+
},
68+
});
69+
} catch (error) {
70+
fastify.log.error("Error fetching posts for thread:", error);
71+
return reply
72+
.status(500)
73+
.send({ success: false, error: "Failed to fetch posts" });
74+
}
75+
}
76+
);
4677

4778
fastify.get(
4879
"/posts/:id",

apps/server/src/routers/threads.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,18 @@ import { topicIdParamsSchema } from "@/dto/topics.dto";
1212

1313
export async function threadRoutes(fastify: FastifyInstance) {
1414
fastify.get(
15-
"/topics/:id/threads",
15+
"/topics/:id/threads",
1616
{
1717
preHandler: authenticateUser,
18+
schema: {
19+
querystring: {
20+
type: "object",
21+
properties: {
22+
page: { type: "integer", minimum: 1, default: 1 },
23+
limit: { type: "integer", minimum: 1, maximum: 50, default: 10 },
24+
},
25+
},
26+
},
1827
},
1928
async (request, reply) => {
2029
const userId = request.userId;
@@ -38,14 +47,25 @@ export async function threadRoutes(fastify: FastifyInstance) {
3847
.send({ success: false, error: "Invalid topic ID" });
3948
}
4049
const topicId = params.data.id;
50+
const { page = 1, limit = 10 } =
51+
(request.query as { page?: number; limit?: number }) || {};
52+
const offset = (page - 1) * limit;
4153
try {
4254
const relatedThreads = await DrizzleClient.query.threads.findMany({
4355
where: (t, { eq }) => eq(t.topicId, topicId),
4456
orderBy: (t, { desc }) => [desc(t.createdAt)],
57+
limit: limit,
58+
offset: offset,
59+
});
60+
return reply.status(200).send({
61+
success: true,
62+
threads: relatedThreads,
63+
pagination: {
64+
page,
65+
limit,
66+
count: relatedThreads.length,
67+
},
4568
});
46-
return reply
47-
.status(200)
48-
.send({ success: true, threads: relatedThreads });
4969
} catch (error) {
5070
fastify.log.error("Error fetching threads for topic:", error);
5171
return reply.status(500).send({
@@ -56,6 +76,8 @@ export async function threadRoutes(fastify: FastifyInstance) {
5676
}
5777
);
5878

79+
80+
5981
fastify.get(
6082
"/threads/:id",
6183
{ preHandler: authenticateUser },

apps/server/src/routers/topics.ts

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { eq } from "drizzle-orm";
2-
import type { FastifyInstance } from "fastify";
2+
import type { FastifyInstance, FastifyRequest } from "fastify";
33
import { DrizzleClient } from "@/db/index";
44
import { topics as topicsTable } from "@/db/schema/topic.schema";
55
import {
@@ -12,25 +12,51 @@ import { authenticateUser } from "./auth";
1212
export async function topicRoutes(fastify: FastifyInstance) {
1313

1414
fastify.get(
15-
"/topics",
16-
{ preHandler: authenticateUser },
17-
async (request, reply) => {
18-
const userId = request.userId;
19-
if (!userId)
20-
return reply
21-
.status(401)
22-
.send({ success: false, error: "Unauthorized" });
23-
try {
24-
const allTopics = await DrizzleClient.query.topics.findMany();
25-
return reply.status(200).send({ success: true, topics: allTopics });
26-
} catch (error) {
27-
fastify.log.error({ err: error }, "Failed to fetch topics");
28-
return reply
29-
.status(500)
30-
.send({ success: false, error: "Failed to fetch topics" });
31-
}
32-
},
33-
);
15+
"/topics",
16+
{
17+
preHandler: authenticateUser,
18+
schema: {
19+
querystring: {
20+
type: "object",
21+
properties: {
22+
page: { type: "integer", minimum: 1, default: 1 },
23+
limit: { type: "integer", minimum: 1, maximum: 100, default: 10 },
24+
},
25+
},
26+
},
27+
},
28+
async (request: FastifyRequest<{ Querystring: { page?: number; limit?: number } }>, reply) => {
29+
const userId = request.userId;
30+
if (!userId)
31+
return reply
32+
.status(401)
33+
.send({ success: false, error: "Unauthorized" });
34+
const { page = 1, limit = 10 } = request.query;
35+
const offset = (page - 1) * limit;
36+
try {
37+
const topics = await DrizzleClient.query.topics.findMany({
38+
limit: limit,
39+
offset: offset,
40+
orderBy: (table, { desc }) => [desc(table.createdAt)],
41+
});
42+
43+
return reply.status(200).send({
44+
success: true,
45+
data: topics,
46+
pagination: {
47+
page,
48+
limit,
49+
count: topics.length,
50+
},
51+
});
52+
} catch (error) {
53+
fastify.log.error({ err: error }, "Failed to fetch topics");
54+
return reply
55+
.status(500)
56+
.send({ success: false, error: "Failed to fetch topics" });
57+
}
58+
}
59+
);
3460

3561
fastify.post(
3662
"/topics",

0 commit comments

Comments
 (0)