@emeryld/rrroutes-client 2.7.3 → 2.7.4

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
@@ -2776,12 +2776,15 @@ function mergeRoomState(prev, toRoomsResult) {
2776
2776
  leaveMeta: toRoomsResult.leaveMeta ?? prev.leaveMeta
2777
2777
  };
2778
2778
  }
2779
- function roomsFromData(data, args, toRooms) {
2779
+ function roomsFromData(data, args, toRooms, meta) {
2780
2780
  if (data == null) return { rooms: [] };
2781
2781
  let state = { rooms: [] };
2782
2782
  const add = (input) => {
2783
2783
  const mergeForValue = (value) => {
2784
- state = mergeRoomState(state, toRooms(value, args));
2784
+ state = mergeRoomState(
2785
+ state,
2786
+ toRooms({ data: value, args, meta })
2787
+ );
2785
2788
  };
2786
2789
  if (Array.isArray(input)) {
2787
2790
  input.forEach((entry) => mergeForValue(entry));
@@ -2816,8 +2819,21 @@ function parseUseEndpointArgs(useArgs) {
2816
2819
  const endpointArgsTuple = typeof endpointArgs === "undefined" ? [] : [endpointArgs];
2817
2820
  return { endpointArgs, endpointArgsTuple };
2818
2821
  }
2822
+ function useDefaultSocketedRouteContext() {
2823
+ return void 0;
2824
+ }
2825
+ function createToRoomsMeta(appContext) {
2826
+ return { appContext };
2827
+ }
2819
2828
  function buildSocketedRoute(options) {
2820
- const { built, toRooms, applySocket, useSocketClient: useSocketClient2, debug } = options;
2829
+ const {
2830
+ built,
2831
+ toRooms,
2832
+ applySocket,
2833
+ useSocketClient: useSocketClient2,
2834
+ useContext: useRouteContext = useDefaultSocketedRouteContext,
2835
+ debug
2836
+ } = options;
2821
2837
  const { useEndpoint: useInnerEndpoint, ...rest } = built;
2822
2838
  const useEndpoint = (...useArgs) => {
2823
2839
  const client = useSocketClient2();
@@ -2825,6 +2841,11 @@ function buildSocketedRoute(options) {
2825
2841
  const endpointResult = useInnerEndpoint(
2826
2842
  ...useArgs
2827
2843
  );
2844
+ const appContext = useRouteContext();
2845
+ const toRoomsMeta = (0, import_react5.useMemo)(
2846
+ () => createToRoomsMeta(appContext),
2847
+ [appContext]
2848
+ );
2828
2849
  const { endpointArgs, endpointArgsTuple } = parseUseEndpointArgs(useArgs);
2829
2850
  const argsKey = (0, import_react5.useMemo)(
2830
2851
  () => safeJsonKey(endpointArgs ?? null),
@@ -2834,7 +2855,8 @@ function buildSocketedRoute(options) {
2834
2855
  () => roomsFromData(
2835
2856
  endpointResult.data,
2836
2857
  endpointArgs,
2837
- toRooms
2858
+ toRooms,
2859
+ toRoomsMeta
2838
2860
  )
2839
2861
  );
2840
2862
  const renderCountRef = (0, import_react5.useRef)(0);
@@ -2843,6 +2865,7 @@ function buildSocketedRoute(options) {
2843
2865
  endpointResult.data
2844
2866
  );
2845
2867
  const toRoomsRef = (0, import_react5.useRef)(toRooms);
2868
+ const toRoomsMetaRef = (0, import_react5.useRef)(toRoomsMeta);
2846
2869
  const onReceiveEffectDebugRef = (0, import_react5.useRef)(null);
2847
2870
  const deriveRoomsEffectDebugRef = (0, import_react5.useRef)(null);
2848
2871
  const joinRoomsEffectDebugRef = (0, import_react5.useRef)(null);
@@ -2850,6 +2873,7 @@ function buildSocketedRoute(options) {
2850
2873
  renderCountRef.current += 1;
2851
2874
  endpointDataRef.current = endpointResult.data;
2852
2875
  toRoomsRef.current = toRooms;
2876
+ toRoomsMetaRef.current = toRoomsMeta;
2853
2877
  const roomsKey = (0, import_react5.useMemo)(() => roomState.rooms.join("|"), [roomState.rooms]);
2854
2878
  const joinMetaKey = (0, import_react5.useMemo)(
2855
2879
  () => safeJsonKey(roomState.joinMeta ?? null),
@@ -2891,7 +2915,11 @@ function buildSocketedRoute(options) {
2891
2915
  setRoomState((prev) => {
2892
2916
  const next = mergeRoomState(
2893
2917
  prev,
2894
- toRoomsRef.current(data, endpointArgs)
2918
+ toRoomsRef.current({
2919
+ data,
2920
+ args: endpointArgs,
2921
+ meta: toRoomsMetaRef.current
2922
+ })
2895
2923
  );
2896
2924
  return roomStateEqual(prev, next) ? prev : next;
2897
2925
  });
@@ -2909,9 +2937,14 @@ function buildSocketedRoute(options) {
2909
2937
  toRoomsRef: describeObjectReference(toRooms)
2910
2938
  }
2911
2939
  });
2912
- const next = roomsFromData(endpointDataRef.current, endpointArgs, toRooms);
2940
+ const next = roomsFromData(
2941
+ endpointDataRef.current,
2942
+ endpointArgs,
2943
+ toRooms,
2944
+ toRoomsMeta
2945
+ );
2913
2946
  setRoomState((prev) => roomStateEqual(prev, next) ? prev : next);
2914
- }, [argsKey, toRooms, debug]);
2947
+ }, [argsKey, toRooms, toRoomsMeta, debug]);
2915
2948
  (0, import_react5.useEffect)(() => {
2916
2949
  trackHookTrigger2({
2917
2950
  ref: joinRoomsEffectDebugRef,
@@ -3029,7 +3062,10 @@ function buildSocketedRoute(options) {
3029
3062
  prev,
3030
3063
  payload: nextUpdate.payload,
3031
3064
  args: endpointArgs,
3032
- meta: nextUpdate.meta ?? {}
3065
+ meta: {
3066
+ ...nextUpdate.meta ?? {},
3067
+ appContext: toRoomsMetaRef.current.appContext
3068
+ }
3033
3069
  });
3034
3070
  if (next === null) return prev;
3035
3071
  if (shouldWarnSocketMutationGuard() && isSameObjectReference(prev, next) && !sameRefWarnedEvents.has(nextUpdate.event)) {
@@ -3041,7 +3077,8 @@ function buildSocketedRoute(options) {
3041
3077
  const nextRoomState = roomsFromData(
3042
3078
  next,
3043
3079
  endpointArgs,
3044
- toRooms
3080
+ toRooms,
3081
+ toRoomsMetaRef.current
3045
3082
  );
3046
3083
  setRoomState(
3047
3084
  (prevRoomState) => roomStateEqual(prevRoomState, nextRoomState) ? prevRoomState : nextRoomState