@novu/react 3.18.1 → 3.18.2
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/cjs/hooks/internal/useWebsocketEvent.cjs +4 -1
- package/dist/cjs/hooks/internal/useWebsocketEvent.cjs.map +1 -1
- package/dist/cjs/utils/requestLock.cjs +6 -1
- package/dist/cjs/utils/requestLock.cjs.map +1 -1
- package/dist/cjs/utils/requestLock.d.cts +2 -1
- package/dist/esm/hooks/internal/useWebsocketEvent.js +5 -2
- package/dist/esm/hooks/internal/useWebsocketEvent.js.map +1 -1
- package/dist/esm/utils/requestLock.d.ts +2 -1
- package/dist/esm/utils/requestLock.js +5 -1
- package/dist/esm/utils/requestLock.js.map +1 -1
- package/package.json +2 -2
|
@@ -39,9 +39,12 @@ var useWebSocketEvent = ({
|
|
|
39
39
|
onMessage,
|
|
40
40
|
enabled
|
|
41
41
|
});
|
|
42
|
+
const shouldBroadcast = (0, import_requestLock.isWebLocksSupported)();
|
|
42
43
|
const updateReadCount = (data) => {
|
|
43
44
|
onMessage(data);
|
|
44
|
-
|
|
45
|
+
if (shouldBroadcast) {
|
|
46
|
+
postMessage(data);
|
|
47
|
+
}
|
|
45
48
|
};
|
|
46
49
|
(0, import_react.useEffect)(() => {
|
|
47
50
|
if (!enabled) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { requestLock } from '../../utils/requestLock';\nimport { useNovu } from '../NovuProvider';\nimport { useBrowserTabsChannel } from './useBrowserTabsChannel';\n\nexport const useWebSocketEvent = <E extends SocketEventNames>({\n event: webSocketEvent,\n eventHandler: onMessage,\n enabled = true,\n}: {\n event: E;\n eventHandler: (args: Events[E]) => void;\n enabled?: boolean;\n}) => {\n const novu = useNovu();\n const channelName = `nv_ws_connection:a=${novu.applicationIdentifier}:s=${novu.subscriberId}:c=${novu.contextKey}:e=${webSocketEvent}`;\n\n const { postMessage } = useBrowserTabsChannel({\n channelName,\n onMessage,\n enabled,\n });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n if (!enabled) return;\n\n let cleanup: () => void;\n const resolveLock = requestLock(channelName, () => {\n cleanup = novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n\n resolveLock();\n };\n }, [enabled]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0B;AAC1B,
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { isWebLocksSupported, requestLock } from '../../utils/requestLock';\nimport { useNovu } from '../NovuProvider';\nimport { useBrowserTabsChannel } from './useBrowserTabsChannel';\n\nexport const useWebSocketEvent = <E extends SocketEventNames>({\n event: webSocketEvent,\n eventHandler: onMessage,\n enabled = true,\n}: {\n event: E;\n eventHandler: (args: Events[E]) => void;\n enabled?: boolean;\n}) => {\n const novu = useNovu();\n const channelName = `nv_ws_connection:a=${novu.applicationIdentifier}:s=${novu.subscriberId}:c=${novu.contextKey}:e=${webSocketEvent}`;\n\n const { postMessage } = useBrowserTabsChannel({\n channelName,\n onMessage,\n enabled,\n });\n\n // When Web Locks are unavailable, requestLock runs the callback in every tab,\n // so each tab already receives the event through its own socket. Re-broadcasting\n // in that case would duplicate the event across tabs (count multiplied by tab\n // count). Only the exclusive lock owner should fan out to the other tabs.\n const shouldBroadcast = isWebLocksSupported();\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n if (shouldBroadcast) {\n postMessage(data);\n }\n };\n\n useEffect(() => {\n if (!enabled) return;\n\n let cleanup: () => void;\n const resolveLock = requestLock(channelName, () => {\n cleanup = novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n\n resolveLock();\n };\n }, [enabled]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAA0B;AAC1B,yBAAiD;AACjD,0BAAwB;AACxB,mCAAsC;AAE/B,IAAM,oBAAoB,CAA6B;AAAA,EAC5D,OAAO;AAAA,EACP,cAAc;AAAA,EACd,UAAU;AACZ,MAIM;AACJ,QAAM,WAAO,6BAAQ;AACrB,QAAM,cAAc,sBAAsB,KAAK,qBAAqB,MAAM,KAAK,YAAY,MAAM,KAAK,UAAU,MAAM,cAAc;AAEpI,QAAM,EAAE,YAAY,QAAI,oDAAsB;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAMD,QAAM,sBAAkB,wCAAoB;AAC5C,QAAM,kBAA2C,CAAC,SAAS;AACzD,cAAU,IAAI;AACd,QAAI,iBAAiB;AACnB,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,8BAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,QAAI;AACJ,UAAM,kBAAc,gCAAY,aAAa,MAAM;AACjD,gBAAU,KAAK,GAAG,gBAAgB,eAAe;AAAA,IACnD,CAAC;AAED,WAAO,MAAM;AACX,UAAI,SAAS;AACX,gBAAQ;AAAA,MACV;AAEA,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AACd;","names":[]}
|
|
@@ -20,11 +20,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/utils/requestLock.ts
|
|
21
21
|
var requestLock_exports = {};
|
|
22
22
|
__export(requestLock_exports, {
|
|
23
|
+
isWebLocksSupported: () => isWebLocksSupported,
|
|
23
24
|
requestLock: () => requestLock
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(requestLock_exports);
|
|
27
|
+
function isWebLocksSupported() {
|
|
28
|
+
return typeof navigator !== "undefined" && "locks" in navigator && !!navigator.locks;
|
|
29
|
+
}
|
|
26
30
|
function requestLock(id, cb) {
|
|
27
|
-
if (!(
|
|
31
|
+
if (!isWebLocksSupported()) {
|
|
28
32
|
cb(id);
|
|
29
33
|
return () => {
|
|
30
34
|
};
|
|
@@ -47,6 +51,7 @@ function requestLock(id, cb) {
|
|
|
47
51
|
}
|
|
48
52
|
// Annotate the CommonJS export names for ESM import in node:
|
|
49
53
|
0 && (module.exports = {
|
|
54
|
+
isWebLocksSupported,
|
|
50
55
|
requestLock
|
|
51
56
|
});
|
|
52
57
|
//# sourceMappingURL=requestLock.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/requestLock.ts"],"sourcesContent":["export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!(
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/requestLock.ts"],"sourcesContent":["export function isWebLocksSupported(): boolean {\n return typeof navigator !== 'undefined' && 'locks' in navigator && !!navigator.locks;\n}\n\nexport function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!isWebLocksSupported()) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,sBAA+B;AAC7C,SAAO,OAAO,cAAc,eAAe,WAAW,aAAa,CAAC,CAAC,UAAU;AACjF;AAEO,SAAS,YAAY,IAAY,IAA0B;AAEhE,MAAI,CAAC,oBAAoB,GAAG;AAE1B,OAAG,EAAE;AAEL,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,MAAI,cAAc;AAClB,MAAI;AAEJ,QAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAC7C,qBAAiB;AAAA,EACnB,CAAC;AAED,YAAU,MAAM,QAAQ,IAAI,MAAM;AAChC,QAAI,CAAC,aAAa;AAChB,SAAG,EAAE;AAAA,IACP;AAEA,WAAO;AAAA,EACT,CAAC;AAED,SAAO,MAAM;AACX,kBAAc;AACd,mBAAe;AAAA,EACjB;AACF;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/hooks/internal/useWebsocketEvent.ts
|
|
2
2
|
import { useEffect } from "react";
|
|
3
|
-
import { requestLock } from "../../utils/requestLock.js";
|
|
3
|
+
import { isWebLocksSupported, requestLock } from "../../utils/requestLock.js";
|
|
4
4
|
import { useNovu } from "../NovuProvider.js";
|
|
5
5
|
import { useBrowserTabsChannel } from "./useBrowserTabsChannel.js";
|
|
6
6
|
var useWebSocketEvent = ({
|
|
@@ -15,9 +15,12 @@ var useWebSocketEvent = ({
|
|
|
15
15
|
onMessage,
|
|
16
16
|
enabled
|
|
17
17
|
});
|
|
18
|
+
const shouldBroadcast = isWebLocksSupported();
|
|
18
19
|
const updateReadCount = (data) => {
|
|
19
20
|
onMessage(data);
|
|
20
|
-
|
|
21
|
+
if (shouldBroadcast) {
|
|
22
|
+
postMessage(data);
|
|
23
|
+
}
|
|
21
24
|
};
|
|
22
25
|
useEffect(() => {
|
|
23
26
|
if (!enabled) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { requestLock } from '../../utils/requestLock';\nimport { useNovu } from '../NovuProvider';\nimport { useBrowserTabsChannel } from './useBrowserTabsChannel';\n\nexport const useWebSocketEvent = <E extends SocketEventNames>({\n event: webSocketEvent,\n eventHandler: onMessage,\n enabled = true,\n}: {\n event: E;\n eventHandler: (args: Events[E]) => void;\n enabled?: boolean;\n}) => {\n const novu = useNovu();\n const channelName = `nv_ws_connection:a=${novu.applicationIdentifier}:s=${novu.subscriberId}:c=${novu.contextKey}:e=${webSocketEvent}`;\n\n const { postMessage } = useBrowserTabsChannel({\n channelName,\n onMessage,\n enabled,\n });\n\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n postMessage(data);\n };\n\n useEffect(() => {\n if (!enabled) return;\n\n let cleanup: () => void;\n const resolveLock = requestLock(channelName, () => {\n cleanup = novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n\n resolveLock();\n };\n }, [enabled]);\n};\n"],"mappings":";AACA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;
|
|
1
|
+
{"version":3,"sources":["../../../../src/hooks/internal/useWebsocketEvent.ts"],"sourcesContent":["import { EventHandler, Events, SocketEventNames } from '@novu/js';\nimport { useEffect } from 'react';\nimport { isWebLocksSupported, requestLock } from '../../utils/requestLock';\nimport { useNovu } from '../NovuProvider';\nimport { useBrowserTabsChannel } from './useBrowserTabsChannel';\n\nexport const useWebSocketEvent = <E extends SocketEventNames>({\n event: webSocketEvent,\n eventHandler: onMessage,\n enabled = true,\n}: {\n event: E;\n eventHandler: (args: Events[E]) => void;\n enabled?: boolean;\n}) => {\n const novu = useNovu();\n const channelName = `nv_ws_connection:a=${novu.applicationIdentifier}:s=${novu.subscriberId}:c=${novu.contextKey}:e=${webSocketEvent}`;\n\n const { postMessage } = useBrowserTabsChannel({\n channelName,\n onMessage,\n enabled,\n });\n\n // When Web Locks are unavailable, requestLock runs the callback in every tab,\n // so each tab already receives the event through its own socket. Re-broadcasting\n // in that case would duplicate the event across tabs (count multiplied by tab\n // count). Only the exclusive lock owner should fan out to the other tabs.\n const shouldBroadcast = isWebLocksSupported();\n const updateReadCount: EventHandler<Events[E]> = (data) => {\n onMessage(data);\n if (shouldBroadcast) {\n postMessage(data);\n }\n };\n\n useEffect(() => {\n if (!enabled) return;\n\n let cleanup: () => void;\n const resolveLock = requestLock(channelName, () => {\n cleanup = novu.on(webSocketEvent, updateReadCount);\n });\n\n return () => {\n if (cleanup) {\n cleanup();\n }\n\n resolveLock();\n };\n }, [enabled]);\n};\n"],"mappings":";AACA,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB,mBAAmB;AACjD,SAAS,eAAe;AACxB,SAAS,6BAA6B;AAE/B,IAAM,oBAAoB,CAA6B;AAAA,EAC5D,OAAO;AAAA,EACP,cAAc;AAAA,EACd,UAAU;AACZ,MAIM;AACJ,QAAM,OAAO,QAAQ;AACrB,QAAM,cAAc,sBAAsB,KAAK,qBAAqB,MAAM,KAAK,YAAY,MAAM,KAAK,UAAU,MAAM,cAAc;AAEpI,QAAM,EAAE,YAAY,IAAI,sBAAsB;AAAA,IAC5C;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAMD,QAAM,kBAAkB,oBAAoB;AAC5C,QAAM,kBAA2C,CAAC,SAAS;AACzD,cAAU,IAAI;AACd,QAAI,iBAAiB;AACnB,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,YAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,QAAI;AACJ,UAAM,cAAc,YAAY,aAAa,MAAM;AACjD,gBAAU,KAAK,GAAG,gBAAgB,eAAe;AAAA,IACnD,CAAC;AAED,WAAO,MAAM;AACX,UAAI,SAAS;AACX,gBAAQ;AAAA,MACV;AAEA,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AACd;","names":[]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// src/utils/requestLock.ts
|
|
2
|
+
function isWebLocksSupported() {
|
|
3
|
+
return typeof navigator !== "undefined" && "locks" in navigator && !!navigator.locks;
|
|
4
|
+
}
|
|
2
5
|
function requestLock(id, cb) {
|
|
3
|
-
if (!(
|
|
6
|
+
if (!isWebLocksSupported()) {
|
|
4
7
|
cb(id);
|
|
5
8
|
return () => {
|
|
6
9
|
};
|
|
@@ -22,6 +25,7 @@ function requestLock(id, cb) {
|
|
|
22
25
|
};
|
|
23
26
|
}
|
|
24
27
|
export {
|
|
28
|
+
isWebLocksSupported,
|
|
25
29
|
requestLock
|
|
26
30
|
};
|
|
27
31
|
//# sourceMappingURL=requestLock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/requestLock.ts"],"sourcesContent":["export function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!(
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/requestLock.ts"],"sourcesContent":["export function isWebLocksSupported(): boolean {\n return typeof navigator !== 'undefined' && 'locks' in navigator && !!navigator.locks;\n}\n\nexport function requestLock(id: string, cb: (id: string) => void) {\n // Check if the Lock API is available\n if (!isWebLocksSupported()) {\n // If Lock API is not available, immediately invoke the callback and return a no-op function\n cb(id);\n\n return () => {};\n }\n\n let isFulfilled = false;\n let promiseResolve: () => void;\n\n const promise = new Promise<void>((resolve) => {\n promiseResolve = resolve;\n });\n\n navigator.locks.request(id, () => {\n if (!isFulfilled) {\n cb(id);\n }\n\n return promise;\n });\n\n return () => {\n isFulfilled = true;\n promiseResolve();\n };\n}\n"],"mappings":";AAAO,SAAS,sBAA+B;AAC7C,SAAO,OAAO,cAAc,eAAe,WAAW,aAAa,CAAC,CAAC,UAAU;AACjF;AAEO,SAAS,YAAY,IAAY,IAA0B;AAEhE,MAAI,CAAC,oBAAoB,GAAG;AAE1B,OAAG,EAAE;AAEL,WAAO,MAAM;AAAA,IAAC;AAAA,EAChB;AAEA,MAAI,cAAc;AAClB,MAAI;AAEJ,QAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAC7C,qBAAiB;AAAA,EACnB,CAAC;AAED,YAAU,MAAM,QAAQ,IAAI,MAAM;AAChC,QAAI,CAAC,aAAa;AAChB,SAAG,EAAE;AAAA,IACP;AAEA,WAAO;AAAA,EACT,CAAC;AAED,SAAO,MAAM;AACX,kBAAc;AACd,mBAAe;AAAA,EACjB;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novu/react",
|
|
3
|
-
"version": "3.18.
|
|
3
|
+
"version": "3.18.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/novuhq/novu",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
"dependencies": {
|
|
124
|
-
"@novu/js": "3.18.
|
|
124
|
+
"@novu/js": "3.18.2"
|
|
125
125
|
},
|
|
126
126
|
"nx": {
|
|
127
127
|
"tags": [
|