@emeryld/rrroutes-client 2.6.6 → 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/dist/index.mjs CHANGED
@@ -1,5 +1,12 @@
1
1
  "use client";
2
2
 
3
+ // src/routesV3.client.ts
4
+ import {
5
+ lowProfileParse as lowProfileParse5
6
+ } from "@emeryld/rrroutes-contract";
7
+ import { keepPreviousData as keepPreviousData3, useQuery as useQuery2 } from "@tanstack/react-query";
8
+ import { useCallback as useCallback4, useRef as useRef4 } from "react";
9
+
3
10
  // src/routesV3.client.fetch.ts
4
11
  var HttpError = class extends Error {
5
12
  constructor({
@@ -1095,6 +1102,7 @@ function buildMutationLeaf(leaf, rqOpts, env) {
1095
1102
  }
1096
1103
 
1097
1104
  // src/routesV3.client.ts
1105
+ var BUILT_LEAF_META = "__rrroutesLeaf";
1098
1106
  var defaultDebugLogger = (event) => {
1099
1107
  if (typeof console === "undefined") return;
1100
1108
  const fn = console.debug ?? console.log;
@@ -1161,6 +1169,7 @@ function createRouteClient(opts) {
1161
1169
  const fetcher = opts.fetcher ?? defaultFetcher;
1162
1170
  const baseUrl = opts.baseUrl;
1163
1171
  const environment = opts.environment ?? void 0;
1172
+ const validateResponses = opts.validateResponses ?? true;
1164
1173
  const { emit: emitDebug, mode: debugMode } = createDebugEmitter(
1165
1174
  opts.debug,
1166
1175
  environment
@@ -1175,13 +1184,23 @@ function createRouteClient(opts) {
1175
1184
  await queryClient.invalidateQueries({ queryKey, exact });
1176
1185
  emitDebug({ type: "invalidate", key: queryKey, exact });
1177
1186
  }
1187
+ const toArgsTuple2 = (args) => typeof args === "undefined" ? [] : [args];
1188
+ const getBuiltLeaf = (built) => {
1189
+ const leaf = built[BUILT_LEAF_META];
1190
+ if (!leaf) {
1191
+ throw new Error(
1192
+ "buildBranch(...) expects endpoints created with this route client via client.build(...)."
1193
+ );
1194
+ }
1195
+ return leaf;
1196
+ };
1197
+ const encodeLeafKey = (leaf) => encodeURIComponent(`${leaf.method.toUpperCase()} ${leaf.path}`);
1178
1198
  function buildInternal(leaf, rqOpts, meta) {
1179
1199
  const leafLabel = `${leaf.method.toUpperCase()} ${String(leaf.path)}`;
1180
1200
  const debugName = meta?.name;
1181
1201
  const emit = (event) => emitDebug(event, debugName);
1182
1202
  const isGet = leaf.method === "get";
1183
1203
  const isFeed = !!leaf.cfg.feed;
1184
- const validateResponses = opts.validateResponses ?? true;
1185
1204
  const env = {
1186
1205
  baseUrl,
1187
1206
  validateResponses,
@@ -1192,25 +1211,33 @@ function createRouteClient(opts) {
1192
1211
  isVerboseDebug,
1193
1212
  leafLabel
1194
1213
  };
1214
+ let built;
1195
1215
  if (isGet && isFeed) {
1196
- return buildInfiniteGetLeaf(
1216
+ built = buildInfiniteGetLeaf(
1197
1217
  leaf,
1198
1218
  rqOpts,
1199
1219
  env
1200
1220
  );
1201
- }
1202
- if (isGet) {
1203
- return buildGetLeaf(
1221
+ } else if (isGet) {
1222
+ built = buildGetLeaf(
1223
+ leaf,
1224
+ rqOpts,
1225
+ env
1226
+ );
1227
+ } else {
1228
+ built = buildMutationLeaf(
1204
1229
  leaf,
1205
1230
  rqOpts,
1206
1231
  env
1207
1232
  );
1208
1233
  }
1209
- return buildMutationLeaf(
1210
- leaf,
1211
- rqOpts,
1212
- env
1213
- );
1234
+ Object.defineProperty(built, BUILT_LEAF_META, {
1235
+ value: leaf,
1236
+ enumerable: false,
1237
+ configurable: false,
1238
+ writable: false
1239
+ });
1240
+ return built;
1214
1241
  }
1215
1242
  const fetchRaw = async (input) => {
1216
1243
  const { path, method, query, body, params } = input;
@@ -1279,11 +1306,151 @@ function createRouteClient(opts) {
1279
1306
  throw error;
1280
1307
  }
1281
1308
  };
1309
+ const buildBranchInternal = (leaves, options) => {
1310
+ const batchMethod = options.method ?? "POST";
1311
+ const defaultHeaders = options.headers;
1312
+ const getQueryKeys = (input) => {
1313
+ const out = {};
1314
+ const argsByLeaf = input ?? {};
1315
+ for (const [alias, built] of Object.entries(leaves)) {
1316
+ const args = argsByLeaf[alias];
1317
+ out[alias] = built.getQueryKeys(...toArgsTuple2(args));
1318
+ }
1319
+ return out;
1320
+ };
1321
+ const invalidateBranch = async (input) => {
1322
+ const argsByLeaf = input ?? {};
1323
+ await Promise.all(
1324
+ Object.entries(leaves).map(([alias, built]) => {
1325
+ const args = argsByLeaf[alias];
1326
+ return built.invalidate(...toArgsTuple2(args));
1327
+ })
1328
+ );
1329
+ };
1330
+ const setDataBranch = (input) => {
1331
+ const out = {};
1332
+ for (const [alias, def] of Object.entries(input)) {
1333
+ if (!def) continue;
1334
+ const built = leaves[alias];
1335
+ if (!built) continue;
1336
+ out[alias] = built.setData(
1337
+ def.updater,
1338
+ ...toArgsTuple2(def.args)
1339
+ );
1340
+ }
1341
+ return out;
1342
+ };
1343
+ const fetchBranch = async (input) => {
1344
+ const payload = {};
1345
+ const keyByAlias = /* @__PURE__ */ new Map();
1346
+ for (const [aliasRaw, built] of Object.entries(leaves)) {
1347
+ const alias = aliasRaw;
1348
+ const leaf = getBuiltLeaf(built);
1349
+ const encodedLeaf = encodeLeafKey(leaf);
1350
+ keyByAlias.set(alias, encodedLeaf);
1351
+ const branchInput = input[alias];
1352
+ const args = branchInput?.args;
1353
+ const body = branchInput?.body;
1354
+ payload[encodedLeaf] = {
1355
+ ...args?.params !== void 0 ? { params: args.params } : {},
1356
+ ...args?.query !== void 0 ? { query: args.query } : {},
1357
+ ...body !== void 0 ? { body } : {}
1358
+ };
1359
+ }
1360
+ const batchResponse = await fetchRaw({
1361
+ path: options.path,
1362
+ method: batchMethod,
1363
+ body: payload,
1364
+ headers: defaultHeaders
1365
+ });
1366
+ const rawData = batchResponse.data;
1367
+ if (!rawData || typeof rawData !== "object" || Array.isArray(rawData)) {
1368
+ throw new Error(
1369
+ "Batch response must be a plain object keyed by encoded route keys."
1370
+ );
1371
+ }
1372
+ const mapped = {};
1373
+ for (const [aliasRaw, built] of Object.entries(leaves)) {
1374
+ const alias = aliasRaw;
1375
+ const encodedLeaf = keyByAlias.get(alias);
1376
+ if (!encodedLeaf) {
1377
+ throw new Error(
1378
+ `Internal batch error: missing encoded key for alias "${String(alias)}".`
1379
+ );
1380
+ }
1381
+ if (!(encodedLeaf in rawData)) {
1382
+ throw new Error(`Batch response missing key "${encodedLeaf}".`);
1383
+ }
1384
+ const leaf = getBuiltLeaf(built);
1385
+ const rawLeafData = rawData[encodedLeaf];
1386
+ const parsedLeafData = validateResponses && leaf.cfg.outputSchema ? lowProfileParse5(leaf.cfg.outputSchema, rawLeafData) : rawLeafData;
1387
+ if (validateResponses && !leaf.cfg.outputSchema) {
1388
+ throw new Error(
1389
+ `No output schema defined for leaf ${leaf.method.toUpperCase()} ${leaf.path}, cannot validate batch response.`
1390
+ );
1391
+ }
1392
+ ;
1393
+ mapped[aliasRaw] = parsedLeafData;
1394
+ }
1395
+ return mapped;
1396
+ };
1397
+ const useEndpoint = (input, rqOpts) => {
1398
+ const queryKeys = getQueryKeys(input);
1399
+ const branchQueryKey = [
1400
+ "batch",
1401
+ String(batchMethod).toLowerCase(),
1402
+ options.path,
1403
+ queryKeys
1404
+ ];
1405
+ const { onReceive, ...useQueryOptions } = rqOpts ?? {};
1406
+ const listenersRef = useRef4(
1407
+ /* @__PURE__ */ new Set()
1408
+ );
1409
+ const notifyOnReceive = useCallback4(
1410
+ (data) => {
1411
+ onReceive?.(data);
1412
+ listenersRef.current.forEach((listener) => listener(data));
1413
+ },
1414
+ [onReceive]
1415
+ );
1416
+ const registerOnReceive = useCallback4(
1417
+ (listener) => {
1418
+ listenersRef.current.add(listener);
1419
+ return () => {
1420
+ listenersRef.current.delete(listener);
1421
+ };
1422
+ },
1423
+ []
1424
+ );
1425
+ const queryResult = useQuery2(
1426
+ {
1427
+ ...useQueryOptions,
1428
+ queryKey: branchQueryKey,
1429
+ placeholderData: useQueryOptions.placeholderData ?? keepPreviousData3,
1430
+ queryFn: async () => {
1431
+ const result = await fetchBranch(input);
1432
+ notifyOnReceive(result);
1433
+ return result;
1434
+ }
1435
+ },
1436
+ queryClient
1437
+ );
1438
+ return { ...queryResult, onReceive: registerOnReceive };
1439
+ };
1440
+ return {
1441
+ fetch: fetchBranch,
1442
+ useEndpoint,
1443
+ getQueryKeys,
1444
+ invalidate: invalidateBranch,
1445
+ setData: setDataBranch
1446
+ };
1447
+ };
1282
1448
  return {
1283
1449
  queryClient,
1284
1450
  invalidate,
1285
1451
  fetch: fetchRaw,
1286
- build: buildInternal
1452
+ build: buildInternal,
1453
+ buildBranch: buildBranchInternal
1287
1454
  };
1288
1455
  }
1289
1456
  function buildRouter(routeClient, routes) {
@@ -2402,7 +2569,7 @@ function SocketProvider(props) {
2402
2569
  }
2403
2570
 
2404
2571
  // src/sockets/socketedRoute/socket.client.helper.route.ts
2405
- import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef5, useState as useState2 } from "react";
2572
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef6, useState as useState2 } from "react";
2406
2573
 
2407
2574
  // src/sockets/socketedRoute/socket.client.helper.debug.ts
2408
2575
  var objectReferenceIds = /* @__PURE__ */ new WeakMap();
@@ -2574,12 +2741,12 @@ function buildSocketedRoute(options) {
2574
2741
  const [roomState, setRoomState] = useState2(
2575
2742
  () => roomsFromData(endpointResult.data, toRooms)
2576
2743
  );
2577
- const renderCountRef = useRef5(0);
2578
- const clientReadyRef = useRef5(null);
2579
- const onReceiveEffectDebugRef = useRef5(null);
2580
- const deriveRoomsEffectDebugRef = useRef5(null);
2581
- const joinRoomsEffectDebugRef = useRef5(null);
2582
- const applySocketEffectDebugRef = useRef5(null);
2744
+ const renderCountRef = useRef6(0);
2745
+ const clientReadyRef = useRef6(null);
2746
+ const onReceiveEffectDebugRef = useRef6(null);
2747
+ const deriveRoomsEffectDebugRef = useRef6(null);
2748
+ const joinRoomsEffectDebugRef = useRef6(null);
2749
+ const applySocketEffectDebugRef = useRef6(null);
2583
2750
  renderCountRef.current += 1;
2584
2751
  const roomsKey = useMemo3(() => roomState.rooms.join("|"), [roomState.rooms]);
2585
2752
  const joinMetaKey = useMemo3(