Skip to content

Commit

Permalink
Fix after when sorting with remmapped keys
Browse files Browse the repository at this point in the history
  • Loading branch information
zoriya committed Jan 9, 2025
1 parent 4b5803a commit ef44640
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 6 deletions.
5 changes: 4 additions & 1 deletion api/src/models/utils/keyset-paginate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export const keysetPaginate = <
};

export const generateAfter = (cursor: any, sort: Sort<any, any>) => {
const ret = [...sort.map((by) => cursor[by.key]), cursor.pk];
const ret = [
...sort.map((by) => cursor[by.remmapedKey ?? by.key]),
cursor.pk,
];
return Buffer.from(JSON.stringify(ret), "utf-8").toString("base64url");
};
3 changes: 2 additions & 1 deletion api/src/models/utils/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type Sort<
Remap extends Partial<Record<T[number], string>>,
> = {
key: Exclude<T[number], keyof Remap> | NonNullable<Remap[keyof Remap]>;
remmapedKey?: keyof Remap;
desc: boolean;
}[];

Expand Down Expand Up @@ -44,7 +45,7 @@ export const Sort = <
return sort.map((x) => {
const desc = x[0] === "-";
const key = (desc ? x.substring(1) : x) as T[number];
if (key in remap) return { key: remap[key]!, desc };
if (key in remap) return { key: remap[key]!, remmapedKey: key, desc };
return { key: key as Exclude<typeof key, keyof Remap>, desc };
});
})
Expand Down
39 changes: 35 additions & 4 deletions api/tests/movies/get-all-movies.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
import { eq } from "drizzle-orm";
import Elysia from "elysia";
import { base } from "~/base";
import { movies } from "~/controllers/movies";
Expand All @@ -18,7 +17,7 @@ const getMovies = async ({
filter?: string;
limit?: number;
after?: string;
sort?: string[];
sort?: string | string[];
langs?: string;
}) => {
const params = new URLSearchParams();
Expand Down Expand Up @@ -98,7 +97,7 @@ describe("Get all movies", () => {
this: "http://localhost/movies?limit=2",
// we can't have the exact after since it contains the pk that changes with every tests.
next: expect.stringContaining(
"http://localhost/movies?limit=2&after=WyJkdW5lIiw0",
"http://localhost/movies?limit=2&after=WyJkdW5lIiw",
),
});
});
Expand All @@ -116,11 +115,43 @@ describe("Get all movies", () => {
expect(body).toMatchObject({
items: [expect.objectContaining({ slug: dune1984.slug })],
this: expect.stringContaining(
"http://localhost/movies?limit=2&after=WyJkdW5lIiw0",
"http://localhost/movies?limit=2&after=WyJkdW5lIiw",
),
next: null,
});
});
it("Limit 2, sort by dates desc, page 2", async () => {
let [resp, body] = await getMovies({
limit: 2,
sort: "-airDate",
langs: "en",
});
expectStatus(resp, body).toBe(200);

// we copy this due to https://github.com/oven-sh/bun/issues/3521
const next = body.next;
expect(body).toMatchObject({
items: [
expect.objectContaining({ slug: bubble.slug, airDate: bubble.airDate }),
expect.objectContaining({ slug: dune.slug, airDate: dune.airDate }),
],
this: "http://localhost/movies?limit=2&sort=-airDate",
next: expect.stringContaining(
"http://localhost/movies?limit=2&sort=-airDate&after=WyIyMDIxLTEwLTIyIiw",
),
});

resp = await app.handle(new Request(next));
body = await resp.json();

expectStatus(resp, body).toBe(200);
expect(body).toMatchObject({
items: [expect.objectContaining({ slug: dune1984.slug })],
this: next,
next: null,
});
});
// TODO: sort with an item that has null in it. We want it to always be last (in both asc & desc).
});

beforeAll(async () => {
Expand Down

0 comments on commit ef44640

Please sign in to comment.