diff --git a/controllers/post.ts b/controllers/post.ts index aa40175..b4cdbc8 100644 --- a/controllers/post.ts +++ b/controllers/post.ts @@ -7,8 +7,23 @@ import { v4 as uuid4 } from "uuid"; const PostController = { index: async (req: Request, res: Response) => { - const items = await pool("posts"); - return res.status(200).json(items); + const page = parseInt(req.query.page as string) || 0; + const size = parseInt(req.query.size as string) || 5; + const items = pool("posts") + .offset(page * size) + .limit(size) + .orderBy("date", "desc"); + const total = pool<{ total: number }>("posts") + .count("id", { as: "total" }) + .first(); + return res.status(200).json({ + items: await items, + paginate: { + page, + size, + total: (await total)?.total, + }, + }); }, show: async (req: Request, res: Response) => { const item = await pool("posts").where("id", req.params.id).first(); @@ -76,6 +91,13 @@ const PostController = { slug: z.string().regex(/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/), }), }); + case ValidateMethod.PAGINATE: + return z.object({ + query: z.object({ + page: z.string().optional().transform((x) => parseInt(x || "0")).pipe(z.number().nonnegative()), + size: z.string().optional().transform((x) => parseInt(x || "5")).pipe(z.number().positive()), + }), + }); default: return z.object({}); } diff --git a/middlewares/validate.ts b/middlewares/validate.ts index ad7ff59..4db960d 100644 --- a/middlewares/validate.ts +++ b/middlewares/validate.ts @@ -7,6 +7,7 @@ export enum ValidateMethod { ID, SLUG, LOGIN, + PAGINATE, } const validate = (schema: AnyZodObject) => { diff --git a/routes/post.ts b/routes/post.ts index 52ce314..f4ea8e1 100644 --- a/routes/post.ts +++ b/routes/post.ts @@ -7,6 +7,7 @@ const router = Router(); router.get( "/", + validate(PostController.validate(ValidateMethod.PAGINATE)), PostController.index ); router.get( diff --git a/tests/post.test.ts b/tests/post.test.ts index b8c2233..f0a238c 100644 --- a/tests/post.test.ts +++ b/tests/post.test.ts @@ -25,14 +25,14 @@ describe("Post", () => { }); test("GET /post/:id 200", async () => { - const result = await request(app).get("/post"); - return request(app).get(`/post/${result.body[0].id}`).expect(200); + const post = await pool("posts").first(); + return request(app).get(`/post/${post!.id}`).expect(200); }); test("GET /post/slug/:slug 200", async () => { - const result = await request(app).get("/post"); + const post = await pool("posts").first(); return request(app) - .get(`/post/slug/${result.body[0].slug}`) + .get(`/post/slug/${post!.slug}`) .expect(200); }); @@ -72,9 +72,9 @@ describe("Post", () => { }); test("DELETE /post 200", async () => { - const result = await request(app).get("/post"); + const post = await pool("posts").first(); return request(app) - .delete(`/post/${result.body[0].id}`) + .delete(`/post/${post!.id}`) .set({ Authorization: `Bearer ${token}` }) .expect(200); });