feat: setup the attachment to the passenger api

This commit is contained in:
Nathnael
2026-07-18 09:44:14 +00:00
parent 4f043ea4bf
commit bdcd5e957e
12 changed files with 781 additions and 116 deletions

View File

@@ -0,0 +1,52 @@
import { BadRequestException } from '@nestjs/common';
/**
* Keyset cursor for paging a thread backwards from newest.
*
* The sort key is the pair `(createdAt, id)`, not `createdAt` alone: two
* messages can share a millisecond, and a cursor on a non-unique key either
* re-serves or skips the tied rows depending which side of the boundary they
* land on. The id breaks ties with a stable total order.
*
* Deliberately a twin of the freight API's `message-cursor.ts`, not a shared
* import: the two APIs share no runtime package, and @edr/types is Nest-free by
* design (this throws Nest exceptions). The wire format matches so a client can
* treat both chats identically — keep them in step if either changes.
*/
export interface MessageCursor {
createdAt: Date;
id: string;
}
export function encodeMessageCursor(cursor: MessageCursor): string {
return Buffer.from(`${cursor.createdAt.toISOString()}|${cursor.id}`, 'utf8').toString(
'base64url',
);
}
/**
* Parse a client-supplied cursor. Rejects anything malformed rather than
* silently falling back to "first page" — a corrupted cursor that degrades to
* page 1 makes an infinite scroll loop forever over the same rows.
*/
export function decodeMessageCursor(raw: string): MessageCursor {
let decoded: string;
try {
decoded = Buffer.from(raw, 'base64url').toString('utf8');
} catch {
throw new BadRequestException('Malformed pagination cursor.');
}
const separator = decoded.lastIndexOf('|');
if (separator === -1) {
throw new BadRequestException('Malformed pagination cursor.');
}
const createdAt = new Date(decoded.slice(0, separator));
const id = decoded.slice(separator + 1);
if (Number.isNaN(createdAt.getTime()) || !id) {
throw new BadRequestException('Malformed pagination cursor.');
}
return { createdAt, id };
}