@jsenv/navi 0.29.127 → 0.29.128

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.
@@ -3000,8 +3000,9 @@ naviI18n.addAll({
3000
3000
  * read by the action layer rather than by every callback.
3001
3001
  *
3002
3002
  * Under a policy (a truthy reason):
3003
- * - a resource GET answers with the row its store holds for its params and
3004
- * asks nothing (resource_graph.js, applyNetworkPolicy); a completed read
3003
+ * - a resource GET answers with the row its store holds for it named by its
3004
+ * params, or the one it last completed with — and asks nothing
3005
+ * (resource_graph.js, applyNetworkPolicy); a completed read
3005
3006
  * asked to rerun stays completed (actions.js, handleActionRequest);
3006
3007
  * anything else settles with an OfflineError carrying the reason;
3007
3008
  * - a control bound to a write — or inside a form bound to one — is read-only
@@ -4037,6 +4038,7 @@ const createAction = (callback, rootOptions = {}) => {
4037
4038
  event,
4038
4039
  signal: internalAbortSignal,
4039
4040
  isPrerun,
4041
+ action,
4040
4042
  });
4041
4043
  const returnValue = sideEffect(...args);
4042
4044
  if (typeof returnValue === "function") {
@@ -14792,7 +14794,7 @@ const debug$3 = (...args) => {
14792
14794
  *
14793
14795
  * @param {string} name - resource name, used in action names and error messages
14794
14796
  * @param {Object} restCallbacks - `{ idKey, uniqueKeys, rerunOn, dependencies, GET, GET_MANY, GET_RANGE, POST, POST_MANY, PUT, PUT_MANY, PATCH, PATCH_MANY, DELETE, DELETE_MANY }`
14795
- * @param {string} [restCallbacks.idKey] - primary key property, defaults to `"id"` (or the first `uniqueKeys` entry)
14797
+ * @param {string} [restCallbacks.idKey] - primary key property, defaults to `"id"`
14796
14798
  * @param {string[]} [restCallbacks.uniqueKeys] - alternate keys the store can find an item by (e.g. `"username"`); a callback may return a different `id` to rename the item's primary key
14797
14799
  * @see docs/resource.md — relationships, callback return contracts, decision table
14798
14800
  *
@@ -14808,7 +14810,7 @@ const resource = (
14808
14810
  name,
14809
14811
  {
14810
14812
  // configuration options
14811
- idKey,
14813
+ idKey = "id",
14812
14814
  uniqueKeys = [],
14813
14815
  rerunOn,
14814
14816
  dependencies,
@@ -14827,9 +14829,6 @@ const resource = (
14827
14829
  } = {},
14828
14830
  ) => {
14829
14831
  const declarationSite = getDeclarationSite();
14830
- if (idKey === undefined) {
14831
- idKey = uniqueKeys.length === 0 ? "id" : uniqueKeys[0];
14832
- }
14833
14832
  const setupCallbackSet = new Set();
14834
14833
  const addItemSetup = (callback) => {
14835
14834
  setupCallbackSet.add(callback);
@@ -14877,10 +14876,12 @@ const resource = (
14877
14876
  store,
14878
14877
  declarationSite,
14879
14878
  });
14880
- // The row a GET's params designate, when the store already holds it: the
14881
- // value under idKey may be the id or any unique key (a route opening a user
14882
- // by id or by slug names both `id`), and a unique key may be given under its
14883
- // own name. Answers a GET under a network policy (see applyNetworkPolicy).
14879
+ // The row a GET designates, when the store already holds it — by its params:
14880
+ // the value under idKey may be the id or any unique key (a route opening a
14881
+ // user by id or by slug names both `id`), and a unique key may be given under
14882
+ // its own name; or, when the params name no row (a GET without params, or
14883
+ // whose params carry no key), the row the action last completed with.
14884
+ // Answers a GET under a network policy (see applyNetworkPolicy).
14884
14885
  const selectByAnyKey = (value) => {
14885
14886
  const item = store.select(value);
14886
14887
  if (item) {
@@ -14894,31 +14895,42 @@ const resource = (
14894
14895
  }
14895
14896
  return null;
14896
14897
  };
14897
- const findItemInStore = (params) => {
14898
- return untracked(() => {
14899
- if (primitiveCanBeId(params)) {
14900
- return selectByAnyKey(params);
14901
- }
14902
- if (!isProps(params)) {
14903
- return null;
14898
+ const findItemByParams = (params) => {
14899
+ if (primitiveCanBeId(params)) {
14900
+ return selectByAnyKey(params);
14901
+ }
14902
+ if (!isProps(params)) {
14903
+ return null;
14904
+ }
14905
+ const idParam = params[idKey];
14906
+ if (idParam !== undefined) {
14907
+ const item = selectByAnyKey(idParam);
14908
+ if (item) {
14909
+ return item;
14904
14910
  }
14905
- const idParam = params[idKey];
14906
- if (idParam !== undefined) {
14907
- const item = selectByAnyKey(idParam);
14911
+ }
14912
+ for (const uniqueKey of uniqueKeys) {
14913
+ const uniqueKeyParam = params[uniqueKey];
14914
+ if (uniqueKeyParam !== undefined) {
14915
+ const item = store.select(uniqueKey, uniqueKeyParam);
14908
14916
  if (item) {
14909
14917
  return item;
14910
14918
  }
14911
14919
  }
14912
- for (const uniqueKey of uniqueKeys) {
14913
- const uniqueKeyParam = params[uniqueKey];
14914
- if (uniqueKeyParam !== undefined) {
14915
- const item = store.select(uniqueKey, uniqueKeyParam);
14916
- if (item) {
14917
- return item;
14918
- }
14919
- }
14920
+ }
14921
+ return null;
14922
+ };
14923
+ const findItemInStore = (params, action) => {
14924
+ return untracked(() => {
14925
+ const itemByParams = findItemByParams(params);
14926
+ if (itemByParams) {
14927
+ return itemByParams;
14920
14928
  }
14921
- return null;
14929
+ const lastItemId = getLastGetItemId(action);
14930
+ if (lastItemId === undefined) {
14931
+ return null;
14932
+ }
14933
+ return store.select(lastItemId) || null;
14922
14934
  });
14923
14935
  };
14924
14936
  return createResource(name, {
@@ -15970,6 +15982,9 @@ const createRestActionFactoryForRoot = (
15970
15982
  // lifecycle rules can detect whether sub-resources were embedded.
15971
15983
  if (verb === "GET") {
15972
15984
  recordGetResultProperties(action, Object.keys(result));
15985
+ const itemId = applyResultToValue(result);
15986
+ lastGetItemIdWeakMap.set(action, itemId);
15987
+ return itemId;
15973
15988
  }
15974
15989
  return applyResultToValue(result);
15975
15990
  },
@@ -16017,12 +16032,12 @@ const createRestActionFactoryForRoot = (
16017
16032
  };
16018
16033
 
16019
16034
  // Under a network policy no callback is called (see network_policy.js). A GET
16020
- // of a root resource answers with the row the store holds for its params —
16021
- // handing the item back is an upsert without effect, so the action completes
16022
- // with what it had and nothing is asked. A relationship GET has no row of its
16023
- // own to answer with, and a write has nothing to answer: both settle with an
16024
- // OfflineError carrying the policy's reason. A completed GET asked to rerun
16025
- // never gets here (actions.js holds it).
16035
+ // of a root resource answers with the row the store holds for it (see
16036
+ // findItemInStore) — handing the item back is an upsert without effect, so the
16037
+ // action completes with what it had and nothing is asked. A relationship GET
16038
+ // has no row of its own to answer with, and a write has nothing to answer:
16039
+ // both settle with an OfflineError carrying the policy's reason. A completed
16040
+ // GET asked to rerun never gets here (actions.js holds it).
16026
16041
  const applyNetworkPolicy = (
16027
16042
  restCallback,
16028
16043
  { verb, isMany, findItemInStore },
@@ -16033,7 +16048,7 @@ const applyNetworkPolicy = (
16033
16048
  return restCallback(params, context);
16034
16049
  }
16035
16050
  if (verb === "GET" && !isMany && findItemInStore) {
16036
- const item = findItemInStore(params);
16051
+ const item = findItemInStore(params, context.action);
16037
16052
  if (item) {
16038
16053
  return item;
16039
16054
  }
@@ -16042,6 +16057,14 @@ const applyNetworkPolicy = (
16042
16057
  };
16043
16058
  };
16044
16059
 
16060
+ // WeakMap<action, itemId> — the row each GET action last completed with. A
16061
+ // reset clears the action's value; this survives it, so a GET run again after
16062
+ // a reset can still be answered from the store under a network policy.
16063
+ const lastGetItemIdWeakMap = new WeakMap();
16064
+ const getLastGetItemId = (action) => {
16065
+ return lastGetItemIdWeakMap.get(action);
16066
+ };
16067
+
16045
16068
  // Captures the "file:line:column" of the user code that invoked the public
16046
16069
  // function (resource(), .one(), .many(), withParams, …), so invalid-result
16047
16070
  // errors can point at where the callbacks were declared, not at this file.