@emeryld/rrroutes-client 2.6.12 → 2.7.0

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.
package/README.md CHANGED
@@ -47,7 +47,7 @@ export function Users() {
47
47
 
48
48
  - `createRouteClient` wires your `QueryClient`, base URL, optional custom fetcher, and debug settings.
49
49
  - `build(leaf, options?, meta?)` returns a helper that exposes:
50
- - `useEndpoint(args?)` — React hook for GET/feeds/mutations (typed params/query/body/output).
50
+ - `useEndpoint(args?, options?)` — React hook for GET/feeds/mutations (typed params/query/body/output) with optional per-call TanStack options.
51
51
  - `fetch(...)` — direct fetcher (no cache). Mutations require the body as the last argument.
52
52
  - `getQueryKeys(...)` — deterministic cache key used by React Query + invalidation.
53
53
  - `invalidate(...)` — invalidate this exact endpoint instance.
package/dist/index.cjs CHANGED
@@ -641,7 +641,8 @@ function buildGetLeaf(leaf, rqOpts, env) {
641
641
  });
642
642
  };
643
643
  const useEndpoint = (...useArgs) => {
644
- const args = useArgs[0];
644
+ const args = expectsArgs ? useArgs[0] : void 0;
645
+ const useEndpointOptions = expectsArgs ? useArgs[1] : useArgs[0];
645
646
  const tuple = toArgsTuple(args);
646
647
  const queryKeys = getQueryKeys(...tuple);
647
648
  emit({
@@ -650,12 +651,18 @@ function buildGetLeaf(leaf, rqOpts, env) {
650
651
  variant: "get",
651
652
  keys: queryKeys
652
653
  });
653
- const buildOptions = rqOpts ?? {};
654
+ const { onReceive: buildOnReceive2, ...buildQueryOptions } = rqOpts ?? {};
655
+ const { onReceive: useOnReceive, ...runtimeQueryOptions } = useEndpointOptions ?? {};
656
+ const mergedQueryOptions = {
657
+ ...buildQueryOptions,
658
+ ...runtimeQueryOptions
659
+ };
654
660
  const listenersRef = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
655
661
  const notifyOnReceive = (0, import_react2.useCallback)((data) => {
656
- buildOptions?.onReceive?.(data);
662
+ buildOnReceive2?.(data);
663
+ useOnReceive?.(data);
657
664
  listenersRef.current.forEach((listener) => listener(data));
658
- }, []);
665
+ }, [buildOnReceive2, useOnReceive]);
659
666
  const registerOnReceive = (0, import_react2.useCallback)(
660
667
  (listener) => {
661
668
  listenersRef.current.add(listener);
@@ -667,9 +674,9 @@ function buildGetLeaf(leaf, rqOpts, env) {
667
674
  );
668
675
  const queryResult = (0, import_react_query2.useQuery)(
669
676
  {
670
- ...buildOptions,
677
+ ...mergedQueryOptions,
671
678
  queryKey: getQueryKeys(...tuple),
672
- placeholderData: import_react_query2.keepPreviousData,
679
+ placeholderData: mergedQueryOptions.placeholderData ?? import_react_query2.keepPreviousData,
673
680
  queryFn: () => fetchEndpoint(tuple, {
674
681
  onReceive: notifyOnReceive
675
682
  })
@@ -914,7 +921,8 @@ function buildInfiniteGetLeaf(leaf, rqOpts, env) {
914
921
  });
915
922
  };
916
923
  const useEndpoint = (...useArgs) => {
917
- const args = useArgs[0];
924
+ const args = expectsArgs ? useArgs[0] : void 0;
925
+ const useEndpointOptions = expectsArgs ? useArgs[1] : useArgs[0];
918
926
  const tuple = toArgsTuple(args);
919
927
  const queryKeys = getQueryKeys(...tuple);
920
928
  emit({
@@ -926,11 +934,18 @@ function buildInfiniteGetLeaf(leaf, rqOpts, env) {
926
934
  const params = args?.params;
927
935
  const query = args?.query;
928
936
  const buildOptions = feedQueryOptions ?? {};
937
+ const { onReceive: buildOnReceive2, ...buildInfiniteQueryOptions } = buildOptions;
938
+ const { onReceive: useOnReceive, ...runtimeInfiniteQueryOptions } = useEndpointOptions ?? {};
939
+ const mergedInfiniteQueryOptions = {
940
+ ...buildInfiniteQueryOptions,
941
+ ...runtimeInfiniteQueryOptions
942
+ };
929
943
  const listenersRef = (0, import_react3.useRef)(/* @__PURE__ */ new Set());
930
944
  const notifyOnReceive = (0, import_react3.useCallback)((data) => {
931
- buildOptions?.onReceive?.(data);
945
+ buildOnReceive2?.(data);
946
+ useOnReceive?.(data);
932
947
  listenersRef.current.forEach((listener) => listener(data));
933
- }, []);
948
+ }, [buildOnReceive2, useOnReceive]);
934
949
  const registerOnReceive = (0, import_react3.useCallback)(
935
950
  (listener) => {
936
951
  listenersRef.current.add(listener);
@@ -948,8 +963,8 @@ function buildInfiniteGetLeaf(leaf, rqOpts, env) {
948
963
  );
949
964
  const queryResult = (0, import_react_query3.useInfiniteQuery)(
950
965
  {
951
- ...buildOptions,
952
- placeholderData: buildOptions.placeholderData ?? import_react_query3.keepPreviousData,
966
+ ...mergedInfiniteQueryOptions,
967
+ placeholderData: mergedInfiniteQueryOptions.placeholderData ?? import_react_query3.keepPreviousData,
953
968
  initialPageParam: feedInitialPageParam,
954
969
  getNextPageParam: (lastPage) => cursorFromPage(lastPage),
955
970
  queryKey: queryKeys,
@@ -1086,6 +1101,7 @@ function buildMutationLeaf(leaf, rqOpts, env) {
1086
1101
  return next;
1087
1102
  };
1088
1103
  const mutationBuildOptions = rqOpts ?? {};
1104
+ const { onReceive: mutationBuildOnReceive, ...mutationBuildQueryOptions } = mutationBuildOptions;
1089
1105
  const fetchEndpoint = async (tuple, options) => {
1090
1106
  const a = extractArgs(tuple);
1091
1107
  const params = a?.params;
@@ -1217,13 +1233,14 @@ function buildMutationLeaf(leaf, rqOpts, env) {
1217
1233
  const body = tupleWithBody[bodyIndex];
1218
1234
  const result = await fetchEndpoint(tuple, {
1219
1235
  body,
1220
- onReceive: (data) => mutationBuildOptions?.onReceive?.(data),
1236
+ onReceive: (data) => mutationBuildOnReceive?.(data),
1221
1237
  requireBody: true
1222
1238
  });
1223
1239
  return result;
1224
1240
  };
1225
1241
  const useEndpoint = (...useArgs) => {
1226
- const args = useArgs[0];
1242
+ const args = expectsArgs ? useArgs[0] : void 0;
1243
+ const useEndpointOptions = expectsArgs ? useArgs[1] : useArgs[0];
1227
1244
  const tuple = toArgsTuple(args);
1228
1245
  const mutationKey = getQueryKeys(...tuple);
1229
1246
  emit({
@@ -1232,6 +1249,11 @@ function buildMutationLeaf(leaf, rqOpts, env) {
1232
1249
  variant: "mutation",
1233
1250
  keys: mutationKey
1234
1251
  });
1252
+ const { onReceive: useOnReceive, ...runtimeMutationOptions } = useEndpointOptions ?? {};
1253
+ const mergedMutationOptions = {
1254
+ ...mutationBuildQueryOptions,
1255
+ ...runtimeMutationOptions
1256
+ };
1235
1257
  const listenersRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
1236
1258
  const notifyListeners = (0, import_react4.useCallback)((data) => {
1237
1259
  listenersRef.current.forEach((listener) => listener(data));
@@ -1247,12 +1269,13 @@ function buildMutationLeaf(leaf, rqOpts, env) {
1247
1269
  );
1248
1270
  const mutationResult = (0, import_react_query4.useMutation)(
1249
1271
  {
1250
- ...mutationBuildOptions ?? {},
1272
+ ...mergedMutationOptions,
1251
1273
  mutationKey,
1252
1274
  mutationFn: async (body) => {
1253
1275
  const result = await fetchMutation(
1254
1276
  ...[...tuple, body]
1255
1277
  );
1278
+ useOnReceive?.(result);
1256
1279
  notifyListeners(result);
1257
1280
  return result;
1258
1281
  }
@@ -2759,6 +2782,16 @@ function roomsFromData(data, args, toRooms) {
2759
2782
  }
2760
2783
 
2761
2784
  // src/sockets/socketedRoute/socket.client.helper.route.ts
2785
+ function parseUseEndpointArgs(useArgs) {
2786
+ const firstArg = useArgs[0];
2787
+ const firstArgRecord = firstArg && typeof firstArg === "object" ? firstArg : void 0;
2788
+ const hasRouteArgs = Boolean(
2789
+ firstArgRecord && (Object.prototype.hasOwnProperty.call(firstArgRecord, "params") || Object.prototype.hasOwnProperty.call(firstArgRecord, "query"))
2790
+ );
2791
+ const endpointArgs = hasRouteArgs ? firstArg : void 0;
2792
+ const endpointArgsTuple = typeof endpointArgs === "undefined" ? [] : [endpointArgs];
2793
+ return { endpointArgs, endpointArgsTuple };
2794
+ }
2762
2795
  function buildSocketedRoute(options) {
2763
2796
  const { built, toRooms, applySocket, useSocketClient: useSocketClient2, debug } = options;
2764
2797
  const { useEndpoint: useInnerEndpoint, ...rest } = built;
@@ -2768,11 +2801,15 @@ function buildSocketedRoute(options) {
2768
2801
  const endpointResult = useInnerEndpoint(
2769
2802
  ...useArgs
2770
2803
  );
2771
- const argsKey = (0, import_react5.useMemo)(() => safeJsonKey(useArgs[0] ?? null), [useArgs]);
2804
+ const { endpointArgs, endpointArgsTuple } = parseUseEndpointArgs(useArgs);
2805
+ const argsKey = (0, import_react5.useMemo)(
2806
+ () => safeJsonKey(endpointArgs ?? null),
2807
+ [endpointArgs]
2808
+ );
2772
2809
  const [roomState, setRoomState] = (0, import_react5.useState)(
2773
2810
  () => roomsFromData(
2774
2811
  endpointResult.data,
2775
- useArgs[0],
2812
+ endpointArgs,
2776
2813
  toRooms
2777
2814
  )
2778
2815
  );
@@ -2830,13 +2867,13 @@ function buildSocketedRoute(options) {
2830
2867
  setRoomState((prev) => {
2831
2868
  const next = mergeRoomState(
2832
2869
  prev,
2833
- toRoomsRef.current(data, useArgs[0])
2870
+ toRoomsRef.current(data, endpointArgs)
2834
2871
  );
2835
2872
  return roomStateEqual(prev, next) ? prev : next;
2836
2873
  });
2837
2874
  });
2838
2875
  return unsubscribe;
2839
- }, [endpointResult.onReceive]);
2876
+ }, [endpointResult.onReceive, argsKey]);
2840
2877
  (0, import_react5.useEffect)(() => {
2841
2878
  trackHookTrigger2({
2842
2879
  ref: deriveRoomsEffectDebugRef,
@@ -2848,7 +2885,7 @@ function buildSocketedRoute(options) {
2848
2885
  toRoomsRef: describeObjectReference(toRooms)
2849
2886
  }
2850
2887
  });
2851
- const next = roomsFromData(endpointDataRef.current, useArgs[0], toRooms);
2888
+ const next = roomsFromData(endpointDataRef.current, endpointArgs, toRooms);
2852
2889
  setRoomState((prev) => roomStateEqual(prev, next) ? prev : next);
2853
2890
  }, [argsKey, toRooms, debug]);
2854
2891
  (0, import_react5.useEffect)(() => {
@@ -2964,11 +3001,12 @@ function buildSocketedRoute(options) {
2964
3001
  if (!nextUpdate) continue;
2965
3002
  built.setData(
2966
3003
  (prev) => {
2967
- const next = nextUpdate.fn(
3004
+ const next = nextUpdate.fn({
2968
3005
  prev,
2969
- nextUpdate.payload,
2970
- nextUpdate.meta ? { ...nextUpdate.meta, args: useArgs } : { args: useArgs }
2971
- );
3006
+ payload: nextUpdate.payload,
3007
+ args: endpointArgs,
3008
+ meta: nextUpdate.meta ?? {}
3009
+ });
2972
3010
  if (next === null) return prev;
2973
3011
  if (shouldWarnSocketMutationGuard() && isSameObjectReference(prev, next) && !sameRefWarnedEvents.has(nextUpdate.event)) {
2974
3012
  sameRefWarnedEvents.add(nextUpdate.event);
@@ -2978,7 +3016,7 @@ function buildSocketedRoute(options) {
2978
3016
  }
2979
3017
  const nextRoomState = roomsFromData(
2980
3018
  next,
2981
- useArgs[0],
3019
+ endpointArgs,
2982
3020
  toRooms
2983
3021
  );
2984
3022
  setRoomState(
@@ -2986,7 +3024,7 @@ function buildSocketedRoute(options) {
2986
3024
  );
2987
3025
  return next;
2988
3026
  },
2989
- ...useArgs
3027
+ ...endpointArgsTuple
2990
3028
  );
2991
3029
  }
2992
3030
  } finally {