@emeryld/rrroutes-client 2.7.12 → 2.8.0
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 +161 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +160 -106
- package/dist/index.mjs.map +1 -1
- package/dist/routesV3.client.types.d.ts +7 -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
|
@@ -39,8 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
buildSocketedRoute: () => buildSocketedRoute,
|
|
40
40
|
createRouteClient: () => createRouteClient,
|
|
41
41
|
defaultFetcher: () => defaultFetcher,
|
|
42
|
-
useSocketClient: () => useSocketClient
|
|
43
|
-
useSocketConnection: () => useSocketConnection
|
|
42
|
+
useSocketClient: () => useSocketClient
|
|
44
43
|
});
|
|
45
44
|
module.exports = __toCommonJS(index_exports);
|
|
46
45
|
|
|
@@ -1479,6 +1478,12 @@ function createRouteClient(opts) {
|
|
|
1479
1478
|
configurable: false,
|
|
1480
1479
|
writable: false
|
|
1481
1480
|
});
|
|
1481
|
+
Object.defineProperty(built, "metadata", {
|
|
1482
|
+
value: { leaf },
|
|
1483
|
+
enumerable: true,
|
|
1484
|
+
configurable: false,
|
|
1485
|
+
writable: false
|
|
1486
|
+
});
|
|
1482
1487
|
return built;
|
|
1483
1488
|
}
|
|
1484
1489
|
const fetchRaw = async (input) => {
|
|
@@ -1589,25 +1594,76 @@ function useSocketClient() {
|
|
|
1589
1594
|
|
|
1590
1595
|
// src/sockets/socket.client.context.connection.ts
|
|
1591
1596
|
var React2 = __toESM(require("react"), 1);
|
|
1592
|
-
function
|
|
1597
|
+
function normalizeRooms(rooms) {
|
|
1598
|
+
if (rooms == null) return [];
|
|
1599
|
+
return Array.isArray(rooms) ? rooms : [rooms];
|
|
1600
|
+
}
|
|
1601
|
+
function safeSerialize(value) {
|
|
1602
|
+
try {
|
|
1603
|
+
return JSON.stringify(value) ?? String(value);
|
|
1604
|
+
} catch {
|
|
1605
|
+
return "[unserializable]";
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
function derivePayloadIdentity(payload) {
|
|
1609
|
+
if (!payload || typeof payload !== "object") return void 0;
|
|
1610
|
+
const record = payload;
|
|
1611
|
+
const idCandidate = record.id ?? record._id ?? record.notificationId ?? record.uuid ?? record.key;
|
|
1612
|
+
if (typeof idCandidate === "string" || typeof idCandidate === "number" || typeof idCandidate === "bigint") {
|
|
1613
|
+
return String(idCandidate);
|
|
1614
|
+
}
|
|
1615
|
+
return void 0;
|
|
1616
|
+
}
|
|
1617
|
+
function useLatestRef(value) {
|
|
1618
|
+
const ref = React2.useRef(value);
|
|
1619
|
+
React2.useEffect(() => {
|
|
1620
|
+
ref.current = value;
|
|
1621
|
+
}, [value]);
|
|
1622
|
+
return ref;
|
|
1623
|
+
}
|
|
1624
|
+
function useDebugEmitter(debug) {
|
|
1625
|
+
const debugRef = useLatestRef(debug);
|
|
1626
|
+
return React2.useCallback((event) => {
|
|
1627
|
+
const dbg3 = debugRef.current;
|
|
1628
|
+
if (!dbg3?.enabled) return;
|
|
1629
|
+
if (dbg3[event.type] === false) return;
|
|
1630
|
+
const logger = dbg3.logger;
|
|
1631
|
+
if (logger) {
|
|
1632
|
+
try {
|
|
1633
|
+
logger(event);
|
|
1634
|
+
} catch (error) {
|
|
1635
|
+
if (typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1636
|
+
console.warn("[socket] debug logger threw", error);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
if (typeof console !== "undefined" && typeof console.log === "function") {
|
|
1642
|
+
console.log("[socket]", event);
|
|
1643
|
+
}
|
|
1644
|
+
}, []);
|
|
1645
|
+
}
|
|
1646
|
+
function useSocketRooms(args) {
|
|
1593
1647
|
const {
|
|
1594
|
-
event,
|
|
1595
1648
|
rooms,
|
|
1596
|
-
onMessage,
|
|
1597
|
-
onCleanup,
|
|
1598
1649
|
autoJoin = true,
|
|
1599
1650
|
autoLeave = true,
|
|
1651
|
+
enabled = true,
|
|
1652
|
+
onCleanup,
|
|
1600
1653
|
debug
|
|
1601
1654
|
} = args;
|
|
1602
1655
|
const client = useSocketClient();
|
|
1603
|
-
const normalizedRooms = React2.useMemo(
|
|
1604
|
-
() => rooms == null ? [] : Array.isArray(rooms) ? rooms : [rooms],
|
|
1605
|
-
[rooms]
|
|
1606
|
-
);
|
|
1656
|
+
const normalizedRooms = React2.useMemo(() => normalizeRooms(rooms), [rooms]);
|
|
1607
1657
|
const normalizedRoomsKey = React2.useMemo(
|
|
1608
1658
|
() => normalizedRooms.join(""),
|
|
1609
1659
|
[normalizedRooms]
|
|
1610
1660
|
);
|
|
1661
|
+
const joinMetaRef = useLatestRef(args.joinMeta);
|
|
1662
|
+
const leaveMetaRef = useLatestRef(args.leaveMeta);
|
|
1663
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1664
|
+
const debugRef = useLatestRef(debug);
|
|
1665
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1666
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1611
1667
|
const joinMetaKey = React2.useMemo(
|
|
1612
1668
|
() => JSON.stringify(args.joinMeta ?? null),
|
|
1613
1669
|
[args.joinMeta]
|
|
@@ -1616,107 +1672,48 @@ function useSocketConnection(args) {
|
|
|
1616
1672
|
() => JSON.stringify(args.leaveMeta ?? null),
|
|
1617
1673
|
[args.leaveMeta]
|
|
1618
1674
|
);
|
|
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
1675
|
React2.useEffect(() => {
|
|
1671
1676
|
emitDebug({
|
|
1672
1677
|
type: "lifecycle",
|
|
1673
1678
|
phase: "effect_start",
|
|
1674
|
-
event,
|
|
1675
1679
|
rooms: normalizedRooms,
|
|
1676
1680
|
autoJoin,
|
|
1677
1681
|
autoLeave
|
|
1678
1682
|
});
|
|
1683
|
+
if (!enabled) {
|
|
1684
|
+
emitDebug({
|
|
1685
|
+
type: "room",
|
|
1686
|
+
phase: "join_skip",
|
|
1687
|
+
rooms: normalizedRooms,
|
|
1688
|
+
reason: "disabled"
|
|
1689
|
+
});
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1679
1692
|
if (!client) {
|
|
1680
1693
|
emitDebug({
|
|
1681
1694
|
type: "lifecycle",
|
|
1682
1695
|
phase: "client_missing",
|
|
1683
|
-
event,
|
|
1684
1696
|
rooms: normalizedRooms,
|
|
1685
1697
|
autoJoin,
|
|
1686
1698
|
autoLeave
|
|
1687
1699
|
});
|
|
1688
|
-
if (debugRef.current?.throwIfClientMissing) {
|
|
1689
|
-
throw new Error(
|
|
1690
|
-
`useSocketConnection("${event}") missing SocketClient. Wrap with <SocketProvider>.`
|
|
1691
|
-
);
|
|
1692
|
-
}
|
|
1693
1700
|
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1694
1701
|
missingClientWarnedRef.current = true;
|
|
1695
|
-
console.warn(
|
|
1696
|
-
`[socket] useSocketConnection("${event}") skipped because SocketClient is null.`
|
|
1697
|
-
);
|
|
1702
|
+
console.warn("[socket] useSocketRooms skipped because SocketClient is null.");
|
|
1698
1703
|
}
|
|
1699
1704
|
return;
|
|
1700
1705
|
}
|
|
1701
1706
|
missingClientWarnedRef.current = false;
|
|
1702
|
-
emitDebug({ type: "subscription", phase: "register", event });
|
|
1703
1707
|
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({
|
|
1708
|
+
emitDebug({ type: "room", phase: "join_attempt", rooms: normalizedRooms });
|
|
1709
|
+
void client.joinRooms(normalizedRooms, joinMetaRef.current).then(() => emitDebug({ type: "room", phase: "join_ok", rooms: normalizedRooms })).catch(
|
|
1710
|
+
(error) => emitDebug({
|
|
1713
1711
|
type: "room",
|
|
1714
1712
|
phase: "join_error",
|
|
1715
1713
|
rooms: normalizedRooms,
|
|
1716
1714
|
err: String(error)
|
|
1717
|
-
})
|
|
1718
|
-
|
|
1719
|
-
});
|
|
1715
|
+
})
|
|
1716
|
+
);
|
|
1720
1717
|
} else {
|
|
1721
1718
|
emitDebug({
|
|
1722
1719
|
type: "room",
|
|
@@ -1725,30 +1722,23 @@ function useSocketConnection(args) {
|
|
|
1725
1722
|
reason: autoJoin ? "no_rooms" : "auto_disabled"
|
|
1726
1723
|
});
|
|
1727
1724
|
}
|
|
1728
|
-
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1729
|
-
emitDebug({ type: "subscription", phase: "message", event });
|
|
1730
|
-
onMessageRef.current(payload, meta);
|
|
1731
|
-
});
|
|
1732
1725
|
return () => {
|
|
1733
|
-
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1734
|
-
unsubscribe();
|
|
1735
1726
|
if (autoLeave && normalizedRooms.length > 0) {
|
|
1736
1727
|
emitDebug({
|
|
1737
1728
|
type: "room",
|
|
1738
1729
|
phase: "leave_attempt",
|
|
1739
1730
|
rooms: normalizedRooms
|
|
1740
1731
|
});
|
|
1741
|
-
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1742
|
-
emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1743
|
-
|
|
1744
|
-
emitDebug({
|
|
1732
|
+
void client.leaveRooms(normalizedRooms, leaveMetaRef.current).then(
|
|
1733
|
+
() => emitDebug({ type: "room", phase: "leave_ok", rooms: normalizedRooms })
|
|
1734
|
+
).catch(
|
|
1735
|
+
(error) => emitDebug({
|
|
1745
1736
|
type: "room",
|
|
1746
1737
|
phase: "leave_error",
|
|
1747
1738
|
rooms: normalizedRooms,
|
|
1748
1739
|
err: String(error)
|
|
1749
|
-
})
|
|
1750
|
-
|
|
1751
|
-
});
|
|
1740
|
+
})
|
|
1741
|
+
);
|
|
1752
1742
|
} else {
|
|
1753
1743
|
emitDebug({
|
|
1754
1744
|
type: "room",
|
|
@@ -1757,11 +1747,10 @@ function useSocketConnection(args) {
|
|
|
1757
1747
|
reason: autoLeave ? "no_rooms" : "auto_disabled"
|
|
1758
1748
|
});
|
|
1759
1749
|
}
|
|
1760
|
-
|
|
1750
|
+
onCleanupRef.current?.();
|
|
1761
1751
|
emitDebug({
|
|
1762
1752
|
type: "lifecycle",
|
|
1763
1753
|
phase: "effect_cleanup",
|
|
1764
|
-
event,
|
|
1765
1754
|
rooms: normalizedRooms,
|
|
1766
1755
|
autoJoin,
|
|
1767
1756
|
autoLeave
|
|
@@ -1769,16 +1758,79 @@ function useSocketConnection(args) {
|
|
|
1769
1758
|
};
|
|
1770
1759
|
}, [
|
|
1771
1760
|
client,
|
|
1772
|
-
|
|
1761
|
+
enabled,
|
|
1773
1762
|
autoJoin,
|
|
1774
1763
|
autoLeave,
|
|
1775
|
-
emitDebug,
|
|
1776
|
-
reportAsyncError,
|
|
1777
1764
|
normalizedRoomsKey,
|
|
1778
1765
|
joinMetaKey,
|
|
1779
|
-
leaveMetaKey
|
|
1766
|
+
leaveMetaKey,
|
|
1767
|
+
emitDebug
|
|
1780
1768
|
]);
|
|
1781
1769
|
}
|
|
1770
|
+
function useSocketEvent(args) {
|
|
1771
|
+
const {
|
|
1772
|
+
event,
|
|
1773
|
+
onMessage,
|
|
1774
|
+
onCleanup,
|
|
1775
|
+
enabled = true,
|
|
1776
|
+
messageDeduplication,
|
|
1777
|
+
debug
|
|
1778
|
+
} = args;
|
|
1779
|
+
const client = useSocketClient();
|
|
1780
|
+
const onMessageRef = useLatestRef(onMessage);
|
|
1781
|
+
const onCleanupRef = useLatestRef(onCleanup);
|
|
1782
|
+
const messageDeduplicationRef = useLatestRef(messageDeduplication);
|
|
1783
|
+
const debugRef = useLatestRef(debug);
|
|
1784
|
+
const emitDebug = useDebugEmitter(debug);
|
|
1785
|
+
const missingClientWarnedRef = React2.useRef(false);
|
|
1786
|
+
const seenMessageKeysRef = React2.useRef(/* @__PURE__ */ new Map());
|
|
1787
|
+
React2.useEffect(() => {
|
|
1788
|
+
emitDebug({ type: "lifecycle", phase: "effect_start", event });
|
|
1789
|
+
if (!enabled) return;
|
|
1790
|
+
if (!client) {
|
|
1791
|
+
emitDebug({ type: "lifecycle", phase: "client_missing", event });
|
|
1792
|
+
if (debugRef.current?.warnIfClientMissing && !missingClientWarnedRef.current && typeof console !== "undefined" && typeof console.warn === "function") {
|
|
1793
|
+
missingClientWarnedRef.current = true;
|
|
1794
|
+
console.warn(`[socket] useSocketEvent("${event}") skipped because SocketClient is null.`);
|
|
1795
|
+
}
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
missingClientWarnedRef.current = false;
|
|
1799
|
+
emitDebug({ type: "subscription", phase: "register", event });
|
|
1800
|
+
const unsubscribe = client.on(event, (payload, meta) => {
|
|
1801
|
+
const dedupeCfg = messageDeduplicationRef.current;
|
|
1802
|
+
if (dedupeCfg !== false) {
|
|
1803
|
+
const ttlMs = Math.max(0, dedupeCfg?.ttlMs ?? 2500);
|
|
1804
|
+
const now = Date.now();
|
|
1805
|
+
const payloadId = derivePayloadIdentity(payload);
|
|
1806
|
+
const dedupeKey = dedupeCfg?.key?.(payload, meta) ?? (payloadId ? `${event}|payload:${payloadId}` : void 0) ?? (meta?.envelope ? `${event}|${String(meta.envelope.eventName)}|${String(meta.envelope.sentAt)}|${safeSerialize(payload)}` : `${event}|${safeSerialize(payload)}`);
|
|
1807
|
+
const prev = seenMessageKeysRef.current.get(dedupeKey);
|
|
1808
|
+
if (typeof prev === "number" && now - prev <= ttlMs) {
|
|
1809
|
+
emitDebug({
|
|
1810
|
+
type: "subscription",
|
|
1811
|
+
phase: "message_dropped_duplicate",
|
|
1812
|
+
event,
|
|
1813
|
+
dedupeKey
|
|
1814
|
+
});
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
seenMessageKeysRef.current.set(dedupeKey, now);
|
|
1818
|
+
}
|
|
1819
|
+
emitDebug({ type: "subscription", phase: "message", event });
|
|
1820
|
+
onMessageRef.current(payload, meta);
|
|
1821
|
+
});
|
|
1822
|
+
return () => {
|
|
1823
|
+
emitDebug({ type: "subscription", phase: "unregister", event });
|
|
1824
|
+
unsubscribe();
|
|
1825
|
+
onCleanupRef.current?.();
|
|
1826
|
+
emitDebug({ type: "lifecycle", phase: "effect_cleanup", event });
|
|
1827
|
+
};
|
|
1828
|
+
}, [client, enabled, event, emitDebug]);
|
|
1829
|
+
}
|
|
1830
|
+
function useSocketConnection(roomsArgs, eventArgs) {
|
|
1831
|
+
useSocketRooms(roomsArgs);
|
|
1832
|
+
useSocketEvent(eventArgs);
|
|
1833
|
+
}
|
|
1782
1834
|
|
|
1783
1835
|
// src/sockets/socket.client.context.debug.ts
|
|
1784
1836
|
function dbg(dbgOpts, e) {
|
|
@@ -2700,7 +2752,9 @@ function buildSocketProvider(args) {
|
|
|
2700
2752
|
}
|
|
2701
2753
|
),
|
|
2702
2754
|
useSocketClient: () => useSocketClient(),
|
|
2703
|
-
|
|
2755
|
+
useSocketRooms: (p) => useSocketRooms(p),
|
|
2756
|
+
useSocketEvent: (p) => useSocketEvent(p),
|
|
2757
|
+
useSocketConnection: (...args2) => useSocketConnection(...args2)
|
|
2704
2758
|
};
|
|
2705
2759
|
}
|
|
2706
2760
|
function SocketProvider(props) {
|
|
@@ -2915,7 +2969,7 @@ function trackHookTrigger2({
|
|
|
2915
2969
|
}
|
|
2916
2970
|
|
|
2917
2971
|
// src/sockets/socketedRoute/socket.client.helper.rooms.ts
|
|
2918
|
-
function
|
|
2972
|
+
function normalizeRooms2(rooms) {
|
|
2919
2973
|
if (rooms == null) return [];
|
|
2920
2974
|
const list = Array.isArray(rooms) ? rooms : [rooms];
|
|
2921
2975
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2940,7 +2994,7 @@ function roomStateEqual(prev, next) {
|
|
|
2940
2994
|
}
|
|
2941
2995
|
function mergeRoomState(prev, toRoomsResult) {
|
|
2942
2996
|
const merged = new Set(prev.rooms);
|
|
2943
|
-
for (const r of
|
|
2997
|
+
for (const r of normalizeRooms2(toRoomsResult.rooms)) merged.add(r);
|
|
2944
2998
|
return {
|
|
2945
2999
|
rooms: Array.from(merged),
|
|
2946
3000
|
joinMeta: toRoomsResult.joinMeta ?? prev.joinMeta,
|
|
@@ -3301,7 +3355,6 @@ function buildSocketedRoute(options) {
|
|
|
3301
3355
|
buildSocketedRoute,
|
|
3302
3356
|
createRouteClient,
|
|
3303
3357
|
defaultFetcher,
|
|
3304
|
-
useSocketClient
|
|
3305
|
-
useSocketConnection
|
|
3358
|
+
useSocketClient
|
|
3306
3359
|
});
|
|
3307
3360
|
//# sourceMappingURL=index.cjs.map
|