UNPKG

@dudousxd/nestjs-telescope

Version:

Laravel Telescope-style observability console for NestJS — core: watchers, recorder, correlation, SQLite store, headless API.

87 lines 3.81 kB
/** * The wire contract for a `table` panel's sort/filter state, and the helper a * provider uses to read it back. * * Sorting and filtering a dashboard table are done **server-side**: the UI never * holds more than the page it is showing, so sorting in the browser would sort * 50 rows out of 50,000 and quietly present the result as "the top of the list". * The state therefore travels to the provider the same way `page`/`limit` * already do — merged into the panel's `data.query` and serialized as query * params on `GET /telescope/api/ext/<ext>/data/<provider>`. * * Everything here is **additive**: a provider that never reads these params * behaves exactly as it did before they existed, and a panel whose columns * declare no `sortable`/`filterable` flag never sends them. * * The wire shape, flat because the query object is serialized through * `URLSearchParams` (a nested object would arrive as the string * `"[object Object]"`): * * ```text * ?page=2&limit=50&sort=duration&dir=desc&filter.status=failed * ``` * * Note that params arrive as **strings** — the host controller passes * `@Query()` through verbatim — which is exactly the trap {@link readTableQuery} * exists to close: `query.page > 1` is `false` for the string `'2'`, silently, * with no type error to catch it. */ /** Query-param key naming the column the table is sorted by. */ export declare const TABLE_SORT_PARAM = "sort"; /** Query-param key carrying the sort direction (`'asc'` / `'desc'`). */ export declare const TABLE_SORT_DIR_PARAM = "dir"; /** * Prefix that namespaces a per-column filter — `filter.status=failed` filters * the column whose `key` is `status`. * * Prefixed rather than flat so a filterable column can never collide with a * param the panel itself declared in `data.query` (a panel with a static * `{ status: 'running' }` scope AND a filterable `status` column is an ordinary * combination, and one silently overwriting the other would be a bug nobody * could see from the outside). */ export declare const TABLE_FILTER_PREFIX = "filter."; /** Which column a table is sorted by, and which way. */ export interface TableSort { /** The `Column.key` of the sorted column. */ key: string; dir: 'asc' | 'desc'; } /** A table panel's paging + sort + filter request, normalized off the raw query. */ export interface TableQuery { /** 1-based page, present only for a `paged: true` panel. */ page?: number; /** Requested page size, present only for a `paged: true` panel. */ limit?: number; /** Absent when the table is unsorted (the provider's own default order wins). */ sort?: TableSort; /** Per-column filter text, keyed by `Column.key`. Empty when nothing is filtered. */ filters: Record<string, string>; } /** * Normalizes the sort/filter/paging params out of a provider's raw `query`. * * Written as a guard-per-field rather than a cast: `query` is genuinely * untrusted — it is whatever was in the URL — and every field has a safe absent * behaviour, so a hand-typed `?sort=` or `?page=banana` degrades to "unsorted" / * "first page" instead of reaching a SQL builder as `NaN`. * * @example * ```ts * const provider: DataProvider = { * name: 'durable.runs', * async resolve(query) { * const { page = 1, limit = 50, sort, filters } = readTableQuery(query); * const rows = await store.findRuns({ * offset: (page - 1) * limit, * limit, * orderBy: sort ? { [sort.key]: sort.dir } : { startedAt: 'desc' }, * where: filters, * }); * return { rows: rows.items, total: rows.total, page, limit }; * }, * }; * ``` */ export declare function readTableQuery(query: Record<string, unknown> | undefined): TableQuery; //# sourceMappingURL=table-query.d.ts.map