import type { Notification, findManyNotifications, } from "~/classes/functions/notification"; import type { Status, findManyNotes } from "~/classes/functions/status"; import type { UserType, findManyUsers } from "~/classes/functions/user"; import type { db } from "~/drizzle/db"; import { config } from "~/packages/config-manager/index"; export async function fetchTimeline( model: | typeof findManyNotes | typeof findManyUsers | typeof findManyNotifications, args: | Parameters[0] | Parameters[0] | Parameters[0], req: Request, userId?: string, ) { // BEFORE: Before in a top-to-bottom order, so the most recent posts // AFTER: After in a top-to-bottom order, so the oldest posts // @ts-expect-error This is a hack to get around the fact that Prisma doesn't have a common base type for all models const objects = (await model(args, userId)) as T[]; // Constuct HTTP Link header (next and prev) only if there are more statuses const linkHeader: string[] = []; const urlWithoutQuery = new URL( new URL(req.url).pathname, config.http.base_url, ).toString(); if (objects.length > 0) { // Check if there are statuses before the first one // @ts-expect-error This is a hack to get around the fact that Prisma doesn't have a common base type for all models const objectsBefore = await model({ ...args, // @ts-expect-error this hack breaks typing :( where: (object, { gt }) => gt(object.id, objects[0].id), limit: 1, }); if (objectsBefore.length > 0) { // Add prev link linkHeader.push( `<${urlWithoutQuery}?limit=${args?.limit ?? 20}&min_id=${ objects[0].id }>; rel="prev"`, ); } if (objects.length >= (Number(args?.limit) ?? 20)) { // Check if there are statuses after the last one // @ts-expect-error hack again const objectsAfter = await model({ ...args, // @ts-expect-error this hack breaks typing :( where: (object, { lt }) => lt(object.id, objects.at(-1).id), limit: 1, }); if (objectsAfter.length > 0) { // Add next link linkHeader.push( `<${urlWithoutQuery}?limit=${args?.limit ?? 20}&max_id=${ objects.at(-1)?.id }>; rel="next"`, ); } } } return { link: linkHeader.join(", "), objects, }; }