@emeryld/rrroutes-client 2.1.11 → 2.2.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.
@@ -1,7 +1,7 @@
1
1
  import type { InfiniteData, QueryClient, QueryKey, UseInfiniteQueryOptions, UseInfiniteQueryResult, UseMutationOptions, UseMutationResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
2
2
  import type { AnyLeaf, HttpMethod, InferBody, InferOutput, InferParams, InferQuery, Prettify } from '@emeryld/rrroutes-contract';
3
3
  /** Helper type used when setting React Query cache data. */
4
- export type Updater<T> = T | ((prev: T | undefined) => T);
4
+ export type Updater<T> = T | ((prev: T | undefined) => T | undefined) | undefined;
5
5
  /** Cursor string extracted from paginated endpoints. */
6
6
  export type Cursor = string | undefined;
7
7
  /** Runtime request details consumed by a `Fetcher` implementation. */
@@ -164,7 +164,7 @@ export type BuildOptionsFor<L extends AnyLeaf> = L['method'] extends 'get' ? L['
164
164
  type UseEndpointOptionsFor<L extends AnyLeaf> = {
165
165
  onReceive?: OnReceive<L>;
166
166
  };
167
- type UseEndpointArgs<L extends AnyLeaf, O> = keyof ArgsFor<L> extends never ? [options?: O] : [args: ArgsFor<L>, options?: O];
167
+ export type UseEndpointArgs<L extends AnyLeaf, O> = keyof ArgsFor<L> extends never ? [options?: O] : [args: ArgsFor<L>, options?: O];
168
168
  export type QueryUseEndpointOptionsFor<L extends AnyLeaf> = UseEndpointOptionsFor<L>;
169
169
  export type InfiniteUseEndpointOptionsFor<L extends AnyLeaf> = UseEndpointOptionsFor<L>;
170
170
  export type MutationUseEndpointOptionsFor<L extends AnyLeaf> = UseEndpointOptionsFor<L>;
@@ -64,7 +64,6 @@ export type UseSocketConnectionArgs<T extends EventMap, K extends keyof T & stri
64
64
  onCleanup?: () => void;
65
65
  autoJoin?: boolean;
66
66
  autoLeave?: boolean;
67
- deps?: React.DependencyList;
68
67
  joinMeta: SocketSchemaOutput<C['joinMetaMessage']>;
69
68
  leaveMeta: SocketSchemaOutput<C['leaveMetaMessage']>;
70
69
  };
@@ -99,7 +99,7 @@ export declare class SocketClient<T extends EventMap, C extends SocketConnection
99
99
  */
100
100
  stopHeartbeat(reason?: string): void;
101
101
  emit<K extends keyof T & string>(event: K, payload: Payload<T, K>, metadata?: Record<string, unknown>): void;
102
- joinRooms(rooms: string[] | string, meta: SocketSchemaOutput<C['joinMetaMessage']>): Promise<void>;
102
+ joinRooms(rooms: string[] | string, meta: SocketSchemaOutput<C['joinMetaMessage']>): Promise<() => Promise<void>>;
103
103
  leaveRooms(rooms: string[] | string, meta: SocketSchemaOutput<C['leaveMetaMessage']>): Promise<void>;
104
104
  on<K extends keyof T & string>(event: K, handler: (payload: Payload<T, K>, meta: {
105
105
  envelope: ServerEnvelope<T, K>;
@@ -116,3 +116,4 @@ export declare class SocketClient<T extends EventMap, C extends SocketConnection
116
116
  }
117
117
  export * from './socket.client.context';
118
118
  export * from './socket.client.sys';
119
+ export * from './socketedRoute/socket.client.helper';
@@ -0,0 +1,52 @@
1
+ import type { AnyLeaf, InferOutput, EventMap as ContractEventMap, SocketConnectionConfig, SocketSchemaOutput, Payload } from '@emeryld/rrroutes-contract';
2
+ import type { BuildMeta, BuildOptionsFor, ArgsFor, DataShape, InfiniteUseEndpointOptionsFor, RouterBuilder } from '../../routesV3.client.types';
3
+ import type { ClientCtx, ServerEnvelope, SocketClient } from '../socket.client.index';
4
+ /** Narrow to feed-style GET leaves so `data.pages` is always present. */
5
+ type FeedLeaf = AnyLeaf & {
6
+ method: 'get';
7
+ cfg: {
8
+ feed: true;
9
+ };
10
+ };
11
+ type PageOf<L extends FeedLeaf> = InferOutput<L>;
12
+ type SocketedHandlers<L extends FeedLeaf, E extends ContractEventMap, K extends keyof E & string, C extends SocketConnectionConfig> = {
13
+ /**
14
+ * Derive the full set of rooms to join based on a newly received page plus
15
+ * the current active room list. Return the complete desired list (not a delta).
16
+ */
17
+ onReceiveRooms?: (page: PageOf<L>, activeRooms: string[]) => string[];
18
+ /**
19
+ * Update the cached route data when a socket message arrives.
20
+ * Return the next cache value (or undefined to keep it unchanged).
21
+ */
22
+ handleMessage: (prev: DataShape<L> | undefined, payload: Payload<E, K>, meta: {
23
+ envelope: ServerEnvelope<E, K>;
24
+ ctx: ClientCtx;
25
+ }) => DataShape<L> | undefined;
26
+ /** Meta payloads for join/leave messages. */
27
+ joinMeta: SocketSchemaOutput<C['joinMetaMessage']>;
28
+ leaveMeta: SocketSchemaOutput<C['leaveMetaMessage']>;
29
+ };
30
+ /**
31
+ * Build a hook that wires an infinite GET route to a socket event:
32
+ * - Keeps React Query cache in sync when socket messages arrive.
33
+ * - Derives and joins rooms from the route’s feed pages.
34
+ */
35
+ export declare function createSocketedRouteHook<Routes extends Record<PropertyKey, FeedLeaf>, Names extends string, Events extends ContractEventMap, C extends SocketConnectionConfig>(args: {
36
+ buildRoute: RouterBuilder<Routes, Names>;
37
+ useClient?: () => SocketClient<Events, C>;
38
+ }): <K extends keyof Routes, Ev extends keyof Events & string>(params: {
39
+ routeKey: K;
40
+ socketEvent: Ev;
41
+ handlers: SocketedHandlers<Routes[K], Events, Ev, C>;
42
+ buildOptions?: BuildOptionsFor<Routes[K]>;
43
+ buildMeta?: BuildMeta<Names>;
44
+ useOptions?: {
45
+ args?: ArgsFor<Routes[K]>;
46
+ options?: InfiniteUseEndpointOptionsFor<Routes[K]>;
47
+ };
48
+ }) => {
49
+ data: import("@tanstack/react-query").InfiniteData<InferOutput<Routes[K]>, unknown> | undefined;
50
+ rooms: string[];
51
+ };
52
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emeryld/rrroutes-client",
3
- "version": "2.1.11",
3
+ "version": "2.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",