@emeryld/rrroutes-server 2.0.6 → 2.0.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.cjs CHANGED
@@ -447,8 +447,24 @@ var buildRoomPayloadSchema = (metaSchema) => import_zod.z.object({
447
447
  meta: metaSchema
448
448
  });
449
449
  var toArray = (rooms) => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];
450
+ var snapshotSocketConfig = (socket) => {
451
+ const handshake = socket.handshake ?? {};
452
+ const conn = socket.conn;
453
+ const protocol = conn?.protocol;
454
+ return {
455
+ url: handshake.url,
456
+ transport: conn?.transport?.name,
457
+ protocol: protocol != null ? String(protocol) : void 0,
458
+ address: conn?.remoteAddress ?? handshake.address,
459
+ issued: handshake.issued,
460
+ time: handshake.time,
461
+ query: handshake.query,
462
+ auth: handshake.auth,
463
+ headers: handshake.headers
464
+ };
465
+ };
450
466
  function createBuiltInConnectionHandlers(opts) {
451
- const { heartbeat, sys, dbg, config, createCtx } = opts;
467
+ const { heartbeat, sys, dbg, config, createCtx, debugVerbose } = opts;
452
468
  const roomJoinEvent = "sys:room_join";
453
469
  const roomLeaveEvent = "sys:room_leave";
454
470
  const pingEvent = "sys:ping";
@@ -463,7 +479,30 @@ function createBuiltInConnectionHandlers(opts) {
463
479
  const socketTeardowns = /* @__PURE__ */ new WeakMap();
464
480
  const builtInConnectionListener = (socket) => {
465
481
  const typedSocket = socket;
482
+ const handshake = socket.handshake ?? {};
483
+ dbg(null, {
484
+ type: "lifecycle",
485
+ stage: "connection_init",
486
+ socketId: socket.id,
487
+ nsp: socket.nsp.name,
488
+ details: {
489
+ rooms: Array.from(socket.rooms),
490
+ handshakeIssued: handshake.issued
491
+ }
492
+ });
493
+ dbg(null, {
494
+ type: "config",
495
+ socketId: socket.id,
496
+ nsp: socket.nsp.name,
497
+ snapshot: snapshotSocketConfig(socket)
498
+ });
466
499
  const defaultConnect = () => {
500
+ dbg("sys:connect", {
501
+ type: "handler",
502
+ phase: "handler_success",
503
+ event: "sys:connect",
504
+ socketId: socket.id
505
+ });
467
506
  if (socket.data?.user) {
468
507
  dbg(null, {
469
508
  type: "auth",
@@ -472,17 +511,27 @@ function createBuiltInConnectionHandlers(opts) {
472
511
  sub: socket.data.user?.sub
473
512
  });
474
513
  }
514
+ const includeRaw = debugVerbose === true;
475
515
  const joinHandler = async (msg) => {
516
+ dbg(roomJoinEvent, {
517
+ type: "handler",
518
+ phase: "receive",
519
+ event: roomJoinEvent,
520
+ socketId: socket.id,
521
+ rooms: Array.from(socket.rooms),
522
+ raw: includeRaw ? msg : void 0
523
+ });
476
524
  const parsed = joinPayloadSchema.safeParse(msg);
477
525
  if (!parsed.success) {
478
526
  socket.emit(`${roomJoinEvent}:error`, {
479
527
  eventName: roomJoinEvent,
480
528
  issues: parsed.error.issues
481
529
  });
482
- dbg("sys:room_join", {
530
+ dbg(roomJoinEvent, {
483
531
  type: "handler",
484
532
  phase: "validation_error",
485
533
  event: roomJoinEvent,
534
+ socketId: socket.id,
486
535
  issues: parsed.error.issues
487
536
  });
488
537
  return;
@@ -502,27 +551,45 @@ function createBuiltInConnectionHandlers(opts) {
502
551
  };
503
552
  try {
504
553
  await run();
554
+ dbg(roomJoinEvent, {
555
+ type: "handler",
556
+ phase: "handler_success",
557
+ event: roomJoinEvent,
558
+ socketId: socket.id,
559
+ rooms: list,
560
+ details: includeRaw ? { meta: parsed.data.meta } : void 0
561
+ });
505
562
  } catch (error) {
506
563
  socket.emit(`${roomJoinEvent}:error`, { error: normalizeError(error) });
507
- dbg("sys:room_join", {
564
+ dbg(roomJoinEvent, {
508
565
  type: "handler",
509
566
  phase: "handler_error",
510
567
  event: roomJoinEvent,
568
+ socketId: socket.id,
511
569
  error
512
570
  });
513
571
  }
514
572
  };
515
573
  const leaveHandler = async (msg) => {
574
+ dbg(roomLeaveEvent, {
575
+ type: "handler",
576
+ phase: "receive",
577
+ event: roomLeaveEvent,
578
+ socketId: socket.id,
579
+ rooms: Array.from(socket.rooms),
580
+ raw: includeRaw ? msg : void 0
581
+ });
516
582
  const parsed = leavePayloadSchema.safeParse(msg);
517
583
  if (!parsed.success) {
518
584
  socket.emit(`${roomLeaveEvent}:error`, {
519
585
  eventName: roomLeaveEvent,
520
586
  issues: parsed.error.issues
521
587
  });
522
- dbg("sys:room_leave", {
588
+ dbg(roomLeaveEvent, {
523
589
  type: "handler",
524
590
  phase: "validation_error",
525
591
  event: roomLeaveEvent,
592
+ socketId: socket.id,
526
593
  issues: parsed.error.issues
527
594
  });
528
595
  return;
@@ -542,18 +609,43 @@ function createBuiltInConnectionHandlers(opts) {
542
609
  };
543
610
  try {
544
611
  await run();
612
+ dbg(roomLeaveEvent, {
613
+ type: "handler",
614
+ phase: "handler_success",
615
+ event: roomLeaveEvent,
616
+ socketId: socket.id,
617
+ rooms: list,
618
+ details: includeRaw ? { meta: parsed.data.meta } : void 0
619
+ });
545
620
  } catch (error) {
546
621
  socket.emit(`${roomLeaveEvent}:error`, { error: normalizeError(error) });
547
- dbg("sys:room_leave", {
622
+ dbg(roomLeaveEvent, {
548
623
  type: "handler",
549
624
  phase: "handler_error",
550
625
  event: roomLeaveEvent,
626
+ socketId: socket.id,
551
627
  error
552
628
  });
553
629
  }
554
630
  };
555
631
  const pingHandler = async (msg) => {
556
- if (!heartbeatEnabled) return;
632
+ if (!heartbeatEnabled) {
633
+ dbg(null, {
634
+ type: "lifecycle",
635
+ stage: "early_return",
636
+ socketId: socket.id,
637
+ nsp: socket.nsp.name,
638
+ details: { reason: "heartbeat_disabled", event: pingEvent }
639
+ });
640
+ dbg(null, {
641
+ type: "heartbeat",
642
+ phase: "skip",
643
+ socketId: socket.id,
644
+ details: { reason: "heartbeat_disabled" },
645
+ error: false
646
+ });
647
+ return;
648
+ }
557
649
  const parsedPing = pingPayloadSchema.safeParse(msg);
558
650
  if (!parsedPing.success) {
559
651
  socket.emit(`${pingEvent}:error`, {
@@ -564,8 +656,10 @@ function createBuiltInConnectionHandlers(opts) {
564
656
  type: "heartbeat",
565
657
  phase: "ping",
566
658
  socketId: socket.id,
659
+ payload: includeRaw ? msg : void 0,
567
660
  issues: parsedPing.error.issues,
568
- error: true
661
+ error: true,
662
+ details: { step: "parse" }
569
663
  });
570
664
  return;
571
665
  }
@@ -587,7 +681,8 @@ function createBuiltInConnectionHandlers(opts) {
587
681
  phase: "ping",
588
682
  socketId: socket.id,
589
683
  payload: parsedPing.data,
590
- error: true
684
+ error: true,
685
+ details: { step: "sys_handler_error" }
591
686
  });
592
687
  return;
593
688
  }
@@ -601,8 +696,10 @@ function createBuiltInConnectionHandlers(opts) {
601
696
  type: "heartbeat",
602
697
  phase: "pong",
603
698
  socketId: socket.id,
699
+ payload: includeRaw ? pongPayload : void 0,
604
700
  issues: parsedPong.error.issues,
605
- error: true
701
+ error: true,
702
+ details: { step: "parse" }
606
703
  });
607
704
  return;
608
705
  }
@@ -621,6 +718,13 @@ function createBuiltInConnectionHandlers(opts) {
621
718
  socket.on(pingEvent, pingHandler);
622
719
  }
623
720
  const cleanup = () => {
721
+ dbg(null, {
722
+ type: "lifecycle",
723
+ stage: "connection_cleanup",
724
+ socketId: socket.id,
725
+ nsp: socket.nsp.name,
726
+ details: { reason: "teardown" }
727
+ });
624
728
  socket.off(roomJoinEvent, joinHandler);
625
729
  socket.off(roomLeaveEvent, leaveHandler);
626
730
  if (heartbeatEnabled) {
@@ -628,7 +732,26 @@ function createBuiltInConnectionHandlers(opts) {
628
732
  }
629
733
  };
630
734
  socketTeardowns.set(socket, cleanup);
735
+ dbg(null, {
736
+ type: "lifecycle",
737
+ stage: "connection_handlers_attached",
738
+ socketId: socket.id,
739
+ nsp: socket.nsp.name,
740
+ details: {
741
+ heartbeatEnabled,
742
+ joinEvent: roomJoinEvent,
743
+ leaveEvent: roomLeaveEvent,
744
+ pingEvent: heartbeatEnabled ? pingEvent : void 0
745
+ }
746
+ });
631
747
  socket.once("disconnect", (reason) => {
748
+ dbg("sys:disconnect", {
749
+ type: "handler",
750
+ phase: "receive",
751
+ event: "sys:disconnect",
752
+ socketId: socket.id,
753
+ details: { reason: String(reason) }
754
+ });
632
755
  const defaultDisconnect = () => {
633
756
  cleanup();
634
757
  socketTeardowns.delete(socket);
@@ -640,6 +763,14 @@ function createBuiltInConnectionHandlers(opts) {
640
763
  });
641
764
  });
642
765
  };
766
+ dbg("sys:connect", {
767
+ type: "handler",
768
+ phase: "receive",
769
+ event: "sys:connect",
770
+ socketId: socket.id,
771
+ nsp: socket.nsp.name,
772
+ details: { hasAuthData: Boolean(socket.data?.user) }
773
+ });
643
774
  getSysEvent("sys:connect")({
644
775
  socket: typedSocket,
645
776
  initConnection: defaultConnect
@@ -681,6 +812,17 @@ var normalizeError2 = (error, verbose) => {
681
812
  function createSocketConnections(io, events, opts) {
682
813
  const dbg = createDebugger(opts?.debug);
683
814
  const socketConfig = opts.config;
815
+ const heartbeatEnabled = opts?.heartbeat?.enabled !== false;
816
+ const eventNames = Object.keys(events);
817
+ dbg(null, {
818
+ type: "lifecycle",
819
+ stage: "server_init",
820
+ details: {
821
+ eventCount: eventNames.length,
822
+ heartbeatEnabled,
823
+ debugEnabled: Boolean(opts?.debug?.logger)
824
+ }
825
+ });
684
826
  const getSchema = (k) => events[k].message;
685
827
  const toArray2 = (rooms) => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms];
686
828
  const registrations = /* @__PURE__ */ new Map();
@@ -694,7 +836,14 @@ function createSocketConnections(io, events, opts) {
694
836
  };
695
837
  const removeAllForEvent = (eventName) => {
696
838
  const set = registrations.get(eventName);
697
- if (!set) return;
839
+ if (!set) {
840
+ dbg(null, {
841
+ type: "lifecycle",
842
+ stage: "early_return",
843
+ details: { reason: "no_registrations", event: eventName }
844
+ });
845
+ return;
846
+ }
698
847
  for (const reg of set) {
699
848
  io.off("connection", reg.connectionListener);
700
849
  for (const socket of io.sockets.sockets.values()) {
@@ -716,9 +865,18 @@ function createSocketConnections(io, events, opts) {
716
865
  sys: opts.sys,
717
866
  dbg,
718
867
  config: socketConfig,
719
- createCtx: createBaseHandlerCtx
868
+ createCtx: createBaseHandlerCtx,
869
+ debugVerbose: opts?.debug?.verbose === true
720
870
  });
721
871
  io.on("connection", builtInConnectionListener);
872
+ dbg(null, {
873
+ type: "lifecycle",
874
+ stage: "connection_listener_installed",
875
+ details: {
876
+ heartbeatEnabled,
877
+ sysEvents: Object.keys(opts.sys ?? {})
878
+ }
879
+ });
722
880
  const conn = {
723
881
  on(eventName, handler) {
724
882
  const socketListeners = /* @__PURE__ */ new WeakMap();
@@ -738,7 +896,8 @@ function createSocketConnections(io, events, opts) {
738
896
  socketId: ctx.socketId,
739
897
  nsp: ctx.nsp,
740
898
  rooms: ctx.rooms,
741
- raw: opts?.debug?.verbose ? raw : void 0
899
+ raw: opts?.debug?.verbose ? raw : void 0,
900
+ details: { ack: Boolean(maybeAck) }
742
901
  });
743
902
  if (!parsed.success) {
744
903
  socket.emit(`${String(eventName)}:error`, {
@@ -750,7 +909,10 @@ function createSocketConnections(io, events, opts) {
750
909
  type: "handler",
751
910
  phase: "validation_error",
752
911
  event: String(eventName),
753
- issues: parsed.error.issues
912
+ socketId: ctx.socketId,
913
+ nsp: ctx.nsp,
914
+ issues: parsed.error.issues,
915
+ details: { ack: Boolean(maybeAck) }
754
916
  });
755
917
  return;
756
918
  }
@@ -759,13 +921,20 @@ function createSocketConnections(io, events, opts) {
759
921
  dbg(String(eventName), {
760
922
  type: "handler",
761
923
  phase: "handler_success",
762
- event: String(eventName)
924
+ event: String(eventName),
925
+ socketId: ctx.socketId,
926
+ nsp: ctx.nsp,
927
+ rooms: ctx.rooms,
928
+ details: { ack: Boolean(maybeAck) }
763
929
  });
764
930
  } catch (error) {
765
931
  dbg(String(eventName), {
766
932
  type: "handler",
767
933
  phase: "handler_error",
768
934
  event: String(eventName),
935
+ socketId: ctx.socketId,
936
+ nsp: ctx.nsp,
937
+ rooms: ctx.rooms,
769
938
  error
770
939
  });
771
940
  socket.emit(`${String(eventName)}:error`, {
@@ -791,7 +960,14 @@ function createSocketConnections(io, events, opts) {
791
960
  });
792
961
  return () => {
793
962
  const set = registrations.get(String(eventName));
794
- if (!set) return;
963
+ if (!set) {
964
+ dbg(null, {
965
+ type: "lifecycle",
966
+ stage: "early_return",
967
+ details: { reason: "registration_missing_on_cleanup", event: String(eventName) }
968
+ });
969
+ return;
970
+ }
795
971
  for (const reg of Array.from(set)) {
796
972
  if (reg.connectionListener === connectionListener) {
797
973
  io.off("connection", reg.connectionListener);
@@ -816,10 +992,22 @@ function createSocketConnections(io, events, opts) {
816
992
  },
817
993
  emit(eventName, payload, rooms, metadata, onAck) {
818
994
  const schema = getSchema(eventName);
995
+ const targets = toArray2(rooms);
819
996
  const check = schema.safeParse(payload);
820
- if (!check.success)
997
+ if (!check.success) {
998
+ dbg(String(eventName), {
999
+ type: "emit",
1000
+ event: String(eventName),
1001
+ rooms: targets,
1002
+ envelope: opts?.debug?.verbose ? { eventName, attemptedPayload: payload, metadata } : void 0,
1003
+ error: {
1004
+ reason: "invalid_payload",
1005
+ message: check.error.message,
1006
+ issues: opts?.debug?.verbose ? check.error.issues : void 0
1007
+ }
1008
+ });
821
1009
  throw new Error(`Invalid payload for "${String(eventName)}": ${check.error.message}`);
822
- const targets = toArray2(rooms);
1010
+ }
823
1011
  const envelope = {
824
1012
  eventName,
825
1013
  sentAt: /* @__PURE__ */ new Date(),
@@ -849,6 +1037,15 @@ function createSocketConnections(io, events, opts) {
849
1037
  });
850
1038
  return;
851
1039
  }
1040
+ dbg(String(eventName), {
1041
+ type: "emit",
1042
+ event: String(eventName),
1043
+ rooms: targets,
1044
+ error: {
1045
+ reason: "socket_not_found",
1046
+ message: `Socket ${sid} not connected`
1047
+ }
1048
+ });
852
1049
  }
853
1050
  if (targets.length === 0) io.emit(String(eventName), envelope);
854
1051
  else io.to(targets).emit(String(eventName), envelope);
@@ -860,6 +1057,14 @@ function createSocketConnections(io, events, opts) {
860
1057
  });
861
1058
  },
862
1059
  destroy() {
1060
+ dbg(null, {
1061
+ type: "lifecycle",
1062
+ stage: "destroy_start",
1063
+ details: {
1064
+ socketCount: io.sockets.sockets.size,
1065
+ registrationCount: registrations.size
1066
+ }
1067
+ });
863
1068
  io.off("connection", builtInConnectionListener);
864
1069
  for (const socket of io.sockets.sockets.values()) {
865
1070
  const cleanup = socketTeardowns.get(socket);
@@ -867,6 +1072,13 @@ function createSocketConnections(io, events, opts) {
867
1072
  cleanup();
868
1073
  socketTeardowns.delete(socket);
869
1074
  } else {
1075
+ dbg(null, {
1076
+ type: "lifecycle",
1077
+ stage: "early_return",
1078
+ socketId: socket.id,
1079
+ nsp: socket.nsp.name,
1080
+ details: { reason: "teardown_missing" }
1081
+ });
870
1082
  try {
871
1083
  socket.removeAllListeners(roomJoinEvent);
872
1084
  socket.removeAllListeners(roomLeaveEvent);
@@ -879,6 +1091,14 @@ function createSocketConnections(io, events, opts) {
879
1091
  removeAllForEvent(eventName);
880
1092
  }
881
1093
  registrations.clear();
1094
+ dbg(null, {
1095
+ type: "lifecycle",
1096
+ stage: "destroy_complete",
1097
+ details: {
1098
+ socketCount: io.sockets.sockets.size,
1099
+ registrationCount: registrations.size
1100
+ }
1101
+ });
882
1102
  }
883
1103
  };
884
1104
  return conn;