/** * Shared feedback-record filtering and pagination — extracted from * `adapter-memory` and `adapter-localstorage` which previously kept two * near-identical copies of the same logic. Any adapter that holds an * in-memory snapshot of feedbacks can use it. * * A record matches when it passes every active filter (see * {@link matchesFeedbackQuery}): * - projectName (always required) * - type * - status / statuses (`statuses` bucket wins when both are set) * - url * - urlPattern * - search (lowercase substring match on `message`) * * Pagination goes through `clampPagination`: `limit` capped at 100, `page` * 1-based, both clamped up to 1 rather than indexing backwards from the end * of the match set. Query adapters reuse the same helper so every store * paginates identically. */ import type { FeedbackQuery, FeedbackRecord } from "./types.js"; /** Default page size when the caller omits `query.limit`. */ export declare const DEFAULT_PAGE_LIMIT = 50; /** Maximum allowed page size — defends against memory blow-ups on hostile callers. */ export declare const MAX_PAGE_LIMIT = 100; export interface FilterResult { feedbacks: FeedbackRecord[]; total: number; } /** Normalised pagination window — see {@link clampPagination}. */ export interface Pagination { /** 1-based page number, at least 1. */ page: number; /** Page size in `[1, MAX_PAGE_LIMIT]`. */ limit: number; /** Offset of the first row: `(page - 1) * limit`. */ skip: number; } /** * Normalise `page` / `limit` to the store contract: `page` is 1-based and * clamped up to 1, `limit` defaults to 50 and is clamped into `[1, 100]`, * non-finite values fall back to the defaults. `skip` is the derived row * offset for query backends (`OFFSET`, Prisma `skip`). * * Shared by the in-memory pipeline and query adapters (`PrismaStore`) so * every store paginates identically — the HTTP schema clamps the same way, * but direct callers (dashboard store mode, server actions) reach the store * without a schema in front of them. */ export declare function clampPagination(query: Pick): Pagination; /** * Whether a {@link clampPagination} offset lies beyond any row a store can * hold. `clampPagination` bounds `page` from below only, so a direct caller's * huge `page` yields an offset past `Number.MAX_SAFE_INTEGER` — or `Infinity` * — that SQL backends reject (`OFFSET` is a 64-bit integer in PostgreSQL and * SQLite; Prisma's `skip` rejects non-integers and 64-bit overflow). * * Every safe integer fits a signed 64-bit offset and no table holds more rows * than that, so query adapters answer such a page as empty — with the real * `total` — instead of issuing the query: the same result the in-memory * pipeline returns. * * @param skip - The `skip` returned by {@link clampPagination}. * @returns `true` when no row can sit at that offset. */ export declare function isUnreachableOffset(skip: number): boolean; /** * Whether one record passes every filter of `query` — the filter half of * {@link applyFeedbackFilters}, exposed so a client holding a single record * (e.g. the dashboard deciding whether an optimistic edit still belongs in * its list) applies exactly the stores' semantics. Pagination is ignored. */ export declare function matchesFeedbackQuery(record: FeedbackRecord, query: FeedbackQuery): boolean; /** * Apply the standard feedback filter + pagination pipeline against an * in-memory snapshot. Used by `MemoryStore.getFeedbacks` and * `LocalStorageStore.getFeedbacks` so the two never drift. * * @param items All known feedback records (already include `annotations`). * @param query Filter and pagination options. `projectName` is required. */ export declare function applyFeedbackFilters(items: readonly FeedbackRecord[], query: FeedbackQuery): FilterResult;