(
_collection: string,
opts: ListOpts = {},
)
| 323 | return row as unknown as T; |
| 324 | }, |
| 325 | async list<T>( |
| 326 | _collection: string, |
| 327 | opts: ListOpts = {}, |
| 328 | ): Promise<ListResult<T>> { |
| 329 | // Honor `status` AND `probe_key` clauses faithfully (shared matcher) so |
| 330 | // the claimNext candidate scan, the family-discovery exclusions, and the |
| 331 | // sweepExpired scans are exercised the way real PB would serve them. A |
| 332 | // clause on any OTHER field THROWS (see rowMatchesFilter) instead of |
| 333 | // silently matching everything. |
| 334 | let items = store.filter((r) => rowMatchesFilter(r, opts.filter)); |
| 335 | // SORT honesty (G1h): this fake used to IGNORE `sort` entirely — any |
| 336 | // test depending on an order the production query requested passed |
| 337 | // vacuously on insertion order. Model the two production sort keys |
| 338 | // (rows here usually lack `created`, where the STABLE sort preserves |
| 339 | // insertion order — PB's tie behavior for identical values) and THROW |
| 340 | // on anything else, matching the fakes' unsupported philosophy. |
| 341 | const desc = opts.sort?.startsWith("-") ?? false; |
| 342 | const sortKey = desc ? opts.sort!.slice(1) : opts.sort; |
| 343 | if (sortKey === "created") { |
| 344 | items = [...items].sort((a, b) => |
| 345 | String((a as { created?: string }).created ?? "").localeCompare( |
| 346 | String((b as { created?: string }).created ?? ""), |
| 347 | ), |
| 348 | ); |
| 349 | } else if (sortKey === "lease_expires_at") { |
| 350 | items = [...items].sort((a, b) => |
| 351 | String(a.lease_expires_at ?? "").localeCompare( |
| 352 | String(b.lease_expires_at ?? ""), |
| 353 | ), |
| 354 | ); |
| 355 | } else if (sortKey) { |
| 356 | throw new Error( |
| 357 | `fake-pb: unmodeled sort key "${sortKey}" — only created/lease_expires_at are honored`, |
| 358 | ); |
| 359 | } |
| 360 | if (desc) items.reverse(); |
| 361 | const totalItems = items.length; |
| 362 | // PAGING honesty (G1h): perPage used to be ignored — a matched set |
| 363 | // LARGER than the requested page came back whole, hiding truncation |
| 364 | // behavior the production pagination depends on. Slice like PB. |
| 365 | if (opts.perPage !== undefined) { |
| 366 | const page = opts.page ?? 1; |
| 367 | items = items.slice((page - 1) * opts.perPage, page * opts.perPage); |
| 368 | } |
| 369 | return { |
| 370 | page: opts.page ?? 1, |
| 371 | perPage: opts.perPage ?? items.length, |
| 372 | totalPages: |
| 373 | opts.skipTotal === true |
| 374 | ? -1 |
| 375 | : opts.perPage !== undefined |
| 376 | ? Math.max(1, Math.ceil(totalItems / opts.perPage)) |
| 377 | : 1, |
| 378 | // Faithful to PB: a skipTotal list returns totalItems -1, NOT the |
| 379 | // real count. A fake that returned real counts under skipTotal |
| 380 | // would green-light code reading totals it never requested (the |
| 381 | // fail-open class countPendingForFamily's skipTotal:false pin |
| 382 | // exists to prevent). |
nothing calls this directly
no test coverage detected
searching dependent graphs…