@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.cjs
CHANGED
|
@@ -40,7 +40,9 @@ __export(index_exports, {
|
|
|
40
40
|
createRouteClient: () => createRouteClient,
|
|
41
41
|
defaultFetcher: () => defaultFetcher,
|
|
42
42
|
useSocketClient: () => useSocketClient,
|
|
43
|
-
useSocketConnection: () => useSocketConnection
|
|
43
|
+
useSocketConnection: () => useSocketConnection,
|
|
44
|
+
useSocketEvent: () => useSocketEvent,
|
|
45
|
+
useSocketRooms: () => useSocketRooms
|
|
44
46
|
});
|
|
45
47
|
module.exports = __toCommonJS(index_exports);
|
|
46
48
|
|
|
@@ -1589,25 +1591,67 @@ function useSocketClient() {
|
|
|
1589
1591
|
|
|
1590
1592
|
// src/sockets/socket.client.context.connection.ts
|
|
1591
1593
|
var React2 = __toESM(require("react"), 1);
|
|
1592
|
-
function
|
|
1594
|
+
function normalizeRooms(rooms) {
|
|
1595
|
+
if (rooms == null) return [];
|
|
1596
|
+
return Array.isArray(rooms) ? rooms : [rooms];
|
|
1597
|
+
}
|
|
1598
|
+
function safeSerialize(value) {
|
|
1599
|
+
try {
|
|
1600
|
+
return JSON.stringify(value) ?? String(value);
|
|
1601
|
+
} catch {
|
|
1602
|
+
return "[unserializable]";
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
function useLatestRef(value) {
|
|
1606
|
+
const ref = React2.useRef(value);
|
|
1607
|
+
React2.useEffect(() => {
|
|
1608
|
+
ref.current = value;
|
|
1609
|
+
}, [value]);
|
|
1610
|
+
return ref;
|
|
1611
|
+
}
|
|
1612
|
+
function useDebugEmitter(debug) {
|
|
1613
|
+
const debugRef = useLatestRef(debug);
|
|
1614
|
+
return React2.useCallback((event) => {
|
|
1615
|
+
const dbg3 = debugRef.current;
|
|
1616
|
+
if (!dbg3?.enabled) return;
|
|
1617
|
+
if (dbg3[event.type] === false) return;
|
|
1618
|
+
const logger = dbg3.logger;
|
|
1619
|
+
if (logger) {
|
|
1620
|
+
try {
|
|
1621
|
+
logger(event);
|
|
1622
|
+
} catch (error) {
|
|
1623
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1624
|
+
console.warn("[socket] debug logger threw", error);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
if (typeof console !== "undefined" && typeof console.log === "function") {
|
|
1630
|
+
console.log("[socket]", event);
|
|
1631
|
+
}
|
|
1632
|
+
}, []);
|
|
1633
|
+
}
|
|
1634
|
+
function useSocketRooms(args) {
|
|
1593
1635
|
const {
|
|
1594
|
-
event,
|
|
1595
1636
|
rooms,
|
|
1596
|
-
onMessage,
|
|
1597
|
-
onCleanup,
|
|
1598
1637
|
autoJoin = true,
|
|
1599
1638
|
autoLeave = true,
|
|
1639
|
+
enabled = true,
|
|
1640
|
+
onCleanup,
|
|
1600
1641
|
debug
|
|
1601
1642
|
} = args;
|
|
1602
1643
|
const client = useSocketClient();
|
|
1603
|
-
const normalizedRooms = React2.useMemo(
|
|
1604
|
-
() => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms],
|
|
1605
|
-
[rooms]
|
|
1606
|
-
);
|
|
1644
|
+
const normalizedRooms = React2.useMemo(() => normalizeRooms(rooms), [rooms]);
|
|
1607
1645
|
const normalizedRoomsKey = React2.useMemo(
|
|
1608
1646
|
() => normalizedRooms.join(""),
|
|
1609
1647
|
[normalizedRooms]
|
|
1610
1648
|
);
|
|
1649
|
+
const joinMetaRef = useLatestRef(args.joinMeta);
|
|
1650
|
+
const leaveMetaRef = useLatestRef(args.leaveMeta);
|
|
1651
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1652
|
+
const debugRef = useLatestRef(debug);
|
|
1653
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1654
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1611
1655
|
const joinMetaKey = React2.useMemo(
|
|
1612
1656
|
() => JSON.stringify(args.joinMeta ?? null),
|
|
1613
1657
|
[args.joinMeta]
|
|
@@ -1616,107 +1660,48 @@ function useSocketConnection(args) {
|
|
|
1616
1660
|
() => JSON.stringify(args.leaveMeta ?? null),
|
|
1617
1661
|
[args.leaveMeta]
|
|
1618
1662
|
);
|
|
1619
|
-
const missingClientWarnedRef = React2.useRef(false);
|
|
1620
|
-
const onMessageRef = React2.useRef(onMessage);
|
|
1621
|
-
const onCleanupRef = React2.useRef(onCleanup);
|
|
1622
|
-
const joinMetaRef = React2.useRef(args.joinMeta);
|
|
1623
|
-
const leaveMetaRef = React2.useRef(args.leaveMeta);
|
|
1624
|
-
const debugRef = React2.useRef(debug);
|
|
1625
|
-
React2.useEffect(() => {
|
|
1626
|
-
onMessageRef.current = onMessage;
|
|
1627
|
-
}, [onMessage]);
|
|
1628
|
-
React2.useEffect(() => {
|
|
1629
|
-
onCleanupRef.current = onCleanup;
|
|
1630
|
-
}, [onCleanup]);
|
|
1631
|
-
React2.useEffect(() => {
|
|
1632
|
-
joinMetaRef.current = args.joinMeta;
|
|
1633
|
-
}, [args.joinMeta]);
|
|
1634
|
-
React2.useEffect(() => {
|
|
1635
|
-
leaveMetaRef.current = args.leaveMeta;
|
|
1636
|
-
}, [args.leaveMeta]);
|
|
1637
|
-
React2.useEffect(() => {
|
|
1638
|
-
debugRef.current = debug;
|
|
1639
|
-
}, [debug]);
|
|
1640
|
-
const emitDebug = React2.useCallback(
|
|
1641
|
-
(event2) => {
|
|
1642
|
-
const dbg3 = debugRef.current;
|
|
1643
|
-
if (!dbg3?.enabled) return;
|
|
1644
|
-
if (dbg3[event2.type] === false) return;
|
|
1645
|
-
const logger = dbg3.logger;
|
|
1646
|
-
if (logger) {
|
|
1647
|
-
try {
|
|
1648
|
-
logger(event2);
|
|
1649
|
-
} catch (error) {
|
|
1650
|
-
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1651
|
-
console.warn("[socket] useSocketConnection debug logger threw", error);
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
return;
|
|
1655
|
-
}
|
|
1656
|
-
if (typeof console !== "undefined" && typeof console.log === "function") {
|
|
1657
|
-
console.log("[socket] useSocketConnection", event2);
|
|
1658
|
-
}
|
|
1659
|
-
},
|
|
1660
|
-
[]
|
|
1661
|
-
);
|
|
1662
|
-
const reportAsyncError = React2.useCallback(
|
|
1663
|
-
(phase, error) => {
|
|
1664
|
-
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1665
|
-
console.warn(`[socket] useSocketConnection ${phase} failed`, error);
|
|
1666
|
-
}
|
|
1667
|
-
},
|
|
1668
|
-
[]
|
|
1669
|
-
);
|
|
1670
1663
|
React2.useEffect(() => {
|
|
1671
1664
|
emitDebug({
|
|
1672
1665
|
type: "lifecycle",
|
|
1673
1666
|
phase: "effect_start",
|
|
1674
|
-
event,
|
|
1675
1667
|
rooms: normalizedRooms,
|
|
1676
1668
|
autoJoin,
|
|
1677
1669
|
autoLeave
|
|
1678
1670
|
});
|
|
1671
|
+
if (!enabled) {
|
|
1672
|
+
emitDebug({
|
|
1673
|
+
type: "room",
|
|
1674
|
+
phase: "join_skip",
|
|
1675
|
+
rooms: normalizedRooms,
|
|
1676
|
+
reason: "disabled"
|
|
1677
|
+
});
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1679
1680
|
if (!client) {
|
|
1680
1681
|
emitDebug({
|
|
1681
1682
|
type: "lifecycle",
|
|
1682
1683
|
phase: "client_missing",
|
|
1683
|
-
event,
|
|
1684
1684
|
rooms: normalizedRooms,
|
|
1685
1685
|
autoJoin,
|
|
1686
1686
|
autoLeave
|
|
1687
1687
|
});
|
|
1688
|
-
if (debugRef.current?.throwIfClientMissing) {
|
|
1689
|
-
throw new Error(
|
|
1690
|
-
`useSocketConnection("${event}") missing SocketClient. Wrap with <SocketProvider>.`
|
|
1691
|
-
);
|
|
1692
|
-
}
|
|
1693
1688
|
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1694
1689
|
missingClientWarnedRef.current = true;
|
|
1695
|
-
console.warn(
|
|
1696
|
-
`[socket] useSocketConnection("${event}") skipped because SocketClient is null.`
|
|
1697
|
-
);
|
|
1690
|
+
console.warn("[socket] useSocketRooms skipped because SocketClient is null.");
|
|
1698
1691
|
}
|
|
1699
1692
|
return;
|
|
1700
1693
|
}
|
|
1701
1694
|
missingClientWarnedRef.current = false;
|
|
1702
|
-
emitDebug({ type: "subscription", phase: "register", event });
|
|
1703
1695
|
if (autoJoin && normalizedRooms.length > 0) {
|
|
1704
|
-
emitDebug({
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
rooms: normalizedRooms
|
|
1708
|
-
});
|
|
1709
|
-
void client.joinRooms(normalizedRooms, joinMetaRef.current).then(() => {
|
|
1710
|
-
emitDebug({ type: "room", phase: "join_ok", rooms: normalizedRooms });
|
|
1711
|
-
}).catch((error) => {
|
|
1712
|
-
emitDebug({
|
|
1696
|
+
emitDebug({ type: "room", phase: "join_attempt", rooms: normalizedRooms });
|
|
1697
|
+
void client.joinRooms(normalizedRooms, joinMetaRef.current).then(() => emitDebug({ type: "room", phase: "join_ok", rooms: normalizedRooms })).catch(
|
|
1698
|
+
(error) => emitDebug({
|
|
1713
1699
|
type: "room",
|
|
1714
1700
|
phase: "join_error",
|
|
1715
1701
|
rooms: normalizedRooms,
|
|
1716
1702
|
err: String(error)
|
|
1717
|
-
})
|
|
1718
|
-
|
|
1719
|
-
});
|
|
1703
|
+
})
|
|
1704
|
+
);
|
|
1720
1705
|
} else {
|
|
1721
1706
|
emitDebug({
|
|
1722
1707
|
type: "room",
|
|
@@ -1725,30 +1710,23 @@ function useSocketConnection(args) {
|
|
|
1725
1710
|
reason: autoJoin ? "no_rooms" : "auto_disabled"
|
|
1726
1711
|
});
|
|
1727
1712
|
}
|
|
1728
|
-
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1729
|
-
emitDebug({ type: "subscription", phase: "message", event });
|
|
1730
|
-
onMessageRef.current(payload, meta);
|
|
1731
|
-
});
|
|
1732
1713
|
return () => {
|
|
1733
|
-
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1734
|
-
unsubscribe();
|
|
1735
1714
|
if (autoLeave && normalizedRooms.length > 0) {
|
|
1736
1715
|
emitDebug({
|
|
1737
1716
|
type: "room",
|
|
1738
1717
|
phase: "leave_attempt",
|
|
1739
1718
|
rooms: normalizedRooms
|
|
1740
1719
|
});
|
|
1741
|
-
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1742
|
-
emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1743
|
-
|
|
1744
|
-
emitDebug({
|
|
1720
|
+
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1721
|
+
() => emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1722
|
+
).catch(
|
|
1723
|
+
(error) => emitDebug({
|
|
1745
1724
|
type: "room",
|
|
1746
1725
|
phase: "leave_error",
|
|
1747
1726
|
rooms: normalizedRooms,
|
|
1748
1727
|
err: String(error)
|
|
1749
|
-
})
|
|
1750
|
-
|
|
1751
|
-
});
|
|
1728
|
+
})
|
|
1729
|
+
);
|
|
1752
1730
|
} else {
|
|
1753
1731
|
emitDebug({
|
|
1754
1732
|
type: "room",
|
|
@@ -1757,11 +1735,10 @@ function useSocketConnection(args) {
|
|
|
1757
1735
|
reason: autoLeave ? "no_rooms" : "auto_disabled"
|
|
1758
1736
|
});
|
|
1759
1737
|
}
|
|
1760
|
-
|
|
1738
|
+
onCleanupRef.current?.();
|
|
1761
1739
|
emitDebug({
|
|
1762
1740
|
type: "lifecycle",
|
|
1763
1741
|
phase: "effect_cleanup",
|
|
1764
|
-
event,
|
|
1765
1742
|
rooms: normalizedRooms,
|
|
1766
1743
|
autoJoin,
|
|
1767
1744
|
autoLeave
|
|
@@ -1769,16 +1746,78 @@ function useSocketConnection(args) {
|
|
|
1769
1746
|
};
|
|
1770
1747
|
}, [
|
|
1771
1748
|
client,
|
|
1772
|
-
|
|
1749
|
+
enabled,
|
|
1773
1750
|
autoJoin,
|
|
1774
1751
|
autoLeave,
|
|
1775
|
-
emitDebug,
|
|
1776
|
-
reportAsyncError,
|
|
1777
1752
|
normalizedRoomsKey,
|
|
1778
1753
|
joinMetaKey,
|
|
1779
|
-
leaveMetaKey
|
|
1754
|
+
leaveMetaKey,
|
|
1755
|
+
emitDebug
|
|
1780
1756
|
]);
|
|
1781
1757
|
}
|
|
1758
|
+
function useSocketEvent(args) {
|
|
1759
|
+
const {
|
|
1760
|
+
event,
|
|
1761
|
+
onMessage,
|
|
1762
|
+
onCleanup,
|
|
1763
|
+
enabled = true,
|
|
1764
|
+
messageDeduplication,
|
|
1765
|
+
debug
|
|
1766
|
+
} = args;
|
|
1767
|
+
const client = useSocketClient();
|
|
1768
|
+
const onMessageRef = useLatestRef(onMessage);
|
|
1769
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1770
|
+
const messageDeduplicationRef = useLatestRef(messageDeduplication);
|
|
1771
|
+
const debugRef = useLatestRef(debug);
|
|
1772
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1773
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1774
|
+
const seenMessageKeysRef = React2.useRef(/* @__PURE__ */ new Map());
|
|
1775
|
+
React2.useEffect(() => {
|
|
1776
|
+
emitDebug({ type: "lifecycle", phase: "effect_start", event });
|
|
1777
|
+
if (!enabled) return;
|
|
1778
|
+
if (!client) {
|
|
1779
|
+
emitDebug({ type: "lifecycle", phase: "client_missing", event });
|
|
1780
|
+
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1781
|
+
missingClientWarnedRef.current = true;
|
|
1782
|
+
console.warn(`[socket] useSocketEvent("${event}") skipped because SocketClient is null.`);
|
|
1783
|
+
}
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
missingClientWarnedRef.current = false;
|
|
1787
|
+
emitDebug({ type: "subscription", phase: "register", event });
|
|
1788
|
+
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1789
|
+
const dedupeCfg = messageDeduplicationRef.current;
|
|
1790
|
+
if (dedupeCfg) {
|
|
1791
|
+
const ttlMs = Math.max(0, dedupeCfg.ttlMs ?? 1500);
|
|
1792
|
+
const now = Date.now();
|
|
1793
|
+
const dedupeKey = dedupeCfg.key?.(payload, meta) ?? (meta?.envelope ? `${event}|${String(meta.envelope.eventName)}|${String(meta.envelope.sentAt)}|${safeSerialize(payload)}` : `${event}|${safeSerialize(payload)}`);
|
|
1794
|
+
const prev = seenMessageKeysRef.current.get(dedupeKey);
|
|
1795
|
+
if (typeof prev === "number" && now - prev <= ttlMs) {
|
|
1796
|
+
emitDebug({
|
|
1797
|
+
type: "subscription",
|
|
1798
|
+
phase: "message_dropped_duplicate",
|
|
1799
|
+
event,
|
|
1800
|
+
dedupeKey
|
|
1801
|
+
});
|
|
1802
|
+
return;
|
|
1803
|
+
}
|
|
1804
|
+
seenMessageKeysRef.current.set(dedupeKey, now);
|
|
1805
|
+
}
|
|
1806
|
+
emitDebug({ type: "subscription", phase: "message", event });
|
|
1807
|
+
onMessageRef.current(payload, meta);
|
|
1808
|
+
});
|
|
1809
|
+
return () => {
|
|
1810
|
+
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1811
|
+
unsubscribe();
|
|
1812
|
+
onCleanupRef.current?.();
|
|
1813
|
+
emitDebug({ type: "lifecycle", phase: "effect_cleanup", event });
|
|
1814
|
+
};
|
|
1815
|
+
}, [client, enabled, event, emitDebug]);
|
|
1816
|
+
}
|
|
1817
|
+
function useSocketConnection(roomsArgs, eventArgs) {
|
|
1818
|
+
useSocketRooms(roomsArgs);
|
|
1819
|
+
useSocketEvent(eventArgs);
|
|
1820
|
+
}
|
|
1782
1821
|
|
|
1783
1822
|
// src/sockets/socket.client.context.debug.ts
|
|
1784
1823
|
function dbg(dbgOpts, e) {
|
|
@@ -2700,7 +2739,9 @@ function buildSocketProvider(args) {
|
|
|
2700
2739
|
}
|
|
2701
2740
|
),
|
|
2702
2741
|
useSocketClient: () => useSocketClient(),
|
|
2703
|
-
|
|
2742
|
+
useSocketRooms: (p) => useSocketRooms(p),
|
|
2743
|
+
useSocketEvent: (p) => useSocketEvent(p),
|
|
2744
|
+
useSocketConnection: (...args2) => useSocketConnection(...args2)
|
|
2704
2745
|
};
|
|
2705
2746
|
}
|
|
2706
2747
|
function SocketProvider(props) {
|
|
@@ -2915,7 +2956,7 @@ function trackHookTrigger2({
|
|
|
2915
2956
|
}
|
|
2916
2957
|
|
|
2917
2958
|
// src/sockets/socketedRoute/socket.client.helper.rooms.ts
|
|
2918
|
-
function
|
|
2959
|
+
function normalizeRooms2(rooms) {
|
|
2919
2960
|
if (rooms == null) return [];
|
|
2920
2961
|
const list = Array.isArray(rooms) ? rooms : [rooms];
|
|
2921
2962
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2940,7 +2981,7 @@ function roomStateEqual(prev, next) {
|
|
|
2940
2981
|
}
|
|
2941
2982
|
function mergeRoomState(prev, toRoomsResult) {
|
|
2942
2983
|
const merged = new Set(prev.rooms);
|
|
2943
|
-
for (const r of
|
|
2984
|
+
for (const r of normalizeRooms2(toRoomsResult.rooms)) merged.add(r);
|
|
2944
2985
|
return {
|
|
2945
2986
|
rooms: Array.from(merged),
|
|
2946
2987
|
joinMeta: toRoomsResult.joinMeta ?? prev.joinMeta,
|
|
@@ -3302,6 +3343,8 @@ function buildSocketedRoute(options) {
|
|
|
3302
3343
|
createRouteClient,
|
|
3303
3344
|
defaultFetcher,
|
|
3304
3345
|
useSocketClient,
|
|
3305
|
-
useSocketConnection
|
|
3346
|
+
useSocketConnection,
|
|
3347
|
+
useSocketEvent,
|
|
3348
|
+
useSocketRooms
|
|
3306
3349
|
});
|
|
3307
3350
|
//# sourceMappingURL=index.cjs.map
|