@emeryld/rrroutes-client 2.7.12 → 2.7.13
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 +149 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +146 -105
- package/dist/index.mjs.map +1 -1
- package/dist/sockets/socket.client.context.connection.d.ts +34 -14
- package/dist/sockets/socket.client.context.d.ts +1 -1
- package/dist/sockets/socket.client.context.provider.d.ts +4 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1558,25 +1558,67 @@ function useSocketClient() {
|
|
|
1558
1558
|
|
|
1559
1559
|
// src/sockets/socket.client.context.connection.ts
|
|
1560
1560
|
import * as React2 from "react";
|
|
1561
|
-
function
|
|
1561
|
+
function normalizeRooms(rooms) {
|
|
1562
|
+
if (rooms == null) return [];
|
|
1563
|
+
return Array.isArray(rooms) ? rooms : [rooms];
|
|
1564
|
+
}
|
|
1565
|
+
function safeSerialize(value) {
|
|
1566
|
+
try {
|
|
1567
|
+
return JSON.stringify(value) ?? String(value);
|
|
1568
|
+
} catch {
|
|
1569
|
+
return "[unserializable]";
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
function useLatestRef(value) {
|
|
1573
|
+
const ref = React2.useRef(value);
|
|
1574
|
+
React2.useEffect(() => {
|
|
1575
|
+
ref.current = value;
|
|
1576
|
+
}, [value]);
|
|
1577
|
+
return ref;
|
|
1578
|
+
}
|
|
1579
|
+
function useDebugEmitter(debug) {
|
|
1580
|
+
const debugRef = useLatestRef(debug);
|
|
1581
|
+
return React2.useCallback((event) => {
|
|
1582
|
+
const dbg3 = debugRef.current;
|
|
1583
|
+
if (!dbg3?.enabled) return;
|
|
1584
|
+
if (dbg3[event.type] === false) return;
|
|
1585
|
+
const logger = dbg3.logger;
|
|
1586
|
+
if (logger) {
|
|
1587
|
+
try {
|
|
1588
|
+
logger(event);
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1591
|
+
console.warn("[socket] debug logger threw", error);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1596
|
+
if (typeof console !== "undefined" && typeof console.log === "function") {
|
|
1597
|
+
console.log("[socket]", event);
|
|
1598
|
+
}
|
|
1599
|
+
}, []);
|
|
1600
|
+
}
|
|
1601
|
+
function useSocketRooms(args) {
|
|
1562
1602
|
const {
|
|
1563
|
-
event,
|
|
1564
1603
|
rooms,
|
|
1565
|
-
onMessage,
|
|
1566
|
-
onCleanup,
|
|
1567
1604
|
autoJoin = true,
|
|
1568
1605
|
autoLeave = true,
|
|
1606
|
+
enabled = true,
|
|
1607
|
+
onCleanup,
|
|
1569
1608
|
debug
|
|
1570
1609
|
} = args;
|
|
1571
1610
|
const client = useSocketClient();
|
|
1572
|
-
const normalizedRooms = React2.useMemo(
|
|
1573
|
-
() => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms],
|
|
1574
|
-
[rooms]
|
|
1575
|
-
);
|
|
1611
|
+
const normalizedRooms = React2.useMemo(() => normalizeRooms(rooms), [rooms]);
|
|
1576
1612
|
const normalizedRoomsKey = React2.useMemo(
|
|
1577
1613
|
() => normalizedRooms.join(""),
|
|
1578
1614
|
[normalizedRooms]
|
|
1579
1615
|
);
|
|
1616
|
+
const joinMetaRef = useLatestRef(args.joinMeta);
|
|
1617
|
+
const leaveMetaRef = useLatestRef(args.leaveMeta);
|
|
1618
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1619
|
+
const debugRef = useLatestRef(debug);
|
|
1620
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1621
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1580
1622
|
const joinMetaKey = React2.useMemo(
|
|
1581
1623
|
() => JSON.stringify(args.joinMeta ?? null),
|
|
1582
1624
|
[args.joinMeta]
|
|
@@ -1585,107 +1627,48 @@ function useSocketConnection(args) {
|
|
|
1585
1627
|
() => JSON.stringify(args.leaveMeta ?? null),
|
|
1586
1628
|
[args.leaveMeta]
|
|
1587
1629
|
);
|
|
1588
|
-
const missingClientWarnedRef = React2.useRef(false);
|
|
1589
|
-
const onMessageRef = React2.useRef(onMessage);
|
|
1590
|
-
const onCleanupRef = React2.useRef(onCleanup);
|
|
1591
|
-
const joinMetaRef = React2.useRef(args.joinMeta);
|
|
1592
|
-
const leaveMetaRef = React2.useRef(args.leaveMeta);
|
|
1593
|
-
const debugRef = React2.useRef(debug);
|
|
1594
|
-
React2.useEffect(() => {
|
|
1595
|
-
onMessageRef.current = onMessage;
|
|
1596
|
-
}, [onMessage]);
|
|
1597
|
-
React2.useEffect(() => {
|
|
1598
|
-
onCleanupRef.current = onCleanup;
|
|
1599
|
-
}, [onCleanup]);
|
|
1600
|
-
React2.useEffect(() => {
|
|
1601
|
-
joinMetaRef.current = args.joinMeta;
|
|
1602
|
-
}, [args.joinMeta]);
|
|
1603
|
-
React2.useEffect(() => {
|
|
1604
|
-
leaveMetaRef.current = args.leaveMeta;
|
|
1605
|
-
}, [args.leaveMeta]);
|
|
1606
|
-
React2.useEffect(() => {
|
|
1607
|
-
debugRef.current = debug;
|
|
1608
|
-
}, [debug]);
|
|
1609
|
-
const emitDebug = React2.useCallback(
|
|
1610
|
-
(event2) => {
|
|
1611
|
-
const dbg3 = debugRef.current;
|
|
1612
|
-
if (!dbg3?.enabled) return;
|
|
1613
|
-
if (dbg3[event2.type] === false) return;
|
|
1614
|
-
const logger = dbg3.logger;
|
|
1615
|
-
if (logger) {
|
|
1616
|
-
try {
|
|
1617
|
-
logger(event2);
|
|
1618
|
-
} catch (error) {
|
|
1619
|
-
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1620
|
-
console.warn("[socket] useSocketConnection debug logger threw", error);
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
return;
|
|
1624
|
-
}
|
|
1625
|
-
if (typeof console !== "undefined" && typeof console.log === "function") {
|
|
1626
|
-
console.log("[socket] useSocketConnection", event2);
|
|
1627
|
-
}
|
|
1628
|
-
},
|
|
1629
|
-
[]
|
|
1630
|
-
);
|
|
1631
|
-
const reportAsyncError = React2.useCallback(
|
|
1632
|
-
(phase, error) => {
|
|
1633
|
-
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1634
|
-
console.warn(`[socket] useSocketConnection ${phase} failed`, error);
|
|
1635
|
-
}
|
|
1636
|
-
},
|
|
1637
|
-
[]
|
|
1638
|
-
);
|
|
1639
1630
|
React2.useEffect(() => {
|
|
1640
1631
|
emitDebug({
|
|
1641
1632
|
type: "lifecycle",
|
|
1642
1633
|
phase: "effect_start",
|
|
1643
|
-
event,
|
|
1644
1634
|
rooms: normalizedRooms,
|
|
1645
1635
|
autoJoin,
|
|
1646
1636
|
autoLeave
|
|
1647
1637
|
});
|
|
1638
|
+
if (!enabled) {
|
|
1639
|
+
emitDebug({
|
|
1640
|
+
type: "room",
|
|
1641
|
+
phase: "join_skip",
|
|
1642
|
+
rooms: normalizedRooms,
|
|
1643
|
+
reason: "disabled"
|
|
1644
|
+
});
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1648
1647
|
if (!client) {
|
|
1649
1648
|
emitDebug({
|
|
1650
1649
|
type: "lifecycle",
|
|
1651
1650
|
phase: "client_missing",
|
|
1652
|
-
event,
|
|
1653
1651
|
rooms: normalizedRooms,
|
|
1654
1652
|
autoJoin,
|
|
1655
1653
|
autoLeave
|
|
1656
1654
|
});
|
|
1657
|
-
if (debugRef.current?.throwIfClientMissing) {
|
|
1658
|
-
throw new Error(
|
|
1659
|
-
`useSocketConnection("${event}") missing SocketClient. Wrap with <SocketProvider>.`
|
|
1660
|
-
);
|
|
1661
|
-
}
|
|
1662
1655
|
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1663
1656
|
missingClientWarnedRef.current = true;
|
|
1664
|
-
console.warn(
|
|
1665
|
-
`[socket] useSocketConnection("${event}") skipped because SocketClient is null.`
|
|
1666
|
-
);
|
|
1657
|
+
console.warn("[socket] useSocketRooms skipped because SocketClient is null.");
|
|
1667
1658
|
}
|
|
1668
1659
|
return;
|
|
1669
1660
|
}
|
|
1670
1661
|
missingClientWarnedRef.current = false;
|
|
1671
|
-
emitDebug({ type: "subscription", phase: "register", event });
|
|
1672
1662
|
if (autoJoin && normalizedRooms.length > 0) {
|
|
1673
|
-
emitDebug({
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
rooms: normalizedRooms
|
|
1677
|
-
});
|
|
1678
|
-
void client.joinRooms(normalizedRooms, joinMetaRef.current).then(() => {
|
|
1679
|
-
emitDebug({ type: "room", phase: "join_ok", rooms: normalizedRooms });
|
|
1680
|
-
}).catch((error) => {
|
|
1681
|
-
emitDebug({
|
|
1663
|
+
emitDebug({ type: "room", phase: "join_attempt", rooms: normalizedRooms });
|
|
1664
|
+
void client.joinRooms(normalizedRooms, joinMetaRef.current).then(() => emitDebug({ type: "room", phase: "join_ok", rooms: normalizedRooms })).catch(
|
|
1665
|
+
(error) => emitDebug({
|
|
1682
1666
|
type: "room",
|
|
1683
1667
|
phase: "join_error",
|
|
1684
1668
|
rooms: normalizedRooms,
|
|
1685
1669
|
err: String(error)
|
|
1686
|
-
})
|
|
1687
|
-
|
|
1688
|
-
});
|
|
1670
|
+
})
|
|
1671
|
+
);
|
|
1689
1672
|
} else {
|
|
1690
1673
|
emitDebug({
|
|
1691
1674
|
type: "room",
|
|
@@ -1694,30 +1677,23 @@ function useSocketConnection(args) {
|
|
|
1694
1677
|
reason: autoJoin ? "no_rooms" : "auto_disabled"
|
|
1695
1678
|
});
|
|
1696
1679
|
}
|
|
1697
|
-
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1698
|
-
emitDebug({ type: "subscription", phase: "message", event });
|
|
1699
|
-
onMessageRef.current(payload, meta);
|
|
1700
|
-
});
|
|
1701
1680
|
return () => {
|
|
1702
|
-
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1703
|
-
unsubscribe();
|
|
1704
1681
|
if (autoLeave && normalizedRooms.length > 0) {
|
|
1705
1682
|
emitDebug({
|
|
1706
1683
|
type: "room",
|
|
1707
1684
|
phase: "leave_attempt",
|
|
1708
1685
|
rooms: normalizedRooms
|
|
1709
1686
|
});
|
|
1710
|
-
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1711
|
-
emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1712
|
-
|
|
1713
|
-
emitDebug({
|
|
1687
|
+
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1688
|
+
() => emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1689
|
+
).catch(
|
|
1690
|
+
(error) => emitDebug({
|
|
1714
1691
|
type: "room",
|
|
1715
1692
|
phase: "leave_error",
|
|
1716
1693
|
rooms: normalizedRooms,
|
|
1717
1694
|
err: String(error)
|
|
1718
|
-
})
|
|
1719
|
-
|
|
1720
|
-
});
|
|
1695
|
+
})
|
|
1696
|
+
);
|
|
1721
1697
|
} else {
|
|
1722
1698
|
emitDebug({
|
|
1723
1699
|
type: "room",
|
|
@@ -1726,11 +1702,10 @@ function useSocketConnection(args) {
|
|
|
1726
1702
|
reason: autoLeave ? "no_rooms" : "auto_disabled"
|
|
1727
1703
|
});
|
|
1728
1704
|
}
|
|
1729
|
-
|
|
1705
|
+
onCleanupRef.current?.();
|
|
1730
1706
|
emitDebug({
|
|
1731
1707
|
type: "lifecycle",
|
|
1732
1708
|
phase: "effect_cleanup",
|
|
1733
|
-
event,
|
|
1734
1709
|
rooms: normalizedRooms,
|
|
1735
1710
|
autoJoin,
|
|
1736
1711
|
autoLeave
|
|
@@ -1738,16 +1713,78 @@ function useSocketConnection(args) {
|
|
|
1738
1713
|
};
|
|
1739
1714
|
}, [
|
|
1740
1715
|
client,
|
|
1741
|
-
|
|
1716
|
+
enabled,
|
|
1742
1717
|
autoJoin,
|
|
1743
1718
|
autoLeave,
|
|
1744
|
-
emitDebug,
|
|
1745
|
-
reportAsyncError,
|
|
1746
1719
|
normalizedRoomsKey,
|
|
1747
1720
|
joinMetaKey,
|
|
1748
|
-
leaveMetaKey
|
|
1721
|
+
leaveMetaKey,
|
|
1722
|
+
emitDebug
|
|
1749
1723
|
]);
|
|
1750
1724
|
}
|
|
1725
|
+
function useSocketEvent(args) {
|
|
1726
|
+
const {
|
|
1727
|
+
event,
|
|
1728
|
+
onMessage,
|
|
1729
|
+
onCleanup,
|
|
1730
|
+
enabled = true,
|
|
1731
|
+
messageDeduplication,
|
|
1732
|
+
debug
|
|
1733
|
+
} = args;
|
|
1734
|
+
const client = useSocketClient();
|
|
1735
|
+
const onMessageRef = useLatestRef(onMessage);
|
|
1736
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1737
|
+
const messageDeduplicationRef = useLatestRef(messageDeduplication);
|
|
1738
|
+
const debugRef = useLatestRef(debug);
|
|
1739
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1740
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1741
|
+
const seenMessageKeysRef = React2.useRef(/* @__PURE__ */ new Map());
|
|
1742
|
+
React2.useEffect(() => {
|
|
1743
|
+
emitDebug({ type: "lifecycle", phase: "effect_start", event });
|
|
1744
|
+
if (!enabled) return;
|
|
1745
|
+
if (!client) {
|
|
1746
|
+
emitDebug({ type: "lifecycle", phase: "client_missing", event });
|
|
1747
|
+
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1748
|
+
missingClientWarnedRef.current = true;
|
|
1749
|
+
console.warn(`[socket] useSocketEvent("${event}") skipped because SocketClient is null.`);
|
|
1750
|
+
}
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
missingClientWarnedRef.current = false;
|
|
1754
|
+
emitDebug({ type: "subscription", phase: "register", event });
|
|
1755
|
+
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1756
|
+
const dedupeCfg = messageDeduplicationRef.current;
|
|
1757
|
+
if (dedupeCfg) {
|
|
1758
|
+
const ttlMs = Math.max(0, dedupeCfg.ttlMs ?? 1500);
|
|
1759
|
+
const now = Date.now();
|
|
1760
|
+
const dedupeKey = dedupeCfg.key?.(payload, meta) ?? (meta?.envelope ? `${event}|${String(meta.envelope.eventName)}|${String(meta.envelope.sentAt)}|${safeSerialize(payload)}` : `${event}|${safeSerialize(payload)}`);
|
|
1761
|
+
const prev = seenMessageKeysRef.current.get(dedupeKey);
|
|
1762
|
+
if (typeof prev === "number" && now - prev <= ttlMs) {
|
|
1763
|
+
emitDebug({
|
|
1764
|
+
type: "subscription",
|
|
1765
|
+
phase: "message_dropped_duplicate",
|
|
1766
|
+
event,
|
|
1767
|
+
dedupeKey
|
|
1768
|
+
});
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
seenMessageKeysRef.current.set(dedupeKey, now);
|
|
1772
|
+
}
|
|
1773
|
+
emitDebug({ type: "subscription", phase: "message", event });
|
|
1774
|
+
onMessageRef.current(payload, meta);
|
|
1775
|
+
});
|
|
1776
|
+
return () => {
|
|
1777
|
+
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1778
|
+
unsubscribe();
|
|
1779
|
+
onCleanupRef.current?.();
|
|
1780
|
+
emitDebug({ type: "lifecycle", phase: "effect_cleanup", event });
|
|
1781
|
+
};
|
|
1782
|
+
}, [client, enabled, event, emitDebug]);
|
|
1783
|
+
}
|
|
1784
|
+
function useSocketConnection(roomsArgs, eventArgs) {
|
|
1785
|
+
useSocketRooms(roomsArgs);
|
|
1786
|
+
useSocketEvent(eventArgs);
|
|
1787
|
+
}
|
|
1751
1788
|
|
|
1752
1789
|
// src/sockets/socket.client.context.debug.ts
|
|
1753
1790
|
function dbg(dbgOpts, e) {
|
|
@@ -2669,7 +2706,9 @@ function buildSocketProvider(args) {
|
|
|
2669
2706
|
}
|
|
2670
2707
|
),
|
|
2671
2708
|
useSocketClient: () => useSocketClient(),
|
|
2672
|
-
|
|
2709
|
+
useSocketRooms: (p) => useSocketRooms(p),
|
|
2710
|
+
useSocketEvent: (p) => useSocketEvent(p),
|
|
2711
|
+
useSocketConnection: (...args2) => useSocketConnection(...args2)
|
|
2673
2712
|
};
|
|
2674
2713
|
}
|
|
2675
2714
|
function SocketProvider(props) {
|
|
@@ -2884,7 +2923,7 @@ function trackHookTrigger2({
|
|
|
2884
2923
|
}
|
|
2885
2924
|
|
|
2886
2925
|
// src/sockets/socketedRoute/socket.client.helper.rooms.ts
|
|
2887
|
-
function
|
|
2926
|
+
function normalizeRooms2(rooms) {
|
|
2888
2927
|
if (rooms == null) return [];
|
|
2889
2928
|
const list = Array.isArray(rooms) ? rooms : [rooms];
|
|
2890
2929
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2909,7 +2948,7 @@ function roomStateEqual(prev, next) {
|
|
|
2909
2948
|
}
|
|
2910
2949
|
function mergeRoomState(prev, toRoomsResult) {
|
|
2911
2950
|
const merged = new Set(prev.rooms);
|
|
2912
|
-
for (const r of
|
|
2951
|
+
for (const r of normalizeRooms2(toRoomsResult.rooms)) merged.add(r);
|
|
2913
2952
|
return {
|
|
2914
2953
|
rooms: Array.from(merged),
|
|
2915
2954
|
joinMeta: toRoomsResult.joinMeta ?? prev.joinMeta,
|
|
@@ -3270,6 +3309,8 @@ export {
|
|
|
3270
3309
|
createRouteClient,
|
|
3271
3310
|
defaultFetcher,
|
|
3272
3311
|
useSocketClient,
|
|
3273
|
-
useSocketConnection
|
|
3312
|
+
useSocketConnection,
|
|
3313
|
+
useSocketEvent,
|
|
3314
|
+
useSocketRooms
|
|
3274
3315
|
};
|
|
3275
3316
|
//# sourceMappingURL=index.mjs.map
|