@novu/react 2.0.0 → 2.1.1
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/client/index.d.mts +72 -2
- package/dist/client/index.d.ts +72 -2
- package/dist/client/index.js +356 -9
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +356 -9
- package/dist/client/index.mjs.map +1 -1
- package/dist/hooks/index.d.mts +2 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/server/server.d.mts +71 -1
- package/dist/server/server.d.ts +71 -1
- package/dist/server/server.js +334 -2
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.mjs +326 -1
- package/dist/server/server.mjs.map +1 -1
- package/hooks/package.json +5 -0
- package/package.json +27 -10
package/dist/client/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import React$1 from 'react';
|
|
2
|
+
import React$1, { ReactNode } from 'react';
|
|
3
3
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
|
+
import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
|
|
5
6
|
|
|
6
7
|
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
8
|
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
@@ -38,6 +39,7 @@ declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_
|
|
|
38
39
|
|
|
39
40
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
40
41
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
42
|
+
declare const InboxChild: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
41
43
|
|
|
42
44
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
43
45
|
|
|
@@ -49,4 +51,72 @@ type NotificationProps = {
|
|
|
49
51
|
};
|
|
50
52
|
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
type NovuProviderProps = NovuOptions & {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
};
|
|
57
|
+
declare const NovuProvider: ({ children, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache, }: NovuProviderProps) => react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare const useNovu: () => Novu;
|
|
59
|
+
declare const useUnsafeNovu: () => Novu | undefined;
|
|
60
|
+
|
|
61
|
+
type UseNotificationsProps = {
|
|
62
|
+
tags?: string[];
|
|
63
|
+
read?: boolean;
|
|
64
|
+
archived?: boolean;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onSuccess?: (data: Notification$1[]) => void;
|
|
67
|
+
onError?: (error: NovuError) => void;
|
|
68
|
+
};
|
|
69
|
+
declare const useNotifications: (props?: UseNotificationsProps) => {
|
|
70
|
+
readAll: () => Promise<{
|
|
71
|
+
data?: void | undefined;
|
|
72
|
+
error?: NovuError | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
archiveAll: () => Promise<{
|
|
75
|
+
data?: void | undefined;
|
|
76
|
+
error?: NovuError | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
archiveAllRead: () => Promise<{
|
|
79
|
+
data?: void | undefined;
|
|
80
|
+
error?: NovuError | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
notifications: Notification$1[] | undefined;
|
|
83
|
+
error: NovuError | undefined;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
isFetching: boolean;
|
|
86
|
+
refetch: () => Promise<void>;
|
|
87
|
+
fetchMore: () => Promise<void>;
|
|
88
|
+
hasMore: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type UsePreferencesProps = {
|
|
92
|
+
onSuccess?: (data: Preference[]) => void;
|
|
93
|
+
onError?: (error: NovuError) => void;
|
|
94
|
+
};
|
|
95
|
+
type UsePreferencesResult = {
|
|
96
|
+
preferences?: Preference[];
|
|
97
|
+
error?: NovuError;
|
|
98
|
+
isLoading: boolean;
|
|
99
|
+
isFetching: boolean;
|
|
100
|
+
refetch: () => Promise<void>;
|
|
101
|
+
};
|
|
102
|
+
declare const usePreferences: (props?: UsePreferencesProps) => UsePreferencesResult;
|
|
103
|
+
|
|
104
|
+
type Count = {
|
|
105
|
+
count: number;
|
|
106
|
+
filter: NotificationFilter;
|
|
107
|
+
};
|
|
108
|
+
type UseCountsProps = {
|
|
109
|
+
filters: NotificationFilter[];
|
|
110
|
+
onSuccess?: (data: Count[]) => void;
|
|
111
|
+
onError?: (error: NovuError) => void;
|
|
112
|
+
};
|
|
113
|
+
type UseCountsResult = {
|
|
114
|
+
counts?: Count[];
|
|
115
|
+
error?: NovuError;
|
|
116
|
+
isLoading: boolean;
|
|
117
|
+
isFetching: boolean;
|
|
118
|
+
refetch: () => Promise<void>;
|
|
119
|
+
};
|
|
120
|
+
declare const useCounts: (props: UseCountsProps) => UseCountsResult;
|
|
121
|
+
|
|
122
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, InboxChild, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, NovuProvider, Preferences, type UseNotificationsProps, type WithChildrenProps, useCounts, useNotifications, useNovu, usePreferences, useUnsafeNovu };
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import React$1 from 'react';
|
|
2
|
+
import React$1, { ReactNode } from 'react';
|
|
3
3
|
import { Notification, NotificationClickHandler, NotificationActionClickHandler, Appearance, Localization, Tab, RouterPush } from '@novu/js/ui';
|
|
4
4
|
export { Notification } from '@novu/js/ui';
|
|
5
|
+
import { Novu, NovuOptions, Notification as Notification$1, NovuError, Preference, NotificationFilter } from '@novu/js';
|
|
5
6
|
|
|
6
7
|
type NotificationsRenderer = (notification: Notification) => React.ReactNode;
|
|
7
8
|
type BellRenderer = (unreadCount: number) => React.ReactNode;
|
|
@@ -38,6 +39,7 @@ declare const Bell: React$1.MemoExoticComponent<(props: BellProps) => react_jsx_
|
|
|
38
39
|
|
|
39
40
|
type InboxProps = DefaultProps | WithChildrenProps;
|
|
40
41
|
declare const Inbox: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
42
|
+
declare const InboxChild: React$1.MemoExoticComponent<(props: InboxProps) => react_jsx_runtime.JSX.Element>;
|
|
41
43
|
|
|
42
44
|
declare const Preferences: () => react_jsx_runtime.JSX.Element;
|
|
43
45
|
|
|
@@ -49,4 +51,72 @@ type NotificationProps = {
|
|
|
49
51
|
};
|
|
50
52
|
declare const Notifications: React$1.MemoExoticComponent<(props: NotificationProps) => react_jsx_runtime.JSX.Element>;
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
type NovuProviderProps = NovuOptions & {
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
};
|
|
57
|
+
declare const NovuProvider: ({ children, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache, }: NovuProviderProps) => react_jsx_runtime.JSX.Element;
|
|
58
|
+
declare const useNovu: () => Novu;
|
|
59
|
+
declare const useUnsafeNovu: () => Novu | undefined;
|
|
60
|
+
|
|
61
|
+
type UseNotificationsProps = {
|
|
62
|
+
tags?: string[];
|
|
63
|
+
read?: boolean;
|
|
64
|
+
archived?: boolean;
|
|
65
|
+
limit?: number;
|
|
66
|
+
onSuccess?: (data: Notification$1[]) => void;
|
|
67
|
+
onError?: (error: NovuError) => void;
|
|
68
|
+
};
|
|
69
|
+
declare const useNotifications: (props?: UseNotificationsProps) => {
|
|
70
|
+
readAll: () => Promise<{
|
|
71
|
+
data?: void | undefined;
|
|
72
|
+
error?: NovuError | undefined;
|
|
73
|
+
}>;
|
|
74
|
+
archiveAll: () => Promise<{
|
|
75
|
+
data?: void | undefined;
|
|
76
|
+
error?: NovuError | undefined;
|
|
77
|
+
}>;
|
|
78
|
+
archiveAllRead: () => Promise<{
|
|
79
|
+
data?: void | undefined;
|
|
80
|
+
error?: NovuError | undefined;
|
|
81
|
+
}>;
|
|
82
|
+
notifications: Notification$1[] | undefined;
|
|
83
|
+
error: NovuError | undefined;
|
|
84
|
+
isLoading: boolean;
|
|
85
|
+
isFetching: boolean;
|
|
86
|
+
refetch: () => Promise<void>;
|
|
87
|
+
fetchMore: () => Promise<void>;
|
|
88
|
+
hasMore: boolean;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type UsePreferencesProps = {
|
|
92
|
+
onSuccess?: (data: Preference[]) => void;
|
|
93
|
+
onError?: (error: NovuError) => void;
|
|
94
|
+
};
|
|
95
|
+
type UsePreferencesResult = {
|
|
96
|
+
preferences?: Preference[];
|
|
97
|
+
error?: NovuError;
|
|
98
|
+
isLoading: boolean;
|
|
99
|
+
isFetching: boolean;
|
|
100
|
+
refetch: () => Promise<void>;
|
|
101
|
+
};
|
|
102
|
+
declare const usePreferences: (props?: UsePreferencesProps) => UsePreferencesResult;
|
|
103
|
+
|
|
104
|
+
type Count = {
|
|
105
|
+
count: number;
|
|
106
|
+
filter: NotificationFilter;
|
|
107
|
+
};
|
|
108
|
+
type UseCountsProps = {
|
|
109
|
+
filters: NotificationFilter[];
|
|
110
|
+
onSuccess?: (data: Count[]) => void;
|
|
111
|
+
onError?: (error: NovuError) => void;
|
|
112
|
+
};
|
|
113
|
+
type UseCountsResult = {
|
|
114
|
+
counts?: Count[];
|
|
115
|
+
error?: NovuError;
|
|
116
|
+
isLoading: boolean;
|
|
117
|
+
isFetching: boolean;
|
|
118
|
+
refetch: () => Promise<void>;
|
|
119
|
+
};
|
|
120
|
+
declare const useCounts: (props: UseCountsProps) => UseCountsResult;
|
|
121
|
+
|
|
122
|
+
export { type BaseProps, Bell, type BellProps, type BellRenderer, type DefaultInboxProps, type DefaultProps, Inbox, InboxChild, type InboxProps, type NotificationProps, Notifications, type NotificationsRenderer, NovuProvider, Preferences, type UseNotificationsProps, type WithChildrenProps, useCounts, useNotifications, useNovu, usePreferences, useUnsafeNovu };
|
package/dist/client/index.js
CHANGED
|
@@ -32,8 +32,15 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
Bell: () => Bell,
|
|
34
34
|
Inbox: () => Inbox,
|
|
35
|
+
InboxChild: () => InboxChild,
|
|
35
36
|
Notifications: () => Notifications,
|
|
36
|
-
|
|
37
|
+
NovuProvider: () => NovuProvider,
|
|
38
|
+
Preferences: () => Preferences,
|
|
39
|
+
useCounts: () => useCounts,
|
|
40
|
+
useNotifications: () => useNotifications,
|
|
41
|
+
useNovu: () => useNovu,
|
|
42
|
+
usePreferences: () => usePreferences,
|
|
43
|
+
useUnsafeNovu: () => useUnsafeNovu
|
|
37
44
|
});
|
|
38
45
|
module.exports = __toCommonJS(src_exports);
|
|
39
46
|
|
|
@@ -119,7 +126,7 @@ var import_react5 = require("react");
|
|
|
119
126
|
var import_react_dom = __toESM(require("react-dom"));
|
|
120
127
|
var import_ui = require("@novu/js/ui");
|
|
121
128
|
|
|
122
|
-
// src/hooks/useDataRef.ts
|
|
129
|
+
// src/hooks/internal/useDataRef.ts
|
|
123
130
|
var import_react4 = require("react");
|
|
124
131
|
var useDataRef = (data) => {
|
|
125
132
|
const ref = (0, import_react4.useRef)(data);
|
|
@@ -129,8 +136,8 @@ var useDataRef = (data) => {
|
|
|
129
136
|
|
|
130
137
|
// src/components/Renderer.tsx
|
|
131
138
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
132
|
-
var Renderer = ({ options, children }) => {
|
|
133
|
-
const optionsRef = useDataRef(options);
|
|
139
|
+
var Renderer = ({ options, novu, children }) => {
|
|
140
|
+
const optionsRef = useDataRef({ ...options, novu });
|
|
134
141
|
const [novuUI, setNovuUI] = (0, import_react5.useState)();
|
|
135
142
|
const [mountedElements, setMountedElements] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
136
143
|
const mountElement = (0, import_react5.useCallback)(
|
|
@@ -151,10 +158,10 @@ var Renderer = ({ options, children }) => {
|
|
|
151
158
|
[setMountedElements]
|
|
152
159
|
);
|
|
153
160
|
(0, import_react5.useEffect)(() => {
|
|
154
|
-
const
|
|
155
|
-
setNovuUI(
|
|
161
|
+
const novu2 = new import_ui.NovuUI(optionsRef.current);
|
|
162
|
+
setNovuUI(novu2);
|
|
156
163
|
return () => {
|
|
157
|
-
|
|
164
|
+
novu2.unmount();
|
|
158
165
|
};
|
|
159
166
|
}, []);
|
|
160
167
|
(0, import_react5.useEffect)(() => {
|
|
@@ -203,6 +210,24 @@ var DefaultInbox = (props) => {
|
|
|
203
210
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Mounter, { mount });
|
|
204
211
|
};
|
|
205
212
|
var Inbox = import_react6.default.memo((props) => {
|
|
213
|
+
const { applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl } = props;
|
|
214
|
+
const novu = useUnsafeNovu();
|
|
215
|
+
if (novu) {
|
|
216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InboxChild, { ...props });
|
|
217
|
+
}
|
|
218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
219
|
+
NovuProvider,
|
|
220
|
+
{
|
|
221
|
+
applicationIdentifier,
|
|
222
|
+
subscriberId,
|
|
223
|
+
subscriberHash,
|
|
224
|
+
backendUrl,
|
|
225
|
+
socketUrl,
|
|
226
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InboxChild, { ...props })
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
var InboxChild = import_react6.default.memo((props) => {
|
|
206
231
|
const {
|
|
207
232
|
localization,
|
|
208
233
|
appearance,
|
|
@@ -214,6 +239,7 @@ var Inbox = import_react6.default.memo((props) => {
|
|
|
214
239
|
backendUrl,
|
|
215
240
|
socketUrl
|
|
216
241
|
} = props;
|
|
242
|
+
const novu = useNovu();
|
|
217
243
|
const options = (0, import_react6.useMemo)(() => {
|
|
218
244
|
return {
|
|
219
245
|
localization,
|
|
@@ -224,10 +250,10 @@ var Inbox = import_react6.default.memo((props) => {
|
|
|
224
250
|
};
|
|
225
251
|
}, [localization, appearance, tabs, applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl]);
|
|
226
252
|
if (isWithChildrenProps(props)) {
|
|
227
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: props.children });
|
|
253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, novu, children: props.children });
|
|
228
254
|
}
|
|
229
255
|
const { open, renderNotification, renderBell, onNotificationClick, onPrimaryActionClick, onSecondaryActionClick } = props;
|
|
230
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Renderer, { options, novu, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
231
257
|
DefaultInbox,
|
|
232
258
|
{
|
|
233
259
|
open,
|
|
@@ -280,4 +306,325 @@ var Notifications = import_react8.default.memo((props) => {
|
|
|
280
306
|
);
|
|
281
307
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Mounter, { mount });
|
|
282
308
|
});
|
|
309
|
+
|
|
310
|
+
// src/hooks/NovuProvider.tsx
|
|
311
|
+
var import_js = require("@novu/js");
|
|
312
|
+
var import_react9 = require("react");
|
|
313
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
314
|
+
var NovuContext = (0, import_react9.createContext)(void 0);
|
|
315
|
+
var NovuProvider = ({
|
|
316
|
+
children,
|
|
317
|
+
applicationIdentifier,
|
|
318
|
+
subscriberId,
|
|
319
|
+
subscriberHash,
|
|
320
|
+
backendUrl,
|
|
321
|
+
socketUrl,
|
|
322
|
+
useCache
|
|
323
|
+
}) => {
|
|
324
|
+
const novu = (0, import_react9.useMemo)(
|
|
325
|
+
() => new import_js.Novu({ applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache }),
|
|
326
|
+
[applicationIdentifier, subscriberId, subscriberHash, backendUrl, socketUrl, useCache]
|
|
327
|
+
);
|
|
328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NovuContext.Provider, { value: novu, children });
|
|
329
|
+
};
|
|
330
|
+
var useNovu = () => {
|
|
331
|
+
const context = (0, import_react9.useContext)(NovuContext);
|
|
332
|
+
if (!context) {
|
|
333
|
+
throw new Error("useNovu must be used within a <NovuProvider />");
|
|
334
|
+
}
|
|
335
|
+
return context;
|
|
336
|
+
};
|
|
337
|
+
var useUnsafeNovu = () => {
|
|
338
|
+
const context = (0, import_react9.useContext)(NovuContext);
|
|
339
|
+
return context;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// src/hooks/useNotifications.ts
|
|
343
|
+
var import_react10 = require("react");
|
|
344
|
+
var import_js2 = require("@novu/js");
|
|
345
|
+
var useNotifications = (props) => {
|
|
346
|
+
const { tags, read, archived = false, limit, onSuccess, onError } = props || {};
|
|
347
|
+
const filterRef = (0, import_react10.useRef)(void 0);
|
|
348
|
+
const { notifications, on, off } = useNovu();
|
|
349
|
+
const [data, setData] = (0, import_react10.useState)();
|
|
350
|
+
const [error, setError] = (0, import_react10.useState)();
|
|
351
|
+
const [isLoading, setIsLoading] = (0, import_react10.useState)(true);
|
|
352
|
+
const [isFetching, setIsFetching] = (0, import_react10.useState)(false);
|
|
353
|
+
const [hasMore, setHasMore] = (0, import_react10.useState)(false);
|
|
354
|
+
const length = data?.length;
|
|
355
|
+
const after = length ? data[length - 1].id : void 0;
|
|
356
|
+
const sync = (event) => {
|
|
357
|
+
if (!event.data || filterRef.current && !(0, import_js2.isSameFilter)(filterRef.current, event.data.filter)) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
setData(event.data.notifications);
|
|
361
|
+
setHasMore(event.data.hasMore);
|
|
362
|
+
};
|
|
363
|
+
(0, import_react10.useEffect)(() => {
|
|
364
|
+
on("notifications.list.updated", sync);
|
|
365
|
+
return () => {
|
|
366
|
+
off("notifications.list.updated", sync);
|
|
367
|
+
};
|
|
368
|
+
}, []);
|
|
369
|
+
(0, import_react10.useEffect)(() => {
|
|
370
|
+
const newFilter = { tags, read, archived };
|
|
371
|
+
if (filterRef.current && (0, import_js2.isSameFilter)(filterRef.current, newFilter)) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
notifications.clearCache({ filter: filterRef.current });
|
|
375
|
+
filterRef.current = newFilter;
|
|
376
|
+
fetchNotifications({ refetch: true });
|
|
377
|
+
}, [tags, read, archived]);
|
|
378
|
+
const fetchNotifications = async (options) => {
|
|
379
|
+
if (options?.refetch) {
|
|
380
|
+
setError(void 0);
|
|
381
|
+
setIsLoading(true);
|
|
382
|
+
setIsFetching(false);
|
|
383
|
+
}
|
|
384
|
+
setIsFetching(true);
|
|
385
|
+
const response = await notifications.list({
|
|
386
|
+
tags,
|
|
387
|
+
read,
|
|
388
|
+
archived,
|
|
389
|
+
limit,
|
|
390
|
+
after: options?.refetch ? void 0 : after
|
|
391
|
+
});
|
|
392
|
+
if (response.error) {
|
|
393
|
+
setError(response.error);
|
|
394
|
+
onError?.(response.error);
|
|
395
|
+
} else {
|
|
396
|
+
onSuccess?.(response.data.notifications);
|
|
397
|
+
setData(response.data.notifications);
|
|
398
|
+
setHasMore(response.data.hasMore);
|
|
399
|
+
}
|
|
400
|
+
setIsLoading(false);
|
|
401
|
+
setIsFetching(false);
|
|
402
|
+
};
|
|
403
|
+
const refetch = () => {
|
|
404
|
+
notifications.clearCache({ filter: { tags, read, archived } });
|
|
405
|
+
return fetchNotifications({ refetch: true });
|
|
406
|
+
};
|
|
407
|
+
const fetchMore = async () => {
|
|
408
|
+
if (!hasMore || isFetching) return;
|
|
409
|
+
return fetchNotifications();
|
|
410
|
+
};
|
|
411
|
+
const readAll = async () => {
|
|
412
|
+
return await notifications.readAll({ tags });
|
|
413
|
+
};
|
|
414
|
+
const archiveAll = async () => {
|
|
415
|
+
return await notifications.archiveAll({ tags });
|
|
416
|
+
};
|
|
417
|
+
const archiveAllRead = async () => {
|
|
418
|
+
return await notifications.archiveAllRead({ tags });
|
|
419
|
+
};
|
|
420
|
+
return {
|
|
421
|
+
readAll,
|
|
422
|
+
archiveAll,
|
|
423
|
+
archiveAllRead,
|
|
424
|
+
notifications: data,
|
|
425
|
+
error,
|
|
426
|
+
isLoading,
|
|
427
|
+
isFetching,
|
|
428
|
+
refetch,
|
|
429
|
+
fetchMore,
|
|
430
|
+
hasMore
|
|
431
|
+
};
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// src/hooks/usePreferences.ts
|
|
435
|
+
var import_react11 = require("react");
|
|
436
|
+
var usePreferences = (props) => {
|
|
437
|
+
const { onSuccess, onError } = props || {};
|
|
438
|
+
const [data, setData] = (0, import_react11.useState)();
|
|
439
|
+
const { preferences, on, off } = useNovu();
|
|
440
|
+
const [error, setError] = (0, import_react11.useState)();
|
|
441
|
+
const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
|
|
442
|
+
const [isFetching, setIsFetching] = (0, import_react11.useState)(false);
|
|
443
|
+
const sync = (event) => {
|
|
444
|
+
if (!event.data) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
setData(event.data);
|
|
448
|
+
};
|
|
449
|
+
(0, import_react11.useEffect)(() => {
|
|
450
|
+
fetchPreferences();
|
|
451
|
+
on("preferences.list.updated", sync);
|
|
452
|
+
on("preferences.list.pending", sync);
|
|
453
|
+
on("preferences.list.resolved", sync);
|
|
454
|
+
return () => {
|
|
455
|
+
off("preferences.list.updated", sync);
|
|
456
|
+
off("preferences.list.pending", sync);
|
|
457
|
+
off("preferences.list.resolved", sync);
|
|
458
|
+
};
|
|
459
|
+
}, []);
|
|
460
|
+
const fetchPreferences = async () => {
|
|
461
|
+
setIsFetching(true);
|
|
462
|
+
const response = await preferences.list();
|
|
463
|
+
if (response.error) {
|
|
464
|
+
setError(response.error);
|
|
465
|
+
onError?.(response.error);
|
|
466
|
+
} else {
|
|
467
|
+
onSuccess?.(response.data);
|
|
468
|
+
}
|
|
469
|
+
setIsLoading(false);
|
|
470
|
+
setIsFetching(false);
|
|
471
|
+
};
|
|
472
|
+
const refetch = () => {
|
|
473
|
+
preferences.cache.clearAll();
|
|
474
|
+
return fetchPreferences();
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
preferences: data,
|
|
478
|
+
error,
|
|
479
|
+
isLoading,
|
|
480
|
+
isFetching,
|
|
481
|
+
refetch
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
// src/hooks/useCounts.ts
|
|
486
|
+
var import_react14 = require("react");
|
|
487
|
+
var import_js3 = require("@novu/js");
|
|
488
|
+
|
|
489
|
+
// src/hooks/internal/useWebsocketEvent.ts
|
|
490
|
+
var import_react13 = require("react");
|
|
491
|
+
|
|
492
|
+
// src/utils/requestLock.ts
|
|
493
|
+
function requestLock(id, cb) {
|
|
494
|
+
if (!("locks" in navigator)) {
|
|
495
|
+
cb(id);
|
|
496
|
+
return () => {
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
let isFulfilled = false;
|
|
500
|
+
let promiseResolve;
|
|
501
|
+
const promise = new Promise((resolve) => {
|
|
502
|
+
promiseResolve = resolve;
|
|
503
|
+
});
|
|
504
|
+
navigator.locks.request(id, () => {
|
|
505
|
+
if (!isFulfilled) {
|
|
506
|
+
cb(id);
|
|
507
|
+
}
|
|
508
|
+
return promise;
|
|
509
|
+
});
|
|
510
|
+
return () => {
|
|
511
|
+
isFulfilled = true;
|
|
512
|
+
promiseResolve();
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// src/hooks/internal/useBrowserTabsChannel.ts
|
|
517
|
+
var import_react12 = require("react");
|
|
518
|
+
var useBrowserTabsChannel = ({
|
|
519
|
+
channelName,
|
|
520
|
+
onMessage
|
|
521
|
+
}) => {
|
|
522
|
+
const [tabsChannel] = (0, import_react12.useState)(
|
|
523
|
+
typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(channelName) : void 0
|
|
524
|
+
);
|
|
525
|
+
const postMessage = (data) => {
|
|
526
|
+
tabsChannel?.postMessage(data);
|
|
527
|
+
};
|
|
528
|
+
(0, import_react12.useEffect)(() => {
|
|
529
|
+
const listener = (event) => {
|
|
530
|
+
onMessage(event.data);
|
|
531
|
+
};
|
|
532
|
+
tabsChannel?.addEventListener("message", listener);
|
|
533
|
+
return () => {
|
|
534
|
+
tabsChannel?.removeEventListener("message", listener);
|
|
535
|
+
};
|
|
536
|
+
}, []);
|
|
537
|
+
return { postMessage };
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// src/hooks/internal/useWebsocketEvent.ts
|
|
541
|
+
var useWebSocketEvent = ({
|
|
542
|
+
event: webSocketEvent,
|
|
543
|
+
eventHandler: onMessage
|
|
544
|
+
}) => {
|
|
545
|
+
const novu = useNovu();
|
|
546
|
+
const { postMessage } = useBrowserTabsChannel({ channelName: `nv.${webSocketEvent}`, onMessage });
|
|
547
|
+
const updateReadCount = (data) => {
|
|
548
|
+
onMessage(data);
|
|
549
|
+
postMessage(data);
|
|
550
|
+
};
|
|
551
|
+
(0, import_react13.useEffect)(() => {
|
|
552
|
+
const resolveLock = requestLock(`nv.${webSocketEvent}`, () => {
|
|
553
|
+
novu.on(webSocketEvent, updateReadCount);
|
|
554
|
+
});
|
|
555
|
+
return () => {
|
|
556
|
+
novu.off(webSocketEvent, updateReadCount);
|
|
557
|
+
resolveLock();
|
|
558
|
+
};
|
|
559
|
+
}, []);
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
// src/hooks/useCounts.ts
|
|
563
|
+
var useCounts = (props) => {
|
|
564
|
+
const { filters, onSuccess, onError } = props;
|
|
565
|
+
const { notifications } = useNovu();
|
|
566
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
567
|
+
const [counts, setCounts] = (0, import_react14.useState)();
|
|
568
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
|
|
569
|
+
const [isFetching, setIsFetching] = (0, import_react14.useState)(false);
|
|
570
|
+
const sync = async (notification) => {
|
|
571
|
+
const existingCounts = counts ?? new Array(filters.length).fill(void 0);
|
|
572
|
+
let countFiltersToFetch = [];
|
|
573
|
+
if (notification) {
|
|
574
|
+
for (let i = 0; i < existingCounts.length; i++) {
|
|
575
|
+
const filter = filters[i];
|
|
576
|
+
if ((0, import_js3.areTagsEqual)(filter.tags, notification.tags)) {
|
|
577
|
+
countFiltersToFetch.push(filter);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
countFiltersToFetch = filters;
|
|
582
|
+
}
|
|
583
|
+
if (countFiltersToFetch.length === 0) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
setIsFetching(true);
|
|
587
|
+
const countsRes = await notifications.count({ filters: countFiltersToFetch });
|
|
588
|
+
setIsFetching(false);
|
|
589
|
+
setIsLoading(false);
|
|
590
|
+
if (countsRes.error) {
|
|
591
|
+
setError(countsRes.error);
|
|
592
|
+
onError?.(countsRes.error);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const data = countsRes.data;
|
|
596
|
+
onSuccess?.(data.counts);
|
|
597
|
+
setCounts((oldCounts) => {
|
|
598
|
+
const newCounts = [];
|
|
599
|
+
const countsReceived = data.counts;
|
|
600
|
+
for (let i = 0; i < existingCounts.length; i++) {
|
|
601
|
+
const countReceived = countsReceived.find((c) => (0, import_js3.areTagsEqual)(c.filter.tags, existingCounts[i]?.filter.tags));
|
|
602
|
+
newCounts.push(countReceived || oldCounts[i]);
|
|
603
|
+
}
|
|
604
|
+
return newCounts;
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
useWebSocketEvent({
|
|
608
|
+
event: "notifications.notification_received",
|
|
609
|
+
eventHandler: (data) => {
|
|
610
|
+
sync(data.result);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
useWebSocketEvent({
|
|
614
|
+
event: "notifications.unread_count_changed",
|
|
615
|
+
eventHandler: () => {
|
|
616
|
+
sync();
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
(0, import_react14.useEffect)(() => {
|
|
620
|
+
setError(void 0);
|
|
621
|
+
setIsLoading(true);
|
|
622
|
+
setIsFetching(false);
|
|
623
|
+
sync();
|
|
624
|
+
}, [JSON.stringify(filters)]);
|
|
625
|
+
const refetch = async () => {
|
|
626
|
+
await sync();
|
|
627
|
+
};
|
|
628
|
+
return { counts, error, refetch, isLoading, isFetching };
|
|
629
|
+
};
|
|
283
630
|
//# sourceMappingURL=index.js.map
|