@emeryld/rrroutes-client 2.7.3 → 2.7.5

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
@@ -468,20 +468,21 @@ import { buildSocketedRoute } from '@emeryld/rrroutes-client';
468
468
  import { useSocketClient } from './socketProvider';
469
469
 
470
470
  const listRooms = client.build(registry.byKey['GET /v1/rooms'], { staleTime: 120_000 });
471
+ const useAppSocketContext = () => ({ workspaceId: 'acme' });
471
472
 
472
473
  const socketedRooms = buildSocketedRoute({
473
474
  built: listRooms,
474
- toRooms: (page) => ({
475
- rooms: page.items.map((r) => r.id), // derive rooms from data (feeds supported)
475
+ useContext: useAppSocketContext, // optional app-level context for hooks
476
+ toRooms: ({ data, meta }) => ({
477
+ rooms: data.items.map((r) => `${meta?.appContext?.workspaceId}:${r.id}`), // derive rooms from data (feeds supported)
476
478
  joinMeta: { source: 'rooms:list' },
477
479
  leaveMeta: { source: 'rooms:list' },
478
480
  }),
479
481
  useSocketClient,
480
482
  applySocket: {
481
- 'chat:message': (prev, payload, meta) => {
483
+ 'chat:message': ({ prev, payload, args, meta }) => {
482
484
  if (!prev) return null; // explicit no-op update
483
- const [args] = meta.args;
484
- console.debug('socket patch args', args);
485
+ console.debug('socket patch args', args, meta.appContext?.workspaceId, meta.ctx?.socketId);
485
486
  // Example: bump unread count in cache
486
487
  const apply = (items: any[]) =>
487
488
  items.map((room) =>
@@ -505,7 +506,11 @@ function RoomList() {
505
506
  }
506
507
  ```
507
508
 
508
- `buildSocketedRoute(...)` returns a built endpoint object with `useEndpoint()` plus the original built helpers. `applySocket` receives `{ envelope?, ctx?, args }` and can return `null` to skip cache updates.
509
+ `buildSocketedRoute(...)` returns a built endpoint object with `useEndpoint()` plus the original built helpers.
510
+
511
+ - `toRooms` receives `{ data, args, meta }` where `meta.appContext` comes from `useContext` (if provided).
512
+ - `applySocket` handlers receive `{ prev, payload, args, meta }`, where `meta` contains `envelope?`, `ctx?`, and `appContext?`.
513
+ - Return `null` from `applySocket` to skip cache updates.
509
514
 
510
515
  ---
511
516
 
package/dist/index.cjs CHANGED
@@ -963,11 +963,14 @@ function buildInfiniteGetLeaf(leaf, rqOpts, env) {
963
963
  const mergedEnabled = mergedInfiniteQueryOptions.enabled;
964
964
  const guardedEnabled = hasCompleteArgs && (typeof mergedEnabled === "undefined" ? true : mergedEnabled);
965
965
  const listenersRef = (0, import_react3.useRef)(/* @__PURE__ */ new Set());
966
- const notifyOnReceive = (0, import_react3.useCallback)((data) => {
967
- buildOnReceive2?.(data);
968
- useOnReceive?.(data);
969
- listenersRef.current.forEach((listener) => listener(data));
970
- }, [buildOnReceive2, useOnReceive]);
966
+ const notifyOnReceive = (0, import_react3.useCallback)(
967
+ (data) => {
968
+ buildOnReceive2?.(data);
969
+ useOnReceive?.(data);
970
+ listenersRef.current.forEach((listener) => listener(data));
971
+ },
972
+ [buildOnReceive2, useOnReceive]
973
+ );
971
974
  const registerOnReceive = (0, import_react3.useCallback)(
972
975
  (listener) => {
973
976
  listenersRef.current.add(listener);
@@ -2776,12 +2779,15 @@ function mergeRoomState(prev, toRoomsResult) {
2776
2779
  leaveMeta: toRoomsResult.leaveMeta ?? prev.leaveMeta
2777
2780
  };
2778
2781
  }
2779
- function roomsFromData(data, args, toRooms) {
2782
+ function roomsFromData(data, args, toRooms, meta) {
2780
2783
  if (data == null) return { rooms: [] };
2781
2784
  let state = { rooms: [] };
2782
2785
  const add = (input) => {
2783
2786
  const mergeForValue = (value) => {
2784
- state = mergeRoomState(state, toRooms(value, args));
2787
+ state = mergeRoomState(
2788
+ state,
2789
+ toRooms({ data: value, args, meta })
2790
+ );
2785
2791
  };
2786
2792
  if (Array.isArray(input)) {
2787
2793
  input.forEach((entry) => mergeForValue(entry));
@@ -2816,8 +2822,21 @@ function parseUseEndpointArgs(useArgs) {
2816
2822
  const endpointArgsTuple = typeof endpointArgs === "undefined" ? [] : [endpointArgs];
2817
2823
  return { endpointArgs, endpointArgsTuple };
2818
2824
  }
2825
+ function useDefaultSocketedRouteContext() {
2826
+ return void 0;
2827
+ }
2828
+ function createToRoomsMeta(appContext) {
2829
+ return { appContext };
2830
+ }
2819
2831
  function buildSocketedRoute(options) {
2820
- const { built, toRooms, applySocket, useSocketClient: useSocketClient2, debug } = options;
2832
+ const {
2833
+ built,
2834
+ toRooms,
2835
+ applySocket,
2836
+ useSocketClient: useSocketClient2,
2837
+ useContext: useRouteContext = useDefaultSocketedRouteContext,
2838
+ debug
2839
+ } = options;
2821
2840
  const { useEndpoint: useInnerEndpoint, ...rest } = built;
2822
2841
  const useEndpoint = (...useArgs) => {
2823
2842
  const client = useSocketClient2();
@@ -2825,6 +2844,11 @@ function buildSocketedRoute(options) {
2825
2844
  const endpointResult = useInnerEndpoint(
2826
2845
  ...useArgs
2827
2846
  );
2847
+ const appContext = useRouteContext();
2848
+ const toRoomsMeta = (0, import_react5.useMemo)(
2849
+ () => createToRoomsMeta(appContext),
2850
+ [appContext]
2851
+ );
2828
2852
  const { endpointArgs, endpointArgsTuple } = parseUseEndpointArgs(useArgs);
2829
2853
  const argsKey = (0, import_react5.useMemo)(
2830
2854
  () => safeJsonKey(endpointArgs ?? null),
@@ -2834,7 +2858,8 @@ function buildSocketedRoute(options) {
2834
2858
  () => roomsFromData(
2835
2859
  endpointResult.data,
2836
2860
  endpointArgs,
2837
- toRooms
2861
+ toRooms,
2862
+ toRoomsMeta
2838
2863
  )
2839
2864
  );
2840
2865
  const renderCountRef = (0, import_react5.useRef)(0);
@@ -2843,6 +2868,7 @@ function buildSocketedRoute(options) {
2843
2868
  endpointResult.data
2844
2869
  );
2845
2870
  const toRoomsRef = (0, import_react5.useRef)(toRooms);
2871
+ const toRoomsMetaRef = (0, import_react5.useRef)(toRoomsMeta);
2846
2872
  const onReceiveEffectDebugRef = (0, import_react5.useRef)(null);
2847
2873
  const deriveRoomsEffectDebugRef = (0, import_react5.useRef)(null);
2848
2874
  const joinRoomsEffectDebugRef = (0, import_react5.useRef)(null);
@@ -2850,6 +2876,7 @@ function buildSocketedRoute(options) {
2850
2876
  renderCountRef.current += 1;
2851
2877
  endpointDataRef.current = endpointResult.data;
2852
2878
  toRoomsRef.current = toRooms;
2879
+ toRoomsMetaRef.current = toRoomsMeta;
2853
2880
  const roomsKey = (0, import_react5.useMemo)(() => roomState.rooms.join("|"), [roomState.rooms]);
2854
2881
  const joinMetaKey = (0, import_react5.useMemo)(
2855
2882
  () => safeJsonKey(roomState.joinMeta ?? null),
@@ -2891,7 +2918,11 @@ function buildSocketedRoute(options) {
2891
2918
  setRoomState((prev) => {
2892
2919
  const next = mergeRoomState(
2893
2920
  prev,
2894
- toRoomsRef.current(data, endpointArgs)
2921
+ toRoomsRef.current({
2922
+ data,
2923
+ args: endpointArgs,
2924
+ meta: toRoomsMetaRef.current
2925
+ })
2895
2926
  );
2896
2927
  return roomStateEqual(prev, next) ? prev : next;
2897
2928
  });
@@ -2909,9 +2940,14 @@ function buildSocketedRoute(options) {
2909
2940
  toRoomsRef: describeObjectReference(toRooms)
2910
2941
  }
2911
2942
  });
2912
- const next = roomsFromData(endpointDataRef.current, endpointArgs, toRooms);
2943
+ const next = roomsFromData(
2944
+ endpointDataRef.current,
2945
+ endpointArgs,
2946
+ toRooms,
2947
+ toRoomsMeta
2948
+ );
2913
2949
  setRoomState((prev) => roomStateEqual(prev, next) ? prev : next);
2914
- }, [argsKey, toRooms, debug]);
2950
+ }, [argsKey, toRooms, toRoomsMeta, debug]);
2915
2951
  (0, import_react5.useEffect)(() => {
2916
2952
  trackHookTrigger2({
2917
2953
  ref: joinRoomsEffectDebugRef,
@@ -3029,7 +3065,10 @@ function buildSocketedRoute(options) {
3029
3065
  prev,
3030
3066
  payload: nextUpdate.payload,
3031
3067
  args: endpointArgs,
3032
- meta: nextUpdate.meta ?? {}
3068
+ meta: {
3069
+ ...nextUpdate.meta ?? {},
3070
+ appContext: toRoomsMetaRef.current.appContext
3071
+ }
3033
3072
  });
3034
3073
  if (next === null) return prev;
3035
3074
  if (shouldWarnSocketMutationGuard() && isSameObjectReference(prev, next) && !sameRefWarnedEvents.has(nextUpdate.event)) {
@@ -3041,7 +3080,8 @@ function buildSocketedRoute(options) {
3041
3080
  const nextRoomState = roomsFromData(
3042
3081
  next,
3043
3082
  endpointArgs,
3044
- toRooms
3083
+ toRooms,
3084
+ toRoomsMetaRef.current
3045
3085
  );
3046
3086
  setRoomState(
3047
3087
  (prevRoomState) => roomStateEqual(prevRoomState, nextRoomState) ? prevRoomState : nextRoomState