@jsenv/navi 0.30.36 → 0.30.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30518,8 +30518,9 @@ const SCOPED_MANY_OPTIONS = new Set([
30518
30518
  * policy as that verb, and is a write of its own for a dependent:
30519
30519
  * `{ resource: ORDER, on: ["cancel"] }`. Its `rerunOn` says which reads of
30520
30520
  * this resource it reruns (`{ GET_RANGE: true }`); a read it leaves out
30521
- * follows `rerunOn` for its verb. A name a verb takes, or one the resource
30522
- * already exposes (`withParams`, `store`…), throws. A `.scopedOne()` or
30521
+ * follows `rerunOn` for its verb. A verb's name in any case (`post`,
30522
+ * `get_many`…), or one the resource already exposes (`withParams`, `store`…),
30523
+ * throws. A `.scopedOne()` or
30523
30524
  * `.scopedMany()` takes `writes` too, `.scopedMany()` with the plural verbs.
30524
30525
  * @param {{ GET?: { ms?: number, max?: number }, GET_MANY?: { ms?: number, max?: number } }} [restCallbacks.keep] -
30525
30526
  * how long an answer of a read is trusted, coming back to the same params
@@ -32084,12 +32085,15 @@ ${name}.many("${propertyName}") source location: ${declarationSite}`,
32084
32085
 
32085
32086
  // expose one action per write named in `writes`
32086
32087
  if (writes) {
32088
+ const membersExposed = Object.keys(stateFacade).filter(
32089
+ (key) => !VERB_KEYS.includes(key),
32090
+ );
32087
32091
  for (const [writeName, write] of Object.entries(writes)) {
32088
32092
  assertWriteCanBeNamed(
32089
32093
  name,
32090
32094
  writeName,
32091
32095
  write,
32092
- stateFacade,
32096
+ membersExposed,
32093
32097
  namedWriteVerbs,
32094
32098
  );
32095
32099
  const { verb: writeVerb, callback, rerunOn: writeRerunOn } = write;
@@ -32402,7 +32406,7 @@ const assertWriteCanBeNamed = (
32402
32406
  name,
32403
32407
  writeName,
32404
32408
  write,
32405
- stateFacade,
32409
+ membersExposed,
32406
32410
  namedWriteVerbs,
32407
32411
  ) => {
32408
32412
  const where = `resource(${name}) writes.${writeName}`;
@@ -32411,9 +32415,9 @@ const assertWriteCanBeNamed = (
32411
32415
  `${where}: "${writeName}" is a verb's name — a write named in "writes" takes a name of its own (cancel, archive…)`,
32412
32416
  );
32413
32417
  }
32414
- if (Object.hasOwn(stateFacade, writeName)) {
32418
+ if (membersExposed.includes(writeName)) {
32415
32419
  throw new Error(
32416
- `${where}: the resource already exposes "${writeName}" — pick another name`,
32420
+ `${where}: the resource already exposes "${writeName}" — a write takes a name none of its members has: ${membersExposed.join(", ")}`,
32417
32421
  );
32418
32422
  }
32419
32423
  if (!write || typeof write !== "object") {
@@ -92780,8 +92784,19 @@ const useItemStore = ({
92780
92784
  // was asked for, and the window keeps growing meanwhile: dropping what the
92781
92785
  // page did not cover empties items on screen.
92782
92786
  const staleRanksRef = useRef(null);
92787
+ // A run standing for no item has no rank to mark: its count is what is from
92788
+ // before, and no window frames anything that would ask for it again.
92789
+ const countStaleRef = useRef(false);
92790
+ const markHeldStale = () => {
92791
+ staleRanksRef.current = new Set(pages.byIndex.keys());
92792
+ countStaleRef.current = pages.count === 0;
92793
+ };
92783
92794
  if (staleRanksRef.current === null) {
92784
- staleRanksRef.current = restored ? new Set(pages.byIndex.keys()) : new Set();
92795
+ if (restored) {
92796
+ markHeldStale();
92797
+ } else {
92798
+ staleRanksRef.current = new Set();
92799
+ }
92785
92800
  }
92786
92801
  const takeInPage = ({
92787
92802
  pageItems,
@@ -92820,6 +92835,7 @@ const useItemStore = ({
92820
92835
  i++;
92821
92836
  }
92822
92837
  pages.count = pageCount;
92838
+ countStaleRef.current = false;
92823
92839
  // Which rank holds which id, kept by the source so a list drawing
92824
92840
  // this collection again finds it drawn (see readComposition above).
92825
92841
  if (itemsAction.writeComposition) {
@@ -92855,7 +92871,7 @@ const useItemStore = ({
92855
92871
  const invalidationRef = useRef(invalidation);
92856
92872
  if (invalidationRef.current !== invalidation) {
92857
92873
  invalidationRef.current = invalidation;
92858
- staleRanksRef.current = new Set(pages.byIndex.keys());
92874
+ markHeldStale();
92859
92875
  }
92860
92876
  // The one request in flight, with the means to call it off: a page asked for
92861
92877
  // a window the list has left is work the server and the browser are doing for
@@ -93053,7 +93069,8 @@ const useItemStore = ({
93053
93069
  rank++;
93054
93070
  }
93055
93071
  }
93056
- const revalidating = staleFrom !== -1;
93072
+ const countStale = countStaleRef.current;
93073
+ const revalidating = staleFrom !== -1 || countStale;
93057
93074
  // The list is held on an item nothing on screen leads to: the items it holds
93058
93075
  // do not contain it, so no window it could draw will ever bring it. Only
93059
93076
  // asking for it by name does.
@@ -93069,6 +93086,10 @@ const useItemStore = ({
93069
93086
  const from = typeof wanted.index === "number" ? rankOfIndex(wanted.index) - Math.floor(budget / 2) : 0;
93070
93087
  start = from < 0 ? 0 : from;
93071
93088
  end = start + budget - 1;
93089
+ } else if (countStale) {
93090
+ // Nothing drawn to anchor on: the first page, like the very first ask.
93091
+ start = 0;
93092
+ end = budget - 1;
93072
93093
  } else if (revalidating) {
93073
93094
  // The items from before that the window draws, and the missing ones
93074
93095
  // with them: one ask.
@@ -93270,6 +93291,7 @@ const useItemStore = ({
93270
93291
  staleRanksRef.current.delete(rank);
93271
93292
  rank++;
93272
93293
  }
93294
+ countStaleRef.current = false;
93273
93295
  setRefreshing(false);
93274
93296
  return;
93275
93297
  }