馃 distributed transcription service thistle.dunkirk.sh
1/** 2 * Cursor encoding/decoding for pagination 3 * Cursors are base64url-encoded strings for opacity and URL safety 4 */ 5 6/** 7 * Encode a cursor from components 8 */ 9export function encodeCursor(parts: string[]): string { 10 const raw = parts.join("|"); 11 // Use base64url encoding (no padding, URL-safe characters) 12 return Buffer.from(raw).toString("base64url"); 13} 14 15/** 16 * Decode a cursor into components 17 */ 18export function decodeCursor(cursor: string): string[] { 19 try { 20 const raw = Buffer.from(cursor, "base64url").toString("utf-8"); 21 return raw.split("|"); 22 } catch { 23 throw new Error("Invalid cursor format"); 24 } 25} 26 27/** 28 * Encode a transcription/user cursor (timestamp-id) 29 */ 30export function encodeSimpleCursor(timestamp: number, id: string): string { 31 return encodeCursor([timestamp.toString(), id]); 32} 33 34/** 35 * Decode a transcription/user cursor (timestamp-id) 36 */ 37export function decodeSimpleCursor(cursor: string): { 38 timestamp: number; 39 id: string; 40} { 41 const parts = decodeCursor(cursor); 42 if (parts.length !== 2) { 43 throw new Error("Invalid cursor format"); 44 } 45 46 const timestamp = Number.parseInt(parts[0] || "", 10); 47 const id = parts[1] || ""; 48 49 if (Number.isNaN(timestamp) || !id) { 50 throw new Error("Invalid cursor format"); 51 } 52 53 return { timestamp, id }; 54} 55 56/** 57 * Encode a class cursor (year-semester-coursecode-id) 58 */ 59export function encodeClassCursor( 60 year: number, 61 semester: string, 62 courseCode: string, 63 id: string, 64): string { 65 return encodeCursor([year.toString(), semester, courseCode, id]); 66} 67 68/** 69 * Decode a class cursor (year-semester-coursecode-id) 70 */ 71export function decodeClassCursor(cursor: string): { 72 year: number; 73 semester: string; 74 courseCode: string; 75 id: string; 76} { 77 const parts = decodeCursor(cursor); 78 if (parts.length !== 4) { 79 throw new Error("Invalid cursor format"); 80 } 81 82 const year = Number.parseInt(parts[0] || "", 10); 83 const semester = parts[1] || ""; 84 const courseCode = parts[2] || ""; 85 const id = parts[3] || ""; 86 87 if (Number.isNaN(year) || !semester || !courseCode || !id) { 88 throw new Error("Invalid cursor format"); 89 } 90 91 return { year, semester, courseCode, id }; 92}