Files
rea/src/domain/analysisView/environmentStatePaging.ts
T
edccb430c4 feat(environment): compare an environment with probe captures of its application (#5699)
* chore: restack environment fidelity onto main

Keep probe comparison, paging, and tied-create behavior on main after #5600. Capture parsing keeps field-path errors and records whether a probe kept request and response bodies.

Co-authored-by: morluto <[email protected]>

* fix(environment): keep served collection order with the fidelity checks

The tied-create collection order lives with the checks that match encoded parents. The write simulation reads field checks from that attribution, and taint uses the same segment match.

Co-authored-by: morluto <[email protected]>

* fix(environment): translate an object's keys only when it is keyed by learned ids

Differ.object mapped every key through the probe's id map, so a field named
like a learned id was compared with another field, and a real rename could
pass as a mapped key. Keys now translate only for an object keyed by
learned ids as learning reads one: a key both sides share needs every key
evidently an id, and otherwise each entry is an entity or each key evidently
an id. Any other object compares field by field.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: morluto <[email protected]>
2026-10-22 21:52:01 +08:00

79 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
iterateUrlQueryParameters,
parseUrlQueryParameterNames,
} from "../recordedTransportUrl.js";
/** Query parameters that page or bound a list without filtering it. */
const PAGING_PARAMETERS = new Set([
"limit",
"offset",
"page",
"per_page",
"perpage",
"page_size",
"pagesize",
"size",
"start",
"_start",
"_end",
]);
/** Whether a query parameter pages or bounds a list rather than filtering it. */
export const isPagingParameter = (name: string): boolean =>
PAGING_PARAMETERS.has(name.toLowerCase());
/** Whether a query only pages its list: no parameters, or paging parameters alone. */
export const pagesOnly = (query: string | undefined): boolean =>
query === undefined ||
[...parseUrlQueryParameterNames(query)].every(isPagingParameter);
const PAGE_POSITION_PARAMETERS = new Set(["offset", "start", "_start", "page"]);
/** A paging-only line that can start at the collection's beginning. Positive page numbers are ambiguous (zero- or one-based); malformed or conflicting positions do not establish whole membership. */
export const startsAtBeginning = (query: string | undefined): boolean => {
if (!pagesOnly(query)) return false;
for (const [name, value] of iterateUrlQueryParameters(query ?? "")) {
const number = Number(value);
if (!/^\d+$/u.test(value) || !Number.isSafeInteger(number)) return false;
if (PAGE_POSITION_PARAMETERS.has(name.toLowerCase()) && number !== 0)
return false;
}
return true;
};
/** Paging parameters that bound how many items a page holds. */
const PAGE_SIZE_PARAMETERS = new Set([
"limit",
"per_page",
"perpage",
"page_size",
"pagesize",
"size",
]);
/** The most items a query's page holds: its smallest whole-number page-size value or `_start`–`_end` range width, or undefined without one; with `unboundedZero`, a size of zero is no bound. */
const pageLimit = (
query: string | undefined,
unboundedZero: boolean,
): number | undefined => {
let size = Infinity;
const range = { start: 0, end: Infinity };
for (const [name, value] of iterateUrlQueryParameters(query ?? "")) {
const key = name.toLowerCase();
if (!/^\d+$/u.test(value)) continue;
const number = Number(value);
if (PAGE_SIZE_PARAMETERS.has(key)) {
if (number > 0 || !unboundedZero) size = Math.min(size, number);
} else if (key === "_start") range.start = number;
else if (key === "_end") range.end = number;
}
const width = Math.min(size, Math.max(range.end - range.start, 0));
return Number.isFinite(width) ? width : undefined;
};
/** The most items a line's call lists. A size of zero is no bound on a line whose own recording listed items under it, as an application reading zero as no limit does; every other size and range still bounds the page. */
export const pageBound = (
query: string | undefined,
recorded: number,
): number | undefined => pageLimit(query, recorded > 0);