/** Offset pagination for a stable dataset; fetch one extra row to detect the next page. */ export const paginationProperties = { limit: { type: "integer", minimum: 1, maximum: 100, default: 25 }, offset: { type: "integer", minimum: 0, default: 0, description: "Startposition. Für Folgeseiten pagination.nextOffset mit denselben Filtern verwenden." }, } export function limitFromArgs(args: Record, fallback = 25) { const value = args.limit ?? fallback if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1 || value > 100) { throw new Error("limit muss eine ganze Zahl zwischen 1 und 100 sein") } return value } export function offsetFromArgs(args: Record) { const value = args.offset ?? 0 if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) { throw new Error("offset muss eine nicht negative ganze Zahl sein") } return value } export function paginatedResult(rows: T[], args: Record, fallback = 25) { const limit = limitFromArgs(args, fallback) const offset = offsetFromArgs(args) const hasMore = rows.length > limit return { rows: rows.slice(0, limit), pagination: { limit, offset, hasMore, nextOffset: hasMore ? offset + limit : null }, } }