@emeryld/rrroutes-client 2.6.5 → 2.6.7
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 +49 -3
- package/dist/index.cjs +227 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +220 -24
- package/dist/index.mjs.map +1 -1
- package/dist/routesV3.client.d.ts +1 -1
- package/dist/routesV3.client.types.d.ts +76 -0
- package/dist/sockets/socket.client.context.provider.d.ts +17 -1
- package/dist/sockets/socket.client.core.d.ts +14 -1
- package/dist/sockets/socket.client.sys.d.ts +9 -1
- package/dist/sockets/socketedRoute/socket.client.helper.route.d.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
Summary:
|
|
3
3
|
- Added comprehensive usage for `createRouteClient`, built endpoints (GET/feeds/mutations), cache helpers, invalidation, debug modes, custom fetchers, and React Query integration.
|
|
4
|
-
- Added new sections for router helpers, infinite/feeds, FormData uploads, and socket utilities (SocketClient, provider hooks, socketed routes).
|
|
4
|
+
- Added new sections for router helpers, batched branches (`buildBranch`), infinite/feeds, FormData uploads, and socket utilities (SocketClient, provider hooks, socketed routes).
|
|
5
5
|
- Removed the sparse README and outdated publishing script focus; future additions should cover server-side Socket.IO envelope expectations and testing recipes for hooks.
|
|
6
6
|
-->
|
|
7
7
|
|
|
@@ -220,7 +220,53 @@ const listUsers = buildRoute('listUsers') // builds from routes.listUsers
|
|
|
220
220
|
const updateUser = buildRoute('updateUser', {}, { name: 'profile' }) // debug name filtering
|
|
221
221
|
```
|
|
222
222
|
|
|
223
|
-
### 8)
|
|
223
|
+
### 8) Batch multiple built endpoints (`buildBranch`)
|
|
224
|
+
|
|
225
|
+
`buildBranch` lets you batch already-built endpoints behind one batch path.
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
const getUser = client.build(registry.byKey['GET /v1/users/:userId'])
|
|
229
|
+
const updateUser = client.build(registry.byKey['PATCH /v1/users/:userId'])
|
|
230
|
+
|
|
231
|
+
const userBatch = client.buildBranch(
|
|
232
|
+
{ getUser, updateUser },
|
|
233
|
+
{ path: '/v1/batch', method: 'post' }, // method defaults to POST
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
const result = await userBatch.fetch({
|
|
237
|
+
getUser: {
|
|
238
|
+
args: { params: { userId: 'u_1' } },
|
|
239
|
+
},
|
|
240
|
+
updateUser: {
|
|
241
|
+
args: { params: { userId: 'u_1' } },
|
|
242
|
+
body: { name: 'Emery' }, // required for mutation leaves
|
|
243
|
+
},
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
// result keys map back to your aliases:
|
|
247
|
+
// { getUser: ..., updateUser: ... }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The request body sent to `/v1/batch` is keyed by URL-encoded leaf keys:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
{
|
|
254
|
+
[encodeURIComponent('GET /v1/users/:userId')]: { params: { userId: 'u_1' } },
|
|
255
|
+
[encodeURIComponent('PATCH /v1/users/:userId')]: {
|
|
256
|
+
params: { userId: 'u_1' },
|
|
257
|
+
body: { name: 'Emery' },
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`buildBranch` also provides:
|
|
263
|
+
|
|
264
|
+
- `useEndpoint(input, options?)` for a single React Query hook over the batched response.
|
|
265
|
+
- `getQueryKeys(input?)` to derive per-alias keys.
|
|
266
|
+
- `invalidate(input?)` to invalidate each leaf alias exactly.
|
|
267
|
+
- `setData(input)` to write cache per alias.
|
|
268
|
+
|
|
269
|
+
### 9) File uploads (FormData)
|
|
224
270
|
|
|
225
271
|
If a leaf has `bodyFiles` set in its contract, the client automatically converts the body to `FormData`.
|
|
226
272
|
For each declared file field name, pass files using `file${name}` in the input body.
|
|
@@ -251,7 +297,7 @@ await uploadAvatar.fetch(
|
|
|
251
297
|
)
|
|
252
298
|
```
|
|
253
299
|
|
|
254
|
-
###
|
|
300
|
+
### 10) Debug logging
|
|
255
301
|
|
|
256
302
|
```ts
|
|
257
303
|
const client = createRouteClient({
|
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,11 @@ __export(index_exports, {
|
|
|
44
44
|
});
|
|
45
45
|
module.exports = __toCommonJS(index_exports);
|
|
46
46
|
|
|
47
|
+
// src/routesV3.client.ts
|
|
48
|
+
var import_rrroutes_contract5 = require("@emeryld/rrroutes-contract");
|
|
49
|
+
var import_react_query4 = require("@tanstack/react-query");
|
|
50
|
+
var import_react4 = require("react");
|
|
51
|
+
|
|
47
52
|
// src/routesV3.client.fetch.ts
|
|
48
53
|
var HttpError = class extends Error {
|
|
49
54
|
constructor({
|
|
@@ -1131,6 +1136,7 @@ function buildMutationLeaf(leaf, rqOpts, env) {
|
|
|
1131
1136
|
}
|
|
1132
1137
|
|
|
1133
1138
|
// src/routesV3.client.ts
|
|
1139
|
+
var BUILT_LEAF_META = "__rrroutesLeaf";
|
|
1134
1140
|
var defaultDebugLogger = (event) => {
|
|
1135
1141
|
if (typeof console === "undefined") return;
|
|
1136
1142
|
const fn = console.debug ?? console.log;
|
|
@@ -1197,6 +1203,7 @@ function createRouteClient(opts) {
|
|
|
1197
1203
|
const fetcher = opts.fetcher ?? defaultFetcher;
|
|
1198
1204
|
const baseUrl = opts.baseUrl;
|
|
1199
1205
|
const environment = opts.environment ?? void 0;
|
|
1206
|
+
const validateResponses = opts.validateResponses ?? true;
|
|
1200
1207
|
const { emit: emitDebug, mode: debugMode } = createDebugEmitter(
|
|
1201
1208
|
opts.debug,
|
|
1202
1209
|
environment
|
|
@@ -1211,13 +1218,23 @@ function createRouteClient(opts) {
|
|
|
1211
1218
|
await queryClient.invalidateQueries({ queryKey, exact });
|
|
1212
1219
|
emitDebug({ type: "invalidate", key: queryKey, exact });
|
|
1213
1220
|
}
|
|
1221
|
+
const toArgsTuple2 = (args) => typeof args === "undefined" ? [] : [args];
|
|
1222
|
+
const getBuiltLeaf = (built) => {
|
|
1223
|
+
const leaf = built[BUILT_LEAF_META];
|
|
1224
|
+
if (!leaf) {
|
|
1225
|
+
throw new Error(
|
|
1226
|
+
"buildBranch(...) expects endpoints created with this route client via client.build(...)."
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
return leaf;
|
|
1230
|
+
};
|
|
1231
|
+
const encodeLeafKey = (leaf) => encodeURIComponent(`${leaf.method.toUpperCase()} ${leaf.path}`);
|
|
1214
1232
|
function buildInternal(leaf, rqOpts, meta) {
|
|
1215
1233
|
const leafLabel = `${leaf.method.toUpperCase()} ${String(leaf.path)}`;
|
|
1216
1234
|
const debugName = meta?.name;
|
|
1217
1235
|
const emit = (event) => emitDebug(event, debugName);
|
|
1218
1236
|
const isGet = leaf.method === "get";
|
|
1219
1237
|
const isFeed = !!leaf.cfg.feed;
|
|
1220
|
-
const validateResponses = opts.validateResponses ?? true;
|
|
1221
1238
|
const env = {
|
|
1222
1239
|
baseUrl,
|
|
1223
1240
|
validateResponses,
|
|
@@ -1228,25 +1245,33 @@ function createRouteClient(opts) {
|
|
|
1228
1245
|
isVerboseDebug,
|
|
1229
1246
|
leafLabel
|
|
1230
1247
|
};
|
|
1248
|
+
let built;
|
|
1231
1249
|
if (isGet && isFeed) {
|
|
1232
|
-
|
|
1250
|
+
built = buildInfiniteGetLeaf(
|
|
1233
1251
|
leaf,
|
|
1234
1252
|
rqOpts,
|
|
1235
1253
|
env
|
|
1236
1254
|
);
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1255
|
+
} else if (isGet) {
|
|
1256
|
+
built = buildGetLeaf(
|
|
1257
|
+
leaf,
|
|
1258
|
+
rqOpts,
|
|
1259
|
+
env
|
|
1260
|
+
);
|
|
1261
|
+
} else {
|
|
1262
|
+
built = buildMutationLeaf(
|
|
1240
1263
|
leaf,
|
|
1241
1264
|
rqOpts,
|
|
1242
1265
|
env
|
|
1243
1266
|
);
|
|
1244
1267
|
}
|
|
1245
|
-
|
|
1246
|
-
leaf,
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1268
|
+
Object.defineProperty(built, BUILT_LEAF_META, {
|
|
1269
|
+
value: leaf,
|
|
1270
|
+
enumerable: false,
|
|
1271
|
+
configurable: false,
|
|
1272
|
+
writable: false
|
|
1273
|
+
});
|
|
1274
|
+
return built;
|
|
1250
1275
|
}
|
|
1251
1276
|
const fetchRaw = async (input) => {
|
|
1252
1277
|
const { path, method, query, body, params } = input;
|
|
@@ -1315,11 +1340,151 @@ function createRouteClient(opts) {
|
|
|
1315
1340
|
throw error;
|
|
1316
1341
|
}
|
|
1317
1342
|
};
|
|
1343
|
+
const buildBranchInternal = (leaves, options) => {
|
|
1344
|
+
const batchMethod = options.method ?? "POST";
|
|
1345
|
+
const defaultHeaders = options.headers;
|
|
1346
|
+
const getQueryKeys = (input) => {
|
|
1347
|
+
const out = {};
|
|
1348
|
+
const argsByLeaf = input ?? {};
|
|
1349
|
+
for (const [alias, built] of Object.entries(leaves)) {
|
|
1350
|
+
const args = argsByLeaf[alias];
|
|
1351
|
+
out[alias] = built.getQueryKeys(...toArgsTuple2(args));
|
|
1352
|
+
}
|
|
1353
|
+
return out;
|
|
1354
|
+
};
|
|
1355
|
+
const invalidateBranch = async (input) => {
|
|
1356
|
+
const argsByLeaf = input ?? {};
|
|
1357
|
+
await Promise.all(
|
|
1358
|
+
Object.entries(leaves).map(([alias, built]) => {
|
|
1359
|
+
const args = argsByLeaf[alias];
|
|
1360
|
+
return built.invalidate(...toArgsTuple2(args));
|
|
1361
|
+
})
|
|
1362
|
+
);
|
|
1363
|
+
};
|
|
1364
|
+
const setDataBranch = (input) => {
|
|
1365
|
+
const out = {};
|
|
1366
|
+
for (const [alias, def] of Object.entries(input)) {
|
|
1367
|
+
if (!def) continue;
|
|
1368
|
+
const built = leaves[alias];
|
|
1369
|
+
if (!built) continue;
|
|
1370
|
+
out[alias] = built.setData(
|
|
1371
|
+
def.updater,
|
|
1372
|
+
...toArgsTuple2(def.args)
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
return out;
|
|
1376
|
+
};
|
|
1377
|
+
const fetchBranch = async (input) => {
|
|
1378
|
+
const payload = {};
|
|
1379
|
+
const keyByAlias = /* @__PURE__ */ new Map();
|
|
1380
|
+
for (const [aliasRaw, built] of Object.entries(leaves)) {
|
|
1381
|
+
const alias = aliasRaw;
|
|
1382
|
+
const leaf = getBuiltLeaf(built);
|
|
1383
|
+
const encodedLeaf = encodeLeafKey(leaf);
|
|
1384
|
+
keyByAlias.set(alias, encodedLeaf);
|
|
1385
|
+
const branchInput = input[alias];
|
|
1386
|
+
const args = branchInput?.args;
|
|
1387
|
+
const body = branchInput?.body;
|
|
1388
|
+
payload[encodedLeaf] = {
|
|
1389
|
+
...args?.params !== void 0 ? { params: args.params } : {},
|
|
1390
|
+
...args?.query !== void 0 ? { query: args.query } : {},
|
|
1391
|
+
...body !== void 0 ? { body } : {}
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
const batchResponse = await fetchRaw({
|
|
1395
|
+
path: options.path,
|
|
1396
|
+
method: batchMethod,
|
|
1397
|
+
body: payload,
|
|
1398
|
+
headers: defaultHeaders
|
|
1399
|
+
});
|
|
1400
|
+
const rawData = batchResponse.data;
|
|
1401
|
+
if (!rawData || typeof rawData !== "object" || Array.isArray(rawData)) {
|
|
1402
|
+
throw new Error(
|
|
1403
|
+
"Batch response must be a plain object keyed by encoded route keys."
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
const mapped = {};
|
|
1407
|
+
for (const [aliasRaw, built] of Object.entries(leaves)) {
|
|
1408
|
+
const alias = aliasRaw;
|
|
1409
|
+
const encodedLeaf = keyByAlias.get(alias);
|
|
1410
|
+
if (!encodedLeaf) {
|
|
1411
|
+
throw new Error(
|
|
1412
|
+
`Internal batch error: missing encoded key for alias "${String(alias)}".`
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
if (!(encodedLeaf in rawData)) {
|
|
1416
|
+
throw new Error(`Batch response missing key "${encodedLeaf}".`);
|
|
1417
|
+
}
|
|
1418
|
+
const leaf = getBuiltLeaf(built);
|
|
1419
|
+
const rawLeafData = rawData[encodedLeaf];
|
|
1420
|
+
const parsedLeafData = validateResponses && leaf.cfg.outputSchema ? (0, import_rrroutes_contract5.lowProfileParse)(leaf.cfg.outputSchema, rawLeafData) : rawLeafData;
|
|
1421
|
+
if (validateResponses && !leaf.cfg.outputSchema) {
|
|
1422
|
+
throw new Error(
|
|
1423
|
+
`No output schema defined for leaf ${leaf.method.toUpperCase()} ${leaf.path}, cannot validate batch response.`
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
;
|
|
1427
|
+
mapped[aliasRaw] = parsedLeafData;
|
|
1428
|
+
}
|
|
1429
|
+
return mapped;
|
|
1430
|
+
};
|
|
1431
|
+
const useEndpoint = (input, rqOpts) => {
|
|
1432
|
+
const queryKeys = getQueryKeys(input);
|
|
1433
|
+
const branchQueryKey = [
|
|
1434
|
+
"batch",
|
|
1435
|
+
String(batchMethod).toLowerCase(),
|
|
1436
|
+
options.path,
|
|
1437
|
+
queryKeys
|
|
1438
|
+
];
|
|
1439
|
+
const { onReceive, ...useQueryOptions } = rqOpts ?? {};
|
|
1440
|
+
const listenersRef = (0, import_react4.useRef)(
|
|
1441
|
+
/* @__PURE__ */ new Set()
|
|
1442
|
+
);
|
|
1443
|
+
const notifyOnReceive = (0, import_react4.useCallback)(
|
|
1444
|
+
(data) => {
|
|
1445
|
+
onReceive?.(data);
|
|
1446
|
+
listenersRef.current.forEach((listener) => listener(data));
|
|
1447
|
+
},
|
|
1448
|
+
[onReceive]
|
|
1449
|
+
);
|
|
1450
|
+
const registerOnReceive = (0, import_react4.useCallback)(
|
|
1451
|
+
(listener) => {
|
|
1452
|
+
listenersRef.current.add(listener);
|
|
1453
|
+
return () => {
|
|
1454
|
+
listenersRef.current.delete(listener);
|
|
1455
|
+
};
|
|
1456
|
+
},
|
|
1457
|
+
[]
|
|
1458
|
+
);
|
|
1459
|
+
const queryResult = (0, import_react_query4.useQuery)(
|
|
1460
|
+
{
|
|
1461
|
+
...useQueryOptions,
|
|
1462
|
+
queryKey: branchQueryKey,
|
|
1463
|
+
placeholderData: useQueryOptions.placeholderData ?? import_react_query4.keepPreviousData,
|
|
1464
|
+
queryFn: async () => {
|
|
1465
|
+
const result = await fetchBranch(input);
|
|
1466
|
+
notifyOnReceive(result);
|
|
1467
|
+
return result;
|
|
1468
|
+
}
|
|
1469
|
+
},
|
|
1470
|
+
queryClient
|
|
1471
|
+
);
|
|
1472
|
+
return { ...queryResult, onReceive: registerOnReceive };
|
|
1473
|
+
};
|
|
1474
|
+
return {
|
|
1475
|
+
fetch: fetchBranch,
|
|
1476
|
+
useEndpoint,
|
|
1477
|
+
getQueryKeys,
|
|
1478
|
+
invalidate: invalidateBranch,
|
|
1479
|
+
setData: setDataBranch
|
|
1480
|
+
};
|
|
1481
|
+
};
|
|
1318
1482
|
return {
|
|
1319
1483
|
queryClient,
|
|
1320
1484
|
invalidate,
|
|
1321
1485
|
fetch: fetchRaw,
|
|
1322
|
-
build: buildInternal
|
|
1486
|
+
build: buildInternal,
|
|
1487
|
+
buildBranch: buildBranchInternal
|
|
1323
1488
|
};
|
|
1324
1489
|
}
|
|
1325
1490
|
function buildRouter(routeClient, routes) {
|
|
@@ -2163,26 +2328,48 @@ function useSocketConnection(args) {
|
|
|
2163
2328
|
() => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms],
|
|
2164
2329
|
[rooms]
|
|
2165
2330
|
);
|
|
2331
|
+
const reportAsyncError = React2.useCallback(
|
|
2332
|
+
(phase, error) => {
|
|
2333
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
2334
|
+
console.warn(`[socket] useSocketConnection ${phase} failed`, error);
|
|
2335
|
+
}
|
|
2336
|
+
},
|
|
2337
|
+
[]
|
|
2338
|
+
);
|
|
2166
2339
|
React2.useEffect(() => {
|
|
2167
2340
|
if (autoJoin && normalizedRooms.length > 0)
|
|
2168
|
-
client.joinRooms(normalizedRooms, args.joinMeta);
|
|
2341
|
+
void client.joinRooms(normalizedRooms, args.joinMeta).catch((error) => reportAsyncError("joinRooms", error));
|
|
2169
2342
|
const unsubscribe = client.on(event, (payload, meta) => {
|
|
2170
2343
|
onMessage(payload, meta);
|
|
2171
2344
|
});
|
|
2172
2345
|
return () => {
|
|
2173
2346
|
unsubscribe();
|
|
2174
2347
|
if (autoLeave && normalizedRooms.length > 0)
|
|
2175
|
-
client.leaveRooms(normalizedRooms, args.leaveMeta);
|
|
2348
|
+
void client.leaveRooms(normalizedRooms, args.leaveMeta).catch((error) => reportAsyncError("leaveRooms", error));
|
|
2176
2349
|
if (onCleanup) onCleanup();
|
|
2177
2350
|
};
|
|
2178
|
-
}, [
|
|
2351
|
+
}, [
|
|
2352
|
+
client,
|
|
2353
|
+
event,
|
|
2354
|
+
onMessage,
|
|
2355
|
+
autoJoin,
|
|
2356
|
+
autoLeave,
|
|
2357
|
+
reportAsyncError,
|
|
2358
|
+
...normalizedRooms
|
|
2359
|
+
]);
|
|
2179
2360
|
}
|
|
2180
2361
|
|
|
2181
2362
|
// src/sockets/socket.client.context.debug.ts
|
|
2182
2363
|
function dbg(dbgOpts, e) {
|
|
2183
2364
|
if (!dbgOpts?.logger) return;
|
|
2184
2365
|
if (!dbgOpts[e.type]) return;
|
|
2185
|
-
|
|
2366
|
+
try {
|
|
2367
|
+
dbgOpts.logger(e);
|
|
2368
|
+
} catch (error) {
|
|
2369
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
2370
|
+
console.warn("[socket] provider debug logger threw", error);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2186
2373
|
}
|
|
2187
2374
|
function isProbablySocket(value) {
|
|
2188
2375
|
if (!value || typeof value !== "object") return false;
|
|
@@ -2399,8 +2586,15 @@ function SocketProvider(props) {
|
|
|
2399
2586
|
});
|
|
2400
2587
|
return () => {
|
|
2401
2588
|
if (client) {
|
|
2402
|
-
client.destroy(destroyLeaveMetaRef.current)
|
|
2403
|
-
|
|
2589
|
+
void Promise.resolve(client.destroy(destroyLeaveMetaRef.current)).then(() => {
|
|
2590
|
+
dbg(providerDebugRef.current, { type: "client", phase: "destroy" });
|
|
2591
|
+
}).catch((error) => {
|
|
2592
|
+
dbg(providerDebugRef.current, {
|
|
2593
|
+
type: "resolve",
|
|
2594
|
+
phase: "error",
|
|
2595
|
+
err: `client.destroy failed: ${String(error)}`
|
|
2596
|
+
});
|
|
2597
|
+
});
|
|
2404
2598
|
}
|
|
2405
2599
|
};
|
|
2406
2600
|
}, [client]);
|
|
@@ -2409,7 +2603,7 @@ function SocketProvider(props) {
|
|
|
2409
2603
|
}
|
|
2410
2604
|
|
|
2411
2605
|
// src/sockets/socketedRoute/socket.client.helper.route.ts
|
|
2412
|
-
var
|
|
2606
|
+
var import_react5 = require("react");
|
|
2413
2607
|
|
|
2414
2608
|
// src/sockets/socketedRoute/socket.client.helper.debug.ts
|
|
2415
2609
|
var objectReferenceIds = /* @__PURE__ */ new WeakMap();
|
|
@@ -2577,23 +2771,23 @@ function buildSocketedRoute(options) {
|
|
|
2577
2771
|
const endpointResult = useInnerEndpoint(
|
|
2578
2772
|
...useArgs
|
|
2579
2773
|
);
|
|
2580
|
-
const argsKey = (0,
|
|
2581
|
-
const [roomState, setRoomState] = (0,
|
|
2774
|
+
const argsKey = (0, import_react5.useMemo)(() => safeJsonKey(useArgs[0] ?? null), [useArgs]);
|
|
2775
|
+
const [roomState, setRoomState] = (0, import_react5.useState)(
|
|
2582
2776
|
() => roomsFromData(endpointResult.data, toRooms)
|
|
2583
2777
|
);
|
|
2584
|
-
const renderCountRef = (0,
|
|
2585
|
-
const clientReadyRef = (0,
|
|
2586
|
-
const onReceiveEffectDebugRef = (0,
|
|
2587
|
-
const deriveRoomsEffectDebugRef = (0,
|
|
2588
|
-
const joinRoomsEffectDebugRef = (0,
|
|
2589
|
-
const applySocketEffectDebugRef = (0,
|
|
2778
|
+
const renderCountRef = (0, import_react5.useRef)(0);
|
|
2779
|
+
const clientReadyRef = (0, import_react5.useRef)(null);
|
|
2780
|
+
const onReceiveEffectDebugRef = (0, import_react5.useRef)(null);
|
|
2781
|
+
const deriveRoomsEffectDebugRef = (0, import_react5.useRef)(null);
|
|
2782
|
+
const joinRoomsEffectDebugRef = (0, import_react5.useRef)(null);
|
|
2783
|
+
const applySocketEffectDebugRef = (0, import_react5.useRef)(null);
|
|
2590
2784
|
renderCountRef.current += 1;
|
|
2591
|
-
const roomsKey = (0,
|
|
2592
|
-
const joinMetaKey = (0,
|
|
2785
|
+
const roomsKey = (0, import_react5.useMemo)(() => roomState.rooms.join("|"), [roomState.rooms]);
|
|
2786
|
+
const joinMetaKey = (0, import_react5.useMemo)(
|
|
2593
2787
|
() => safeJsonKey(roomState.joinMeta ?? null),
|
|
2594
2788
|
[roomState.joinMeta]
|
|
2595
2789
|
);
|
|
2596
|
-
const leaveMetaKey = (0,
|
|
2790
|
+
const leaveMetaKey = (0, import_react5.useMemo)(
|
|
2597
2791
|
() => safeJsonKey(roomState.leaveMeta ?? null),
|
|
2598
2792
|
[roomState.leaveMeta]
|
|
2599
2793
|
);
|
|
@@ -2616,7 +2810,7 @@ function buildSocketedRoute(options) {
|
|
|
2616
2810
|
joinMetaKey,
|
|
2617
2811
|
leaveMetaKey
|
|
2618
2812
|
});
|
|
2619
|
-
(0,
|
|
2813
|
+
(0, import_react5.useEffect)(() => {
|
|
2620
2814
|
trackHookTrigger2({
|
|
2621
2815
|
ref: onReceiveEffectDebugRef,
|
|
2622
2816
|
phase: "endpoint_on_receive_effect",
|
|
@@ -2635,7 +2829,7 @@ function buildSocketedRoute(options) {
|
|
|
2635
2829
|
});
|
|
2636
2830
|
return unsubscribe;
|
|
2637
2831
|
}, [endpointResult, toRooms, debug]);
|
|
2638
|
-
(0,
|
|
2832
|
+
(0, import_react5.useEffect)(() => {
|
|
2639
2833
|
trackHookTrigger2({
|
|
2640
2834
|
ref: deriveRoomsEffectDebugRef,
|
|
2641
2835
|
phase: "derive_rooms_effect",
|
|
@@ -2651,7 +2845,7 @@ function buildSocketedRoute(options) {
|
|
|
2651
2845
|
);
|
|
2652
2846
|
setRoomState((prev) => roomStateEqual(prev, next) ? prev : next);
|
|
2653
2847
|
}, [endpointResult.data, toRooms, debug]);
|
|
2654
|
-
(0,
|
|
2848
|
+
(0, import_react5.useEffect)(() => {
|
|
2655
2849
|
trackHookTrigger2({
|
|
2656
2850
|
ref: joinRoomsEffectDebugRef,
|
|
2657
2851
|
phase: "join_rooms_effect",
|
|
@@ -2737,7 +2931,7 @@ function buildSocketedRoute(options) {
|
|
|
2737
2931
|
});
|
|
2738
2932
|
};
|
|
2739
2933
|
}, [client, roomsKey, joinMetaKey, leaveMetaKey, debug]);
|
|
2740
|
-
(0,
|
|
2934
|
+
(0, import_react5.useEffect)(() => {
|
|
2741
2935
|
trackHookTrigger2({
|
|
2742
2936
|
ref: applySocketEffectDebugRef,
|
|
2743
2937
|
phase: "apply_socket_effect",
|