@emeryld/rrroutes-client 2.2.14 → 2.2.16

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
@@ -26,30 +26,29 @@ var defaultFetcher = async (req) => {
26
26
  };
27
27
 
28
28
  // src/routesV3.client.index.ts
29
- import { useCallback, useRef } from "react";
29
+ import {
30
+ buildCacheKey,
31
+ compilePath,
32
+ lowProfileParse
33
+ } from "@emeryld/rrroutes-contract";
30
34
  import {
31
35
  keepPreviousData,
32
36
  useInfiniteQuery,
33
37
  useMutation,
34
38
  useQuery
35
39
  } from "@tanstack/react-query";
40
+ import { useCallback, useRef } from "react";
36
41
  import { z } from "zod";
37
- import {
38
- buildCacheKey,
39
- compilePath
40
- } from "@emeryld/rrroutes-contract";
41
42
  var toUpper = (m) => m.toUpperCase();
42
- var defaultFeedQuerySchema = z.object({
43
- cursor: z.string().optional(),
44
- limit: z.coerce.number().min(1).max(100).default(20)
45
- });
43
+ var paginationQueryShape = {
44
+ pagination_cursor: z.string().optional(),
45
+ pagination_limit: z.coerce.number().min(1).max(100).default(20)
46
+ };
47
+ var defaultFeedQuerySchema = z.object(paginationQueryShape);
46
48
  var defaultFeedOutputSchema = z.object({
47
49
  items: z.array(z.unknown()),
48
50
  nextCursor: z.string().optional()
49
51
  });
50
- function zParse(value, schema) {
51
- return schema ? schema.parse(value) : value;
52
- }
53
52
  function toSearchString(query) {
54
53
  if (!query) return "";
55
54
  const params = new URLSearchParams();
@@ -148,41 +147,53 @@ function extractArgs(args) {
148
147
  function toArgsTuple(args) {
149
148
  return typeof args === "undefined" ? [] : [args];
150
149
  }
150
+ function getZodShape(schema) {
151
+ const shapeOrGetter = schema.shape ? schema.shape : schema._def?.shape?.();
152
+ if (!shapeOrGetter) return {};
153
+ return typeof shapeOrGetter === "function" ? shapeOrGetter.call(schema) : shapeOrGetter;
154
+ }
151
155
  function augmentFeedQuerySchema(schema) {
152
156
  if (!schema) return defaultFeedQuerySchema;
153
- if (schema instanceof z.ZodObject) {
154
- const shape = schema.shape ? schema.shape : schema._def?.shape?.();
155
- return schema.extend({
156
- ...shape ?? {},
157
- cursor: defaultFeedQuerySchema.shape.cursor,
158
- limit: defaultFeedQuerySchema.shape.limit
159
- });
157
+ if (!(schema instanceof z.ZodObject)) {
158
+ console.warn(
159
+ "Feed queries must be a ZodObject; default pagination applied."
160
+ );
161
+ return defaultFeedQuerySchema;
160
162
  }
161
- return z.intersection(schema, defaultFeedQuerySchema);
163
+ return schema.extend(paginationQueryShape);
162
164
  }
163
165
  function augmentFeedOutputSchema(schema) {
164
166
  if (!schema) return defaultFeedOutputSchema;
165
- if (schema instanceof z.ZodObject) {
166
- const shape = schema.shape ? schema.shape : schema._def?.shape?.();
167
- const hasItems = Boolean(shape?.items);
168
- if (hasItems) return schema.extend({ nextCursor: z.string().optional() });
167
+ if (schema instanceof z.ZodArray) {
169
168
  return z.object({
170
- items: z.array(schema),
169
+ items: schema,
171
170
  nextCursor: z.string().optional()
172
171
  });
173
172
  }
174
- if (schema instanceof z.ZodArray) {
173
+ if (schema instanceof z.ZodObject) {
174
+ const shape = getZodShape(schema);
175
+ if (shape?.items) {
176
+ return schema.extend({
177
+ nextCursor: z.string().optional()
178
+ });
179
+ }
175
180
  return z.object({
176
- items: schema,
181
+ items: z.array(schema),
177
182
  nextCursor: z.string().optional()
178
183
  });
179
184
  }
180
- return defaultFeedOutputSchema;
185
+ return z.object({
186
+ items: z.array(schema),
187
+ nextCursor: z.string().optional()
188
+ });
181
189
  }
182
190
  function buildUrl(leaf, baseUrl, params, query) {
183
- const normalizedParams = zParse(params, leaf.cfg.paramsSchema);
184
- const normalizedQuery = zParse(query, leaf.cfg.querySchema);
185
- const path = compilePath(leaf.path, normalizedParams ?? {});
191
+ const normalizedParams = leaf.cfg.paramsSchema ? lowProfileParse(leaf.cfg.paramsSchema, params) : {};
192
+ const normalizedQuery = leaf.cfg.querySchema ? lowProfileParse(leaf.cfg.querySchema, query) : {};
193
+ const path = compilePath(
194
+ leaf.path,
195
+ normalizedParams ?? {}
196
+ );
186
197
  const url = `${baseUrl ?? ""}${path}${toSearchString(normalizedQuery)}`;
187
198
  return { url, normalizedQuery, normalizedParams };
188
199
  }
@@ -190,10 +201,13 @@ function createRouteClient(opts) {
190
201
  const queryClient = opts.queryClient;
191
202
  const fetcher = opts.fetcher ?? defaultFetcher;
192
203
  const baseUrl = opts.baseUrl;
193
- const cursorParam = opts.cursorParam ?? "cursor";
204
+ const cursorParam = opts.cursorParam ?? "pagination_cursor";
194
205
  const getNextCursor = opts.getNextCursor ?? defaultGetNextCursor;
195
206
  const environment = opts.environment ?? void 0;
196
- const { emit: emitDebug, mode: debugMode } = createDebugEmitter(opts.debug, environment);
207
+ const { emit: emitDebug, mode: debugMode } = createDebugEmitter(
208
+ opts.debug,
209
+ environment
210
+ );
197
211
  const isVerboseDebug = debugMode === "complete";
198
212
  const decorateDebugEvent = (event, details) => {
199
213
  if (!isVerboseDebug || !details) return event;
@@ -207,11 +221,12 @@ function createRouteClient(opts) {
207
221
  function buildInternal(leaf, rqOpts, meta) {
208
222
  const isGet = leaf.method === "get";
209
223
  const isFeed = !!leaf.cfg.feed;
224
+ const rawLeafCfg = leaf.cfg;
210
225
  const leafCfg = isFeed ? {
211
- ...leaf.cfg,
212
- querySchema: augmentFeedQuerySchema(leaf.cfg.querySchema),
213
- outputSchema: augmentFeedOutputSchema(leaf.cfg.outputSchema)
214
- } : leaf.cfg;
226
+ ...rawLeafCfg,
227
+ querySchema: augmentFeedQuerySchema(rawLeafCfg.querySchema),
228
+ outputSchema: augmentFeedOutputSchema(rawLeafCfg.outputSchema)
229
+ } : rawLeafCfg;
215
230
  const method = toUpper(leaf.method);
216
231
  const expectsArgs = Boolean(leafCfg.paramsSchema || leafCfg.querySchema);
217
232
  const leafLabel = `${leaf.method.toUpperCase()} ${String(leaf.path)}`;
@@ -267,9 +282,13 @@ function createRouteClient(opts) {
267
282
  const acceptsBody = Boolean(leafCfg.bodySchema);
268
283
  const requiresBody = options?.requireBody ?? (!isGet && acceptsBody);
269
284
  if (typeof options?.body !== "undefined") {
270
- const normalizedBody = zParse(options.body, leafCfg.bodySchema);
285
+ const normalizedBody = leafCfg.bodySchema ? lowProfileParse(leafCfg.bodySchema, options.body) : void 0;
271
286
  const isMultipart = Array.isArray(leafCfg.bodyFiles) && leafCfg.bodyFiles.length > 0;
272
- payload = isMultipart ? toFormData(normalizedBody) : normalizedBody;
287
+ if (isMultipart && normalizedBody && typeof normalizedBody === "object") {
288
+ payload = toFormData(normalizedBody);
289
+ } else {
290
+ payload = normalizedBody;
291
+ }
273
292
  } else if (requiresBody) {
274
293
  throw new Error("Body is required when invoking a mutation fetch.");
275
294
  }
@@ -292,7 +311,7 @@ function createRouteClient(opts) {
292
311
  const out = await fetcher(
293
312
  payload === void 0 ? { url, method } : { url, method, body: payload }
294
313
  );
295
- const parsed = zParse(out, leafCfg.outputSchema);
314
+ const parsed = leafCfg.outputSchema ? lowProfileParse(leafCfg.outputSchema, out) : void 0;
296
315
  emit(
297
316
  decorateDebugEvent(
298
317
  {
@@ -303,7 +322,11 @@ function createRouteClient(opts) {
303
322
  leaf: leafLabel,
304
323
  durationMs: Date.now() - startedAt
305
324
  },
306
- isVerboseDebug ? { params: normalizedParams, query: normalizedQuery, output: parsed } : void 0
325
+ isVerboseDebug ? {
326
+ params: normalizedParams,
327
+ query: normalizedQuery,
328
+ output: parsed
329
+ } : void 0
307
330
  )
308
331
  );
309
332
  options?.onReceive?.(parsed);
@@ -334,7 +357,11 @@ function createRouteClient(opts) {
334
357
  const hasBodyCandidate = acceptsBody && tupleLength > maybeBodyIndex;
335
358
  const body = hasBodyCandidate ? tupleWithBody[tupleLength - 1] : void 0;
336
359
  const tuple = hasBodyCandidate ? tupleWithBody.slice(0, tupleLength - 1) : tupleWithBody;
337
- return fetchEndpoint(tuple, { body, onReceive: buildOnReceive, requireBody: false });
360
+ return fetchEndpoint(tuple, {
361
+ body,
362
+ onReceive: buildOnReceive,
363
+ requireBody: false
364
+ });
338
365
  };
339
366
  if (isGet && isFeed) {
340
367
  const useEndpoint2 = (...useArgs) => {
@@ -345,13 +372,10 @@ function createRouteClient(opts) {
345
372
  const query = args?.query;
346
373
  const buildOptions = rqOpts ?? {};
347
374
  const listenersRef = useRef(/* @__PURE__ */ new Set());
348
- const notifyOnReceive = useCallback(
349
- (data) => {
350
- buildOptions?.onReceive?.(data);
351
- listenersRef.current.forEach((listener) => listener(data));
352
- },
353
- []
354
- );
375
+ const notifyOnReceive = useCallback((data) => {
376
+ buildOptions?.onReceive?.(data);
377
+ listenersRef.current.forEach((listener) => listener(data));
378
+ }, []);
355
379
  const registerOnReceive = useCallback(
356
380
  (listener) => {
357
381
  listenersRef.current.add(listener);
@@ -367,24 +391,27 @@ function createRouteClient(opts) {
367
391
  params,
368
392
  query
369
393
  );
370
- const queryResult = useInfiniteQuery({
371
- ...buildOptions,
372
- queryKey: getQueryKeys(...tuple),
373
- initialPageParam: void 0,
374
- getNextPageParam: (lastPage) => getNextCursor(lastPage),
375
- placeholderData: keepPreviousData,
376
- queryFn: ({ pageParam }) => {
377
- const pageQuery = {
378
- ...normalizedQuery,
379
- ...pageParam ? { [cursorParam]: pageParam } : {}
380
- };
381
- return fetchEndpoint(tuple, {
382
- queryOverride: pageQuery,
383
- onReceive: notifyOnReceive
384
- });
385
- }
386
- // NOTE: TData is InfiniteData<T>, so we don't need a select here.
387
- }, queryClient);
394
+ const queryResult = useInfiniteQuery(
395
+ {
396
+ ...buildOptions,
397
+ queryKey: getQueryKeys(...tuple),
398
+ initialPageParam: void 0,
399
+ getNextPageParam: (lastPage) => getNextCursor(lastPage),
400
+ placeholderData: keepPreviousData,
401
+ queryFn: ({ pageParam }) => {
402
+ const pageQuery = {
403
+ ...normalizedQuery,
404
+ ...pageParam ? { [cursorParam]: pageParam } : {}
405
+ };
406
+ return fetchEndpoint(tuple, {
407
+ queryOverride: pageQuery,
408
+ onReceive: notifyOnReceive
409
+ });
410
+ }
411
+ // NOTE: TData is InfiniteData<T>, so we don't need a select here.
412
+ },
413
+ queryClient
414
+ );
388
415
  return { ...queryResult, onReceive: registerOnReceive };
389
416
  };
390
417
  return {
@@ -404,13 +431,10 @@ function createRouteClient(opts) {
404
431
  const query = args?.query;
405
432
  const buildOptions = rqOpts ?? {};
406
433
  const listenersRef = useRef(/* @__PURE__ */ new Set());
407
- const notifyOnReceive = useCallback(
408
- (data) => {
409
- buildOptions?.onReceive?.(data);
410
- listenersRef.current.forEach((listener) => listener(data));
411
- },
412
- []
413
- );
434
+ const notifyOnReceive = useCallback((data) => {
435
+ buildOptions?.onReceive?.(data);
436
+ listenersRef.current.forEach((listener) => listener(data));
437
+ }, []);
414
438
  const registerOnReceive = useCallback(
415
439
  (listener) => {
416
440
  listenersRef.current.add(listener);
@@ -421,14 +445,17 @@ function createRouteClient(opts) {
421
445
  []
422
446
  );
423
447
  buildUrl({ ...leaf, cfg: leafCfg }, baseUrl, params, query);
424
- const queryResult = useQuery({
425
- ...buildOptions,
426
- queryKey: getQueryKeys(...tuple),
427
- placeholderData: keepPreviousData,
428
- queryFn: () => fetchEndpoint(tuple, {
429
- onReceive: notifyOnReceive
430
- })
431
- }, queryClient);
448
+ const queryResult = useQuery(
449
+ {
450
+ ...buildOptions,
451
+ queryKey: getQueryKeys(...tuple),
452
+ placeholderData: keepPreviousData,
453
+ queryFn: () => fetchEndpoint(tuple, {
454
+ onReceive: notifyOnReceive
455
+ })
456
+ },
457
+ queryClient
458
+ );
432
459
  return { ...queryResult, onReceive: registerOnReceive };
433
460
  };
434
461
  return {
@@ -462,21 +489,29 @@ function createRouteClient(opts) {
462
489
  const notifyListeners = useCallback((data) => {
463
490
  listenersRef.current.forEach((listener) => listener(data));
464
491
  }, []);
465
- const registerOnReceive = useCallback((listener) => {
466
- listenersRef.current.add(listener);
467
- return () => {
468
- listenersRef.current.delete(listener);
469
- };
470
- }, []);
471
- const mutationResult = useMutation({
472
- ...mutationBuildOptions,
473
- mutationKey: getQueryKeys(...tuple),
474
- mutationFn: async (body) => {
475
- const result = await fetchMutation(...[...tuple, body]);
476
- notifyListeners(result);
477
- return result;
478
- }
479
- }, queryClient);
492
+ const registerOnReceive = useCallback(
493
+ (listener) => {
494
+ listenersRef.current.add(listener);
495
+ return () => {
496
+ listenersRef.current.delete(listener);
497
+ };
498
+ },
499
+ []
500
+ );
501
+ const mutationResult = useMutation(
502
+ {
503
+ ...mutationBuildOptions,
504
+ mutationKey: getQueryKeys(...tuple),
505
+ mutationFn: async (body) => {
506
+ const result = await fetchMutation(
507
+ ...[...tuple, body]
508
+ );
509
+ notifyListeners(result);
510
+ return result;
511
+ }
512
+ },
513
+ queryClient
514
+ );
480
515
  return { ...mutationResult, onReceive: registerOnReceive };
481
516
  };
482
517
  return {
@@ -487,25 +522,163 @@ function createRouteClient(opts) {
487
522
  fetch: fetchMutation
488
523
  };
489
524
  }
525
+ const fetchRaw = async (input) => {
526
+ const { path, method, query, body, params } = input;
527
+ if (!path || typeof path !== "string") {
528
+ throw new Error("fetch(path, ...) requires a non-empty string path.");
529
+ }
530
+ if (!method) {
531
+ throw new Error("fetch(path, method, ...) requires an HTTP method.");
532
+ }
533
+ const methodLower = String(method).toLowerCase();
534
+ const methodUpper = toUpper(methodLower);
535
+ const flatQuery = normalizeFlatQuery(query);
536
+ const search = toSearchString(flatQuery);
537
+ const compiledPath = compileRawPath(path, params);
538
+ const url = `${baseUrl ?? ""}${compiledPath}${search}`;
539
+ const leafLabel = `${methodUpper} ${path}`;
540
+ const startedAt = Date.now();
541
+ const detail = isVerboseDebug ? { params, query: flatQuery } : void 0;
542
+ emitDebug(
543
+ decorateDebugEvent(
544
+ {
545
+ type: "fetch",
546
+ stage: "start",
547
+ method: methodUpper,
548
+ url,
549
+ leaf: leafLabel,
550
+ ...body !== void 0 ? { body } : {}
551
+ },
552
+ detail
553
+ )
554
+ );
555
+ try {
556
+ const out = await fetcher(
557
+ body === void 0 ? { url, method: methodUpper } : { url, method: methodUpper, body }
558
+ );
559
+ emitDebug(
560
+ decorateDebugEvent(
561
+ {
562
+ type: "fetch",
563
+ stage: "success",
564
+ method: methodUpper,
565
+ url,
566
+ leaf: leafLabel,
567
+ durationMs: Date.now() - startedAt
568
+ },
569
+ isVerboseDebug ? { params, query: flatQuery, output: out } : void 0
570
+ )
571
+ );
572
+ return out;
573
+ } catch (error) {
574
+ emitDebug(
575
+ decorateDebugEvent(
576
+ {
577
+ type: "fetch",
578
+ stage: "error",
579
+ method: methodUpper,
580
+ url,
581
+ leaf: leafLabel,
582
+ durationMs: Date.now() - startedAt,
583
+ ...body !== void 0 ? { body } : {},
584
+ error
585
+ },
586
+ detail
587
+ )
588
+ );
589
+ throw error;
590
+ }
591
+ };
490
592
  return {
491
593
  queryClient,
492
594
  invalidate,
595
+ fetch: fetchRaw,
493
596
  build: buildInternal
494
597
  };
495
598
  }
496
599
  function buildRouter(routeClient, routes) {
497
600
  const buildLeaf = routeClient.build;
498
- return ((key, opts, meta) => buildLeaf(routes[key], opts, meta));
601
+ return ((key, opts, meta) => buildLeaf(
602
+ routes[key],
603
+ opts,
604
+ meta
605
+ ));
499
606
  }
500
607
  function toFormData(body) {
501
608
  const fd = new FormData();
502
609
  for (const [k, v] of Object.entries(body ?? {})) {
503
610
  if (v == null) continue;
504
- if (Array.isArray(v)) v.forEach((item, i) => fd.append(`${k}[${i}]`, item));
611
+ if (Array.isArray(v))
612
+ v.forEach((item, i) => fd.append(`${k}[${i}]`, item));
505
613
  else fd.append(k, v);
506
614
  }
507
615
  return fd;
508
616
  }
617
+ function getPathParamNames(path) {
618
+ const names = /* @__PURE__ */ new Set();
619
+ const re = /:([A-Za-z0-9_]+)/g;
620
+ let match;
621
+ while ((match = re.exec(path)) !== null) {
622
+ names.add(match[1]);
623
+ }
624
+ return names;
625
+ }
626
+ function normalizeFlatQuery(query) {
627
+ if (query == null) return void 0;
628
+ if (typeof query !== "object" || Array.isArray(query)) {
629
+ throw new Error("Query must be a plain object (Record<string, string>).");
630
+ }
631
+ const result = {};
632
+ for (const [k, v] of Object.entries(query)) {
633
+ if (v == null) continue;
634
+ if (typeof v !== "string") {
635
+ throw new Error(
636
+ `Query param "${k}" must be a string; received type "${typeof v}".`
637
+ );
638
+ }
639
+ result[k] = v;
640
+ }
641
+ return Object.keys(result).length > 0 ? result : void 0;
642
+ }
643
+ function compileRawPath(path, params) {
644
+ const placeholders = getPathParamNames(path);
645
+ if (!params || typeof params !== "object" || Array.isArray(params)) {
646
+ if (placeholders.size > 0) {
647
+ throw new Error(
648
+ `Missing path parameters for "${path}": ${[...placeholders].join(
649
+ ", "
650
+ )}`
651
+ );
652
+ }
653
+ return path;
654
+ }
655
+ const paramObj = params;
656
+ const providedNames = new Set(Object.keys(paramObj));
657
+ for (const name of providedNames) {
658
+ if (!placeholders.has(name)) {
659
+ throw new Error(
660
+ `Unexpected path parameter "${name}" for template "${path}".`
661
+ );
662
+ }
663
+ const value = paramObj[name];
664
+ if (value != null && (typeof value === "object" || Array.isArray(value))) {
665
+ throw new Error(
666
+ `Path parameter "${name}" must be a primitive; received "${typeof value}".`
667
+ );
668
+ }
669
+ }
670
+ for (const name of placeholders) {
671
+ if (!providedNames.has(name)) {
672
+ throw new Error(
673
+ `Missing value for path parameter "${name}" in template "${path}".`
674
+ );
675
+ }
676
+ }
677
+ if (placeholders.size === 0) {
678
+ return path;
679
+ }
680
+ return compilePath(path, paramObj);
681
+ }
509
682
 
510
683
  // src/sockets/socket.client.sys.ts
511
684
  import { z as z2 } from "zod";
@@ -764,7 +937,21 @@ function roomsFromData(data, toRooms) {
764
937
  if (data == null) return { rooms: [] };
765
938
  let state = { rooms: [] };
766
939
  const add = (input) => {
767
- state = mergeRoomState(state, toRooms(input));
940
+ const mergeForValue = (value) => {
941
+ state = mergeRoomState(state, toRooms(value));
942
+ };
943
+ if (Array.isArray(input)) {
944
+ input.forEach((entry) => mergeForValue(entry));
945
+ return;
946
+ }
947
+ if (input && typeof input === "object") {
948
+ const maybeItems = input.items;
949
+ if (Array.isArray(maybeItems)) {
950
+ maybeItems.forEach((entry) => mergeForValue(entry));
951
+ return;
952
+ }
953
+ }
954
+ mergeForValue(input);
768
955
  };
769
956
  const maybePages = data?.pages;
770
957
  if (Array.isArray(maybePages)) {
@@ -778,22 +965,34 @@ function buildSocketedRoute(options) {
778
965
  const { built, toRooms, applySocket, useSocketClient: useSocketClient2 } = options;
779
966
  return (...useArgs) => {
780
967
  const client = useSocketClient2();
781
- const endpointResult = built.useEndpoint(...useArgs);
968
+ const endpointResult = built.useEndpoint(
969
+ ...useArgs
970
+ );
782
971
  const argsKey = useMemo2(() => JSON.stringify(useArgs[0] ?? null), [useArgs]);
783
972
  const [roomState, setRoomState] = useState2(
784
973
  () => roomsFromData(endpointResult.data, toRooms)
785
974
  );
786
975
  const roomsKey = useMemo2(() => roomState.rooms.join("|"), [roomState.rooms]);
787
- const joinMetaKey = useMemo2(() => JSON.stringify(roomState.joinMeta ?? null), [roomState.joinMeta]);
788
- const leaveMetaKey = useMemo2(() => JSON.stringify(roomState.leaveMeta ?? null), [roomState.leaveMeta]);
976
+ const joinMetaKey = useMemo2(
977
+ () => JSON.stringify(roomState.joinMeta ?? null),
978
+ [roomState.joinMeta]
979
+ );
980
+ const leaveMetaKey = useMemo2(
981
+ () => JSON.stringify(roomState.leaveMeta ?? null),
982
+ [roomState.leaveMeta]
983
+ );
789
984
  useEffect2(() => {
790
985
  const unsubscribe = endpointResult.onReceive((data) => {
791
- setRoomState((prev) => mergeRoomState(prev, toRooms(data)));
986
+ setRoomState(
987
+ (prev) => mergeRoomState(prev, toRooms(data))
988
+ );
792
989
  });
793
990
  return unsubscribe;
794
991
  }, [endpointResult, toRooms]);
795
992
  useEffect2(() => {
796
- setRoomState(roomsFromData(endpointResult.data, toRooms));
993
+ setRoomState(
994
+ roomsFromData(endpointResult.data, toRooms)
995
+ );
797
996
  }, [endpointResult.data, toRooms]);
798
997
  useEffect2(() => {
799
998
  if (roomState.rooms.length === 0) return;
@@ -812,7 +1011,14 @@ function buildSocketedRoute(options) {
812
1011
  void client.leaveRooms(roomState.rooms, leaveMeta).catch(() => {
813
1012
  });
814
1013
  };
815
- }, [client, roomsKey, roomState.joinMeta, roomState.leaveMeta, joinMetaKey, leaveMetaKey]);
1014
+ }, [
1015
+ client,
1016
+ roomsKey,
1017
+ roomState.joinMeta,
1018
+ roomState.leaveMeta,
1019
+ joinMetaKey,
1020
+ leaveMetaKey
1021
+ ]);
816
1022
  useEffect2(() => {
817
1023
  const entries = Object.entries(applySocket).filter(
818
1024
  ([_event, fn]) => typeof fn === "function"
@@ -821,7 +1027,9 @@ function buildSocketedRoute(options) {
821
1027
  ([ev, fn]) => client.on(ev, (payload, meta) => {
822
1028
  built.setData((prev) => {
823
1029
  const next = fn(prev, payload, meta);
824
- setRoomState(roomsFromData(next, toRooms));
1030
+ setRoomState(
1031
+ roomsFromData(next, toRooms)
1032
+ );
825
1033
  return next;
826
1034
  }, ...useArgs);
827
1035
  })
@@ -870,7 +1078,11 @@ var SocketClient = class {
870
1078
  }
871
1079
  this.onConnect = async () => {
872
1080
  if (!this.socket) {
873
- this.dbg({ type: "connection", phase: "connect_event", err: "Socket is null" });
1081
+ this.dbg({
1082
+ type: "connection",
1083
+ phase: "connect_event",
1084
+ err: "Socket is null"
1085
+ });
874
1086
  throw new Error("Socket is null in onConnect handler");
875
1087
  }
876
1088
  this.dbg({
@@ -889,7 +1101,11 @@ var SocketClient = class {
889
1101
  };
890
1102
  this.onReconnect = async (attempt) => {
891
1103
  if (!this.socket) {
892
- this.dbg({ type: "connection", phase: "reconnect_event", err: "Socket is null" });
1104
+ this.dbg({
1105
+ type: "connection",
1106
+ phase: "reconnect_event",
1107
+ err: "Socket is null"
1108
+ });
893
1109
  throw new Error("Socket is null in onReconnect handler");
894
1110
  }
895
1111
  this.dbg({
@@ -910,7 +1126,11 @@ var SocketClient = class {
910
1126
  };
911
1127
  this.onDisconnect = async (reason) => {
912
1128
  if (!this.socket) {
913
- this.dbg({ type: "connection", phase: "disconnect_event", err: "Socket is null" });
1129
+ this.dbg({
1130
+ type: "connection",
1131
+ phase: "disconnect_event",
1132
+ err: "Socket is null"
1133
+ });
914
1134
  throw new Error("Socket is null in onDisconnect handler");
915
1135
  }
916
1136
  this.dbg({
@@ -930,7 +1150,11 @@ var SocketClient = class {
930
1150
  };
931
1151
  this.onConnectError = async (err) => {
932
1152
  if (!this.socket) {
933
- this.dbg({ type: "connection", phase: "connect_error_event", err: "Socket is null" });
1153
+ this.dbg({
1154
+ type: "connection",
1155
+ phase: "connect_error_event",
1156
+ err: "Socket is null"
1157
+ });
934
1158
  throw new Error("Socket is null in onConnectError handler");
935
1159
  }
936
1160
  this.dbg({
@@ -948,7 +1172,11 @@ var SocketClient = class {
948
1172
  };
949
1173
  this.onPong = async (raw) => {
950
1174
  if (!this.socket) {
951
- this.dbg({ type: "heartbeat", phase: "pong_recv", err: "Socket is null" });
1175
+ this.dbg({
1176
+ type: "heartbeat",
1177
+ phase: "pong_recv",
1178
+ err: "Socket is null"
1179
+ });
952
1180
  throw new Error("Socket is null in onPong handler");
953
1181
  }
954
1182
  const parsed = this.config.pongPayload.safeParse(raw);
@@ -1048,11 +1276,15 @@ var SocketClient = class {
1048
1276
  }
1049
1277
  /** internal stats snapshot */
1050
1278
  stats() {
1051
- const rooms = Array.from(this.roomCounts.entries()).map(([room, count]) => ({ room, count }));
1052
- const handlers = Array.from(this.handlerMap.entries()).map(([event, set]) => ({
1053
- event,
1054
- handlers: set.size
1055
- }));
1279
+ const rooms = Array.from(this.roomCounts.entries()).map(
1280
+ ([room, count]) => ({ room, count })
1281
+ );
1282
+ const handlers = Array.from(this.handlerMap.entries()).map(
1283
+ ([event, set]) => ({
1284
+ event,
1285
+ handlers: set.size
1286
+ })
1287
+ );
1056
1288
  return {
1057
1289
  roomsCount: rooms.length,
1058
1290
  totalHandlers: handlers.reduce((a, b) => a + b.handlers, 0),
@@ -1124,7 +1356,10 @@ var SocketClient = class {
1124
1356
  details: this.getValidationDetails(check.error)
1125
1357
  });
1126
1358
  if (this.environment === "development") {
1127
- console.warn("[socket] ping schema validation failed", check.error.issues);
1359
+ console.warn(
1360
+ "[socket] ping schema validation failed",
1361
+ check.error.issues
1362
+ );
1128
1363
  }
1129
1364
  return;
1130
1365
  }
@@ -1183,7 +1418,12 @@ var SocketClient = class {
1183
1418
  }
1184
1419
  async joinRooms(rooms, meta) {
1185
1420
  if (!this.socket) {
1186
- this.dbg({ type: "room", phase: "join", rooms: this.toArray(rooms), err: "Socket is null" });
1421
+ this.dbg({
1422
+ type: "room",
1423
+ phase: "join",
1424
+ rooms: this.toArray(rooms),
1425
+ err: "Socket is null"
1426
+ });
1187
1427
  throw new Error("Socket is null in joinRooms method");
1188
1428
  }
1189
1429
  if (!await this.getSysEvent("sys:room_join")({
@@ -1236,7 +1476,12 @@ var SocketClient = class {
1236
1476
  }
1237
1477
  async leaveRooms(rooms, meta) {
1238
1478
  if (!this.socket) {
1239
- this.dbg({ type: "room", phase: "leave", rooms: this.toArray(rooms), err: "Socket is null" });
1479
+ this.dbg({
1480
+ type: "room",
1481
+ phase: "leave",
1482
+ rooms: this.toArray(rooms),
1483
+ err: "Socket is null"
1484
+ });
1240
1485
  throw new Error("Socket is null in leaveRooms method");
1241
1486
  }
1242
1487
  if (!await this.getSysEvent("sys:room_leave")({
@@ -1288,7 +1533,12 @@ var SocketClient = class {
1288
1533
  const schema = this.events[event].message;
1289
1534
  this.dbg({ type: "register", phase: "register", event });
1290
1535
  if (!this.socket) {
1291
- this.dbg({ type: "register", phase: "register", event, err: "Socket is null" });
1536
+ this.dbg({
1537
+ type: "register",
1538
+ phase: "register",
1539
+ event,
1540
+ err: "Socket is null"
1541
+ });
1292
1542
  return () => {
1293
1543
  };
1294
1544
  }