@novu/react 3.11.0 → 3.11.2-nightly.20251224.eb609546a3
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/README.md +10 -18
- package/dist/cjs/components/Inbox.cjs +5 -1
- package/dist/cjs/components/Inbox.cjs.map +1 -1
- package/dist/cjs/components/NovuUI.cjs +3 -1
- package/dist/cjs/components/NovuUI.cjs.map +1 -1
- package/dist/cjs/components/NovuUI.d.cts +9 -9
- package/dist/cjs/components/index.cjs +7 -1
- package/dist/cjs/components/index.cjs.map +1 -1
- package/dist/cjs/components/index.d.cts +5 -0
- package/dist/cjs/components/subscription/DefaultSubscription.cjs +59 -0
- package/dist/cjs/components/subscription/DefaultSubscription.cjs.map +1 -0
- package/dist/cjs/components/subscription/DefaultSubscription.d.cts +11 -0
- package/dist/cjs/components/subscription/Subscription.cjs +80 -0
- package/dist/cjs/components/subscription/Subscription.cjs.map +1 -0
- package/dist/cjs/components/subscription/Subscription.d.cts +22 -0
- package/dist/cjs/components/subscription/SubscriptionButton.cjs +91 -0
- package/dist/cjs/components/subscription/SubscriptionButton.cjs.map +1 -0
- package/dist/cjs/components/subscription/SubscriptionButton.d.cts +8 -0
- package/dist/cjs/components/subscription/SubscriptionPreferences.cjs +91 -0
- package/dist/cjs/components/subscription/SubscriptionPreferences.cjs.map +1 -0
- package/dist/cjs/components/subscription/SubscriptionPreferences.d.cts +8 -0
- package/dist/cjs/hooks/NovuProvider.cjs +21 -18
- package/dist/cjs/hooks/NovuProvider.cjs.map +1 -1
- package/dist/cjs/hooks/index.cjs +11 -1
- package/dist/cjs/hooks/index.cjs.map +1 -1
- package/dist/cjs/hooks/index.d.cts +7 -1
- package/dist/cjs/hooks/useCounts.cjs +2 -2
- package/dist/cjs/hooks/useCounts.cjs.map +1 -1
- package/dist/cjs/hooks/useCreateSubscription.cjs +61 -0
- package/dist/cjs/hooks/useCreateSubscription.cjs.map +1 -0
- package/dist/cjs/hooks/useCreateSubscription.d.cts +17 -0
- package/dist/cjs/hooks/useNotifications.cjs +57 -60
- package/dist/cjs/hooks/useNotifications.cjs.map +1 -1
- package/dist/cjs/hooks/useRemoveSubscription.cjs +61 -0
- package/dist/cjs/hooks/useRemoveSubscription.cjs.map +1 -0
- package/dist/cjs/hooks/useRemoveSubscription.d.cts +17 -0
- package/dist/cjs/hooks/useSubscription.cjs +156 -0
- package/dist/cjs/hooks/useSubscription.cjs.map +1 -0
- package/dist/cjs/hooks/useSubscription.d.cts +21 -0
- package/dist/cjs/hooks/useSubscriptions.cjs +121 -0
- package/dist/cjs/hooks/useSubscriptions.cjs.map +1 -0
- package/dist/cjs/hooks/useSubscriptions.d.cts +36 -0
- package/dist/cjs/hooks/useUpdateSubscription.cjs +61 -0
- package/dist/cjs/hooks/useUpdateSubscription.cjs.map +1 -0
- package/dist/cjs/hooks/useUpdateSubscription.d.cts +18 -0
- package/dist/cjs/index.cjs +18 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +14 -3
- package/dist/cjs/server/index.cjs +61 -2
- package/dist/cjs/server/index.cjs.map +1 -1
- package/dist/cjs/server/index.d.cts +18 -4
- package/dist/cjs/utils/appearance.cjs.map +1 -1
- package/dist/cjs/utils/appearance.d.cts +3 -3
- package/dist/cjs/utils/types.cjs.map +1 -1
- package/dist/cjs/utils/types.d.cts +32 -11
- package/dist/esm/components/Inbox.js +5 -1
- package/dist/esm/components/Inbox.js.map +1 -1
- package/dist/esm/components/NovuUI.d.ts +9 -9
- package/dist/esm/components/NovuUI.js +3 -1
- package/dist/esm/components/NovuUI.js.map +1 -1
- package/dist/esm/components/index.d.ts +5 -0
- package/dist/esm/components/index.js +3 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/components/subscription/DefaultSubscription.d.ts +11 -0
- package/dist/esm/components/subscription/DefaultSubscription.js +34 -0
- package/dist/esm/components/subscription/DefaultSubscription.js.map +1 -0
- package/dist/esm/components/subscription/Subscription.d.ts +22 -0
- package/dist/esm/components/subscription/Subscription.js +45 -0
- package/dist/esm/components/subscription/Subscription.js.map +1 -0
- package/dist/esm/components/subscription/SubscriptionButton.d.ts +8 -0
- package/dist/esm/components/subscription/SubscriptionButton.js +56 -0
- package/dist/esm/components/subscription/SubscriptionButton.js.map +1 -0
- package/dist/esm/components/subscription/SubscriptionPreferences.d.ts +8 -0
- package/dist/esm/components/subscription/SubscriptionPreferences.js +56 -0
- package/dist/esm/components/subscription/SubscriptionPreferences.js.map +1 -0
- package/dist/esm/hooks/NovuProvider.js +22 -19
- package/dist/esm/hooks/NovuProvider.js.map +1 -1
- package/dist/esm/hooks/index.d.ts +7 -1
- package/dist/esm/hooks/index.js +5 -0
- package/dist/esm/hooks/index.js.map +1 -1
- package/dist/esm/hooks/useCounts.js +3 -3
- package/dist/esm/hooks/useCounts.js.map +1 -1
- package/dist/esm/hooks/useCreateSubscription.d.ts +17 -0
- package/dist/esm/hooks/useCreateSubscription.js +36 -0
- package/dist/esm/hooks/useCreateSubscription.js.map +1 -0
- package/dist/esm/hooks/useNotifications.js +58 -61
- package/dist/esm/hooks/useNotifications.js.map +1 -1
- package/dist/esm/hooks/useRemoveSubscription.d.ts +17 -0
- package/dist/esm/hooks/useRemoveSubscription.js +36 -0
- package/dist/esm/hooks/useRemoveSubscription.js.map +1 -0
- package/dist/esm/hooks/useSubscription.d.ts +21 -0
- package/dist/esm/hooks/useSubscription.js +129 -0
- package/dist/esm/hooks/useSubscription.js.map +1 -0
- package/dist/esm/hooks/useSubscriptions.d.ts +36 -0
- package/dist/esm/hooks/useSubscriptions.js +96 -0
- package/dist/esm/hooks/useSubscriptions.js.map +1 -0
- package/dist/esm/hooks/useUpdateSubscription.d.ts +18 -0
- package/dist/esm/hooks/useUpdateSubscription.js +36 -0
- package/dist/esm/hooks/useUpdateSubscription.js.map +1 -0
- package/dist/esm/index.d.ts +14 -3
- package/dist/esm/index.js +32 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/index.d.ts +18 -4
- package/dist/esm/server/index.js +53 -2
- package/dist/esm/server/index.js.map +1 -1
- package/dist/esm/utils/appearance.d.ts +3 -3
- package/dist/esm/utils/appearance.js.map +1 -1
- package/dist/esm/utils/types.d.ts +32 -11
- package/package.json +11 -11
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/components/subscription/SubscriptionPreferences.tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useNovuUI } from "../../context/NovuUIContext.js";
|
|
4
|
+
import { Mounter } from "../Mounter.js";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var SubscriptionPreferences = React.memo(
|
|
7
|
+
({
|
|
8
|
+
topicKey,
|
|
9
|
+
identifier,
|
|
10
|
+
preferences,
|
|
11
|
+
onClick,
|
|
12
|
+
onDeleteError,
|
|
13
|
+
onDeleteSuccess,
|
|
14
|
+
onCreateError,
|
|
15
|
+
onCreateSuccess
|
|
16
|
+
}) => {
|
|
17
|
+
const { novuUI } = useNovuUI();
|
|
18
|
+
const mount = React.useCallback(
|
|
19
|
+
(element) => {
|
|
20
|
+
if (!topicKey) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return novuUI.mountComponent({
|
|
24
|
+
name: "SubscriptionPreferences",
|
|
25
|
+
element,
|
|
26
|
+
props: {
|
|
27
|
+
topicKey,
|
|
28
|
+
identifier,
|
|
29
|
+
preferences,
|
|
30
|
+
onClick,
|
|
31
|
+
onDeleteError,
|
|
32
|
+
onDeleteSuccess,
|
|
33
|
+
onCreateError,
|
|
34
|
+
onCreateSuccess
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
[
|
|
39
|
+
novuUI,
|
|
40
|
+
topicKey,
|
|
41
|
+
identifier,
|
|
42
|
+
preferences,
|
|
43
|
+
onClick,
|
|
44
|
+
onDeleteError,
|
|
45
|
+
onDeleteSuccess,
|
|
46
|
+
onCreateError,
|
|
47
|
+
onCreateSuccess
|
|
48
|
+
]
|
|
49
|
+
);
|
|
50
|
+
return /* @__PURE__ */ jsx(Mounter, { mount });
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
export {
|
|
54
|
+
SubscriptionPreferences
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=SubscriptionPreferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/subscription/SubscriptionPreferences.tsx"],"sourcesContent":["import type { SubscriptionPreferencesWrapperProps } from '@novu/js/ui';\nimport React from 'react';\nimport { useNovuUI } from '../../context/NovuUIContext';\nimport { Mounter } from '../Mounter';\n\nexport type SubscriptionPreferencesProps = Partial<SubscriptionPreferencesWrapperProps>;\n\nexport const SubscriptionPreferences = React.memo(\n ({\n topicKey,\n identifier,\n preferences,\n onClick,\n onDeleteError,\n onDeleteSuccess,\n onCreateError,\n onCreateSuccess,\n }: SubscriptionPreferencesProps) => {\n const { novuUI } = useNovuUI();\n\n const mount = React.useCallback(\n (element: HTMLElement) => {\n if (!topicKey) {\n return;\n }\n\n return novuUI.mountComponent({\n name: 'SubscriptionPreferences',\n element,\n props: {\n topicKey,\n identifier,\n preferences,\n onClick,\n onDeleteError,\n onDeleteSuccess,\n onCreateError,\n onCreateSuccess,\n },\n });\n },\n [\n novuUI,\n topicKey,\n identifier,\n preferences,\n onClick,\n onDeleteError,\n onDeleteSuccess,\n onCreateError,\n onCreateSuccess,\n ]\n );\n\n return <Mounter mount={mount} />;\n }\n);\n"],"mappings":";AACA,OAAO,WAAW;AAClB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AAmDb;AA/CJ,IAAM,0BAA0B,MAAM;AAAA,EAC3C,CAAC;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAAoC;AAClC,UAAM,EAAE,OAAO,IAAI,UAAU;AAE7B,UAAM,QAAQ,MAAM;AAAA,MAClB,CAAC,YAAyB;AACxB,YAAI,CAAC,UAAU;AACb;AAAA,QACF;AAEA,eAAO,OAAO,eAAe;AAAA,UAC3B,MAAM;AAAA,UACN;AAAA,UACA,OAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO,oBAAC,WAAQ,OAAc;AAAA,EAChC;AACF;","names":[]}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
// src/hooks/NovuProvider.tsx
|
|
2
2
|
import { Novu } from "@novu/js";
|
|
3
3
|
import { buildSubscriber } from "@novu/js/internal";
|
|
4
|
-
import { createContext, useContext,
|
|
4
|
+
import { createContext, useContext, useMemo } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
var version = "3.11.
|
|
6
|
+
var version = "3.11.2-nightly.20251224.eb609546a3";
|
|
7
7
|
var name = "@novu/react";
|
|
8
8
|
var baseUserAgent = `${name}@${version}`;
|
|
9
9
|
var NovuContext = createContext(void 0);
|
|
10
10
|
var NovuProvider = (props) => {
|
|
11
11
|
const { subscriberId, ...propsWithoutSubscriberId } = props;
|
|
12
|
-
const subscriberObj =
|
|
12
|
+
const subscriberObj = useMemo(
|
|
13
|
+
() => buildSubscriber({ subscriberId, subscriber: props.subscriber }),
|
|
14
|
+
[subscriberId, props.subscriber]
|
|
15
|
+
);
|
|
13
16
|
const applicationIdentifier = propsWithoutSubscriberId.applicationIdentifier ? propsWithoutSubscriberId.applicationIdentifier : "";
|
|
14
17
|
const providerProps = {
|
|
15
18
|
...propsWithoutSubscriberId,
|
|
@@ -20,7 +23,10 @@ var NovuProvider = (props) => {
|
|
|
20
23
|
};
|
|
21
24
|
var InternalNovuProvider = (props) => {
|
|
22
25
|
const applicationIdentifier = props.applicationIdentifier || "";
|
|
23
|
-
const subscriberObj =
|
|
26
|
+
const subscriberObj = useMemo(
|
|
27
|
+
() => buildSubscriber({ subscriberId: props.subscriberId, subscriber: props.subscriber }),
|
|
28
|
+
[props.subscriberId, props.subscriber]
|
|
29
|
+
);
|
|
24
30
|
const {
|
|
25
31
|
children,
|
|
26
32
|
subscriberHash,
|
|
@@ -47,22 +53,19 @@ var InternalNovuProvider = (props) => {
|
|
|
47
53
|
defaultSchedule,
|
|
48
54
|
context
|
|
49
55
|
}),
|
|
50
|
-
[
|
|
56
|
+
[
|
|
57
|
+
applicationIdentifier,
|
|
58
|
+
subscriberHash,
|
|
59
|
+
subscriberObj,
|
|
60
|
+
context,
|
|
61
|
+
contextHash,
|
|
62
|
+
backendUrl,
|
|
63
|
+
apiUrl,
|
|
64
|
+
socketUrl,
|
|
65
|
+
useCache,
|
|
66
|
+
userAgentType
|
|
67
|
+
]
|
|
51
68
|
);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
novu.changeSubscriber({
|
|
54
|
-
subscriber: subscriberObj,
|
|
55
|
-
subscriberHash: props.subscriberHash
|
|
56
|
-
});
|
|
57
|
-
}, [subscriberObj.subscriberId, props.subscriberHash, novu]);
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
if (context && contextHash) {
|
|
60
|
-
novu.changeContext({
|
|
61
|
-
context,
|
|
62
|
-
contextHash
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}, [context, contextHash, novu]);
|
|
66
69
|
return /* @__PURE__ */ jsx(NovuContext.Provider, { value: novu, children });
|
|
67
70
|
};
|
|
68
71
|
var useNovu = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/NovuProvider.tsx"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { buildSubscriber } from '@novu/js/internal';\nimport { createContext, ReactNode, useContext,
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/NovuProvider.tsx"],"sourcesContent":["import { Novu, NovuOptions } from '@novu/js';\nimport { buildSubscriber } from '@novu/js/internal';\nimport { createContext, ReactNode, useContext, useMemo } from 'react';\n\n// @ts-expect-error\nconst version = PACKAGE_VERSION;\n// @ts-expect-error\nconst name = PACKAGE_NAME;\nconst baseUserAgent = `${name}@${version}`;\n\nexport type NovuProviderProps = NovuOptions & {\n children: ReactNode;\n};\n\nconst NovuContext = createContext<Novu | undefined>(undefined);\n\nexport const NovuProvider = (props: NovuProviderProps) => {\n const { subscriberId, ...propsWithoutSubscriberId } = props;\n const subscriberObj = useMemo(\n () => buildSubscriber({ subscriberId, subscriber: props.subscriber }),\n [subscriberId, props.subscriber]\n );\n const applicationIdentifier = propsWithoutSubscriberId.applicationIdentifier\n ? propsWithoutSubscriberId.applicationIdentifier\n : '';\n\n const providerProps: NovuProviderProps = {\n ...propsWithoutSubscriberId,\n applicationIdentifier,\n subscriber: subscriberObj,\n };\n\n return (\n <InternalNovuProvider {...providerProps} applicationIdentifier={applicationIdentifier} userAgentType=\"hooks\">\n {props.children}\n </InternalNovuProvider>\n );\n};\n\n/**\n * @internal Should be used internally not to be exposed outside of the library\n * This is needed to differentiate between the hooks and components user agents\n * Better to use this internally to avoid confusion.\n */\nexport const InternalNovuProvider = (props: NovuProviderProps & { userAgentType: 'components' | 'hooks' }) => {\n const applicationIdentifier = props.applicationIdentifier || '';\n const subscriberObj = useMemo(\n () => buildSubscriber({ subscriberId: props.subscriberId, subscriber: props.subscriber }),\n [props.subscriberId, props.subscriber]\n );\n\n const {\n children,\n subscriberHash,\n contextHash,\n backendUrl,\n apiUrl,\n socketUrl,\n useCache,\n userAgentType,\n defaultSchedule,\n context,\n } = props;\n\n const novu = useMemo(\n () =>\n new Novu({\n applicationIdentifier,\n subscriberHash,\n contextHash,\n backendUrl,\n apiUrl,\n socketUrl,\n useCache,\n __userAgent: `${baseUserAgent} ${userAgentType}`,\n subscriber: subscriberObj,\n defaultSchedule,\n context,\n }),\n [\n applicationIdentifier,\n subscriberHash,\n subscriberObj,\n context,\n contextHash,\n backendUrl,\n apiUrl,\n socketUrl,\n useCache,\n userAgentType,\n ]\n );\n\n return <NovuContext.Provider value={novu}>{children}</NovuContext.Provider>;\n};\n\nexport const useNovu = () => {\n const context = useContext(NovuContext);\n if (!context) {\n throw new Error('useNovu must be used within a <NovuProvider />');\n }\n\n return context;\n};\n\nexport const useUnsafeNovu = () => {\n const context = useContext(NovuContext);\n\n return context;\n};\n"],"mappings":";AAAA,SAAS,YAAyB;AAClC,SAAS,uBAAuB;AAChC,SAAS,eAA0B,YAAY,eAAe;AA+B1D;AA5BJ,IAAM,UAAU;AAEhB,IAAM,OAAO;AACb,IAAM,gBAAgB,GAAG,IAAI,IAAI,OAAO;AAMxC,IAAM,cAAc,cAAgC,MAAS;AAEtD,IAAM,eAAe,CAAC,UAA6B;AACxD,QAAM,EAAE,cAAc,GAAG,yBAAyB,IAAI;AACtD,QAAM,gBAAgB;AAAA,IACpB,MAAM,gBAAgB,EAAE,cAAc,YAAY,MAAM,WAAW,CAAC;AAAA,IACpE,CAAC,cAAc,MAAM,UAAU;AAAA,EACjC;AACA,QAAM,wBAAwB,yBAAyB,wBACnD,yBAAyB,wBACzB;AAEJ,QAAM,gBAAmC;AAAA,IACvC,GAAG;AAAA,IACH;AAAA,IACA,YAAY;AAAA,EACd;AAEA,SACE,oBAAC,wBAAsB,GAAG,eAAe,uBAA8C,eAAc,SAClG,gBAAM,UACT;AAEJ;AAOO,IAAM,uBAAuB,CAAC,UAAyE;AAC5G,QAAM,wBAAwB,MAAM,yBAAyB;AAC7D,QAAM,gBAAgB;AAAA,IACpB,MAAM,gBAAgB,EAAE,cAAc,MAAM,cAAc,YAAY,MAAM,WAAW,CAAC;AAAA,IACxF,CAAC,MAAM,cAAc,MAAM,UAAU;AAAA,EACvC;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,OAAO;AAAA,IACX,MACE,IAAI,KAAK;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,GAAG,aAAa,IAAI,aAAa;AAAA,MAC9C,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAO,MAAO,UAAS;AACtD;AAEO,IAAM,UAAU,MAAM;AAC3B,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,SAAO;AACT;AAEO,IAAM,gBAAgB,MAAM;AACjC,QAAM,UAAU,WAAW,WAAW;AAEtC,SAAO;AACT;","names":[]}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from '@novu/js';
|
|
2
|
+
export { PreferenceLevel, SeverityLevelEnum, WorkflowCriticalityEnum } from '@novu/js';
|
|
2
3
|
export { NovuProvider, useNovu } from './NovuProvider.js';
|
|
3
4
|
export { UseCountsProps, UseCountsResult, useCounts } from './useCounts.js';
|
|
5
|
+
export { UseCreateSubscriptionProps, UseCreateSubscriptionResult, useCreateSubscription } from './useCreateSubscription.js';
|
|
4
6
|
export { UseNotificationsProps, UseNotificationsResult, useNotifications } from './useNotifications.js';
|
|
5
7
|
export { UsePreferencesProps, UsePreferencesResult, usePreferences } from './usePreferences.js';
|
|
8
|
+
export { UseRemoveSubscriptionProps, UseRemoveSubscriptionResult, useRemoveSubscription } from './useRemoveSubscription.js';
|
|
6
9
|
export { UseScheduleProps, UseScheduleResult, useSchedule } from './useSchedule.js';
|
|
10
|
+
export { UseSubscriptionProps, UseSubscriptionResult, useSubscription } from './useSubscription.js';
|
|
11
|
+
export { UseSubscriptionsProps, UseSubscriptionsResult, useSubscriptions } from './useSubscriptions.js';
|
|
12
|
+
export { UseUpdateSubscriptionProps, UseUpdateSubscriptionResult, useUpdateSubscription } from './useUpdateSubscription.js';
|
|
7
13
|
import 'react/jsx-runtime';
|
|
8
14
|
import 'react';
|
package/dist/esm/hooks/index.js
CHANGED
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
import { PreferenceLevel, SeverityLevelEnum, WorkflowCriticalityEnum } from "@novu/js";
|
|
3
3
|
import { NovuProvider, useNovu } from "./NovuProvider.js";
|
|
4
4
|
export * from "./useCounts.js";
|
|
5
|
+
export * from "./useCreateSubscription.js";
|
|
5
6
|
export * from "./useNotifications.js";
|
|
6
7
|
export * from "./usePreferences.js";
|
|
8
|
+
export * from "./useRemoveSubscription.js";
|
|
7
9
|
export * from "./useSchedule.js";
|
|
10
|
+
export * from "./useSubscription.js";
|
|
11
|
+
export * from "./useSubscriptions.js";
|
|
12
|
+
export * from "./useUpdateSubscription.js";
|
|
8
13
|
export {
|
|
9
14
|
NovuProvider,
|
|
10
15
|
PreferenceLevel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export type
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/index.ts"],"sourcesContent":["export type * from '@novu/js';\nexport { PreferenceLevel, SeverityLevelEnum, WorkflowCriticalityEnum } from '@novu/js';\nexport { NovuProvider, useNovu } from './NovuProvider';\nexport * from './useCounts';\nexport * from './useCreateSubscription';\nexport * from './useNotifications';\nexport * from './usePreferences';\nexport * from './useRemoveSubscription';\nexport * from './useSchedule';\nexport * from './useSubscription';\nexport * from './useSubscriptions';\nexport * from './useUpdateSubscription';\n"],"mappings":";AACA,SAAS,iBAAiB,mBAAmB,+BAA+B;AAC5E,SAAS,cAAc,eAAe;AACtC,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// src/hooks/useCounts.ts
|
|
2
2
|
import { areTagsEqual, isSameFilter } from "@novu/js";
|
|
3
|
-
import { useEffect,
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { useDataRef } from "./internal/useDataRef.js";
|
|
4
5
|
import { useWebSocketEvent } from "./internal/useWebsocketEvent.js";
|
|
5
6
|
import { useNovu } from "./NovuProvider.js";
|
|
6
7
|
var useCounts = (props) => {
|
|
7
8
|
const { filters, onSuccess, onError } = props;
|
|
8
9
|
const { notifications } = useNovu();
|
|
9
|
-
const filtersRef =
|
|
10
|
+
const filtersRef = useDataRef(filters);
|
|
10
11
|
const [error, setError] = useState();
|
|
11
12
|
const [counts, setCounts] = useState();
|
|
12
13
|
const [isLoading, setIsLoading] = useState(true);
|
|
13
14
|
const [isFetching, setIsFetching] = useState(false);
|
|
14
|
-
filtersRef.current = filters;
|
|
15
15
|
const sync = async (notification, overrideFilters) => {
|
|
16
16
|
const currentFilters = overrideFilters || filtersRef.current;
|
|
17
17
|
const existingCounts = currentFilters.map((filter) => ({ count: 0, filter }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useCounts.ts"],"sourcesContent":["import { areTagsEqual, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useEffect,
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useCounts.ts"],"sourcesContent":["import { areTagsEqual, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useEffect, useState } from 'react';\nimport { useDataRef } from './internal/useDataRef';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\nimport { useNovu } from './NovuProvider';\n\ntype Count = {\n count: number;\n filter: NotificationFilter;\n};\n\n/**\n * Props for the useCounts hook.\n *\n * @example\n * ```tsx\n * // Count unread notifications\n * const { counts } = useCounts({\n * filters: [{ read: false }]\n * });\n *\n * // Count unseen notifications with specific tags\n * const { counts } = useCounts({\n * filters: [{ seen: false, tags: ['important'] }]\n * });\n *\n * // Count seen but unread notifications\n * const { counts } = useCounts({\n * filters: [{ seen: true, read: false }]\n * });\n * ```\n */\nexport type UseCountsProps = {\n filters: NotificationFilter[];\n onSuccess?: (data: Count[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport type UseCountsResult = {\n counts?: Count[];\n error?: NovuError;\n isLoading: boolean; // initial loading\n isFetching: boolean; // the request is in flight\n refetch: () => Promise<void>;\n};\n\nexport const useCounts = (props: UseCountsProps): UseCountsResult => {\n const { filters, onSuccess, onError } = props;\n const { notifications } = useNovu();\n const filtersRef = useDataRef<NotificationFilter[]>(filters);\n const [error, setError] = useState<NovuError>();\n const [counts, setCounts] = useState<Count[]>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n\n const sync = async (notification?: Notification, overrideFilters?: NotificationFilter[]) => {\n const currentFilters = overrideFilters || filtersRef.current;\n const existingCounts = currentFilters.map((filter) => ({ count: 0, filter }));\n let countFiltersToFetch: NotificationFilter[] = [];\n if (notification) {\n for (let i = 0; i < existingCounts.length; i++) {\n const filter = currentFilters[i];\n const isSeverityMatches =\n !filter.severity ||\n (Array.isArray(filter.severity) && filter.severity.length === 0) ||\n (Array.isArray(filter.severity) && filter.severity.includes(notification.severity)) ||\n (!Array.isArray(filter.severity) && filter.severity === notification.severity);\n\n if (areTagsEqual(filter.tags, notification.tags) && isSeverityMatches) {\n countFiltersToFetch.push(filter);\n }\n }\n } else {\n countFiltersToFetch = currentFilters;\n }\n\n if (countFiltersToFetch.length === 0) {\n return;\n }\n\n setIsFetching(true);\n const countsRes = await notifications.count({ filters: countFiltersToFetch });\n setIsFetching(false);\n setIsLoading(false);\n if (countsRes.error) {\n setError(countsRes.error);\n onError?.(countsRes.error);\n\n return;\n }\n const data = countsRes.data!;\n onSuccess?.(data.counts);\n\n setCounts((oldCounts) => {\n const newCounts: Count[] = [];\n const countsReceived = data.counts;\n\n for (let i = 0; i < existingCounts.length; i++) {\n const existingFilter = existingCounts[i].filter;\n const countReceived = countsReceived.find((c) => isSameFilter(c.filter, existingFilter));\n const count = countReceived || oldCounts?.[i];\n if (count) {\n newCounts.push(count);\n }\n }\n\n return newCounts;\n });\n };\n\n useWebSocketEvent({\n event: 'notifications.notification_received',\n eventHandler: (data) => {\n sync(data.result);\n },\n });\n\n useWebSocketEvent({\n event: 'notifications.unread_count_changed',\n eventHandler: () => {\n sync();\n },\n });\n\n useEffect(() => {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n sync(undefined, filters);\n }, [JSON.stringify(filters)]);\n\n const refetch = async () => {\n await sync();\n };\n\n return { counts, error, refetch, isLoading, isFetching };\n};\n"],"mappings":";AAAA,SAAS,cAAc,oBAAiE;AACxF,SAAS,WAAW,gBAAgB;AACpC,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAClC,SAAS,eAAe;AA0CjB,IAAM,YAAY,CAAC,UAA2C;AACnE,QAAM,EAAE,SAAS,WAAW,QAAQ,IAAI;AACxC,QAAM,EAAE,cAAc,IAAI,QAAQ;AAClC,QAAM,aAAa,WAAiC,OAAO;AAC3D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAkB;AAC9C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,OAAO,OAAO,cAA6B,oBAA2C;AAC1F,UAAM,iBAAiB,mBAAmB,WAAW;AACrD,UAAM,iBAAiB,eAAe,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,EAAE;AAC5E,QAAI,sBAA4C,CAAC;AACjD,QAAI,cAAc;AAChB,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,SAAS,eAAe,CAAC;AAC/B,cAAM,oBACJ,CAAC,OAAO,YACP,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,SAAS,WAAW,KAC7D,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,SAAS,SAAS,aAAa,QAAQ,KAChF,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,aAAa,aAAa;AAEvE,YAAI,aAAa,OAAO,MAAM,aAAa,IAAI,KAAK,mBAAmB;AACrE,8BAAoB,KAAK,MAAM;AAAA,QACjC;AAAA,MACF;AAAA,IACF,OAAO;AACL,4BAAsB;AAAA,IACxB;AAEA,QAAI,oBAAoB,WAAW,GAAG;AACpC;AAAA,IACF;AAEA,kBAAc,IAAI;AAClB,UAAM,YAAY,MAAM,cAAc,MAAM,EAAE,SAAS,oBAAoB,CAAC;AAC5E,kBAAc,KAAK;AACnB,iBAAa,KAAK;AAClB,QAAI,UAAU,OAAO;AACnB,eAAS,UAAU,KAAK;AACxB,gBAAU,UAAU,KAAK;AAEzB;AAAA,IACF;AACA,UAAM,OAAO,UAAU;AACvB,gBAAY,KAAK,MAAM;AAEvB,cAAU,CAAC,cAAc;AACvB,YAAM,YAAqB,CAAC;AAC5B,YAAM,iBAAiB,KAAK;AAE5B,eAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAM,iBAAiB,eAAe,CAAC,EAAE;AACzC,cAAM,gBAAgB,eAAe,KAAK,CAAC,MAAM,aAAa,EAAE,QAAQ,cAAc,CAAC;AACvF,cAAM,QAAQ,iBAAiB,YAAY,CAAC;AAC5C,YAAI,OAAO;AACT,oBAAU,KAAK,KAAK;AAAA,QACtB;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,oBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,cAAc,CAAC,SAAS;AACtB,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF,CAAC;AAED,oBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,cAAc,MAAM;AAClB,WAAK;AAAA,IACP;AAAA,EACF,CAAC;AAED,YAAU,MAAM;AACd,aAAS,MAAS;AAClB,iBAAa,IAAI;AACjB,kBAAc,KAAK;AACnB,SAAK,QAAW,OAAO;AAAA,EACzB,GAAG,CAAC,KAAK,UAAU,OAAO,CAAC,CAAC;AAE5B,QAAM,UAAU,YAAY;AAC1B,UAAM,KAAK;AAAA,EACb;AAEA,SAAO,EAAE,QAAQ,OAAO,SAAS,WAAW,WAAW;AACzD;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TopicSubscription, NovuError, CreateSubscriptionArgs } from '@novu/js';
|
|
2
|
+
|
|
3
|
+
type UseCreateSubscriptionProps = {
|
|
4
|
+
onSuccess?: (data: TopicSubscription) => void;
|
|
5
|
+
onError?: (error: NovuError) => void;
|
|
6
|
+
};
|
|
7
|
+
type UseCreateSubscriptionResult = {
|
|
8
|
+
isCreating: boolean;
|
|
9
|
+
error?: NovuError;
|
|
10
|
+
create: (args: CreateSubscriptionArgs) => Promise<{
|
|
11
|
+
data?: TopicSubscription | undefined;
|
|
12
|
+
error?: NovuError | undefined;
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
15
|
+
declare const useCreateSubscription: (props?: UseCreateSubscriptionProps) => UseCreateSubscriptionResult;
|
|
16
|
+
|
|
17
|
+
export { type UseCreateSubscriptionProps, type UseCreateSubscriptionResult, useCreateSubscription };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/hooks/useCreateSubscription.ts
|
|
2
|
+
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
import { useNovu } from "./NovuProvider.js";
|
|
4
|
+
var useCreateSubscription = (props = {}) => {
|
|
5
|
+
const propsRef = useRef(props);
|
|
6
|
+
propsRef.current = props;
|
|
7
|
+
const novu = useNovu();
|
|
8
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
9
|
+
const [error, setError] = useState();
|
|
10
|
+
const create = useCallback(
|
|
11
|
+
async (args) => {
|
|
12
|
+
const { onSuccess, onError } = propsRef.current;
|
|
13
|
+
setError(void 0);
|
|
14
|
+
setIsCreating(true);
|
|
15
|
+
const response = await novu.subscriptions.create(args);
|
|
16
|
+
setIsCreating(false);
|
|
17
|
+
if (response.error) {
|
|
18
|
+
setError(response.error);
|
|
19
|
+
onError?.(response.error);
|
|
20
|
+
} else if (response.data) {
|
|
21
|
+
onSuccess?.(response.data);
|
|
22
|
+
}
|
|
23
|
+
return response;
|
|
24
|
+
},
|
|
25
|
+
[novu]
|
|
26
|
+
);
|
|
27
|
+
return {
|
|
28
|
+
create,
|
|
29
|
+
isCreating,
|
|
30
|
+
error
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export {
|
|
34
|
+
useCreateSubscription
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=useCreateSubscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useCreateSubscription.ts"],"sourcesContent":["import { CreateSubscriptionArgs, NovuError, TopicSubscription } from '@novu/js';\nimport { useCallback, useRef, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\nexport type UseCreateSubscriptionProps = {\n onSuccess?: (data: TopicSubscription) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport type UseCreateSubscriptionResult = {\n isCreating: boolean;\n error?: NovuError;\n create: (args: CreateSubscriptionArgs) => Promise<{\n data?: TopicSubscription | undefined;\n error?: NovuError | undefined;\n }>;\n};\n\nexport const useCreateSubscription = (props: UseCreateSubscriptionProps = {}): UseCreateSubscriptionResult => {\n const propsRef = useRef<UseCreateSubscriptionProps>(props);\n propsRef.current = props;\n const novu = useNovu();\n const [isCreating, setIsCreating] = useState(false);\n const [error, setError] = useState<NovuError>();\n\n const create = useCallback(\n async (args: CreateSubscriptionArgs) => {\n const { onSuccess, onError } = propsRef.current;\n setError(undefined);\n setIsCreating(true);\n\n const response = await novu.subscriptions.create(args);\n\n setIsCreating(false);\n\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else if (response.data) {\n onSuccess?.(response.data);\n }\n\n return response;\n },\n [novu]\n );\n\n return {\n create,\n isCreating,\n error,\n };\n};\n"],"mappings":";AACA,SAAS,aAAa,QAAQ,gBAAgB;AAC9C,SAAS,eAAe;AAgBjB,IAAM,wBAAwB,CAAC,QAAoC,CAAC,MAAmC;AAC5G,QAAM,WAAW,OAAmC,KAAK;AACzD,WAAS,UAAU;AACnB,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAE9C,QAAM,SAAS;AAAA,IACb,OAAO,SAAiC;AACtC,YAAM,EAAE,WAAW,QAAQ,IAAI,SAAS;AACxC,eAAS,MAAS;AAClB,oBAAc,IAAI;AAElB,YAAM,WAAW,MAAM,KAAK,cAAc,OAAO,IAAI;AAErD,oBAAc,KAAK;AAEnB,UAAI,SAAS,OAAO;AAClB,iBAAS,SAAS,KAAK;AACvB,kBAAU,SAAS,KAAK;AAAA,MAC1B,WAAW,SAAS,MAAM;AACxB,oBAAY,SAAS,IAAI;AAAA,MAC3B;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/hooks/useNotifications.ts
|
|
2
2
|
import { checkNotificationMatchesFilter, isSameFilter } from "@novu/js";
|
|
3
|
-
import { useCallback, useEffect,
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { useDataRef } from "./internal/useDataRef.js";
|
|
4
5
|
import { useWebSocketEvent } from "./internal/useWebsocketEvent.js";
|
|
5
6
|
import { useNovu } from "./NovuProvider.js";
|
|
6
7
|
var useNotifications = (props) => {
|
|
@@ -12,16 +13,13 @@ var useNotifications = (props) => {
|
|
|
12
13
|
snoozed = false,
|
|
13
14
|
seen,
|
|
14
15
|
severity,
|
|
15
|
-
limit,
|
|
16
|
+
limit = 10,
|
|
16
17
|
onSuccess,
|
|
17
18
|
onError
|
|
18
19
|
} = props || {};
|
|
19
|
-
const
|
|
20
|
-
const {
|
|
21
|
-
const
|
|
22
|
-
() => filterRef.current || { tags, data: dataFilter, severity },
|
|
23
|
-
[tags, dataFilter, severity]
|
|
24
|
-
);
|
|
20
|
+
const limitRef = useDataRef(limit);
|
|
21
|
+
const filterRef = useDataRef({ tags, data: dataFilter, read, archived, snoozed, seen, severity });
|
|
22
|
+
const novu = useNovu();
|
|
25
23
|
const [data, setData] = useState();
|
|
26
24
|
const [error, setError] = useState();
|
|
27
25
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -29,24 +27,31 @@ var useNotifications = (props) => {
|
|
|
29
27
|
const [hasMore, setHasMore] = useState(false);
|
|
30
28
|
const length = data?.length;
|
|
31
29
|
const after = length ? data[length - 1].id : void 0;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
30
|
+
const afterRef = useDataRef(after);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const listener = ({
|
|
33
|
+
data: data2
|
|
34
|
+
}) => {
|
|
35
|
+
if (!data2 || !isSameFilter(filterRef.current, data2.filter)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
setData(data2.notifications);
|
|
39
|
+
setHasMore(data2.hasMore);
|
|
40
|
+
};
|
|
41
|
+
const cleanup = novu.on("notifications.list.updated", listener);
|
|
42
|
+
return () => {
|
|
43
|
+
cleanup();
|
|
44
|
+
};
|
|
45
|
+
}, [filterRef, novu]);
|
|
44
46
|
useWebSocketEvent({
|
|
45
47
|
event: "notifications.notification_received",
|
|
46
48
|
eventHandler: ({ result: notification }) => {
|
|
47
|
-
const currentFilter =
|
|
49
|
+
const currentFilter = filterRef.current;
|
|
48
50
|
const matches = checkNotificationMatchesFilter(notification, currentFilter);
|
|
49
|
-
if (matches)
|
|
51
|
+
if (matches) {
|
|
52
|
+
const cacheKey = { ...currentFilter, limit: limitRef.current };
|
|
53
|
+
novu.notifications.cache.unshift(cacheKey, notification);
|
|
54
|
+
}
|
|
50
55
|
}
|
|
51
56
|
});
|
|
52
57
|
const fetchNotifications = useCallback(
|
|
@@ -57,59 +62,51 @@ var useNotifications = (props) => {
|
|
|
57
62
|
setIsFetching(false);
|
|
58
63
|
}
|
|
59
64
|
setIsFetching(true);
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
...currentFilter,
|
|
65
|
+
const response = await novu.notifications.list({
|
|
66
|
+
...filterRef.current,
|
|
63
67
|
limit,
|
|
64
|
-
after: options?.refetch ? void 0 :
|
|
68
|
+
after: options?.refetch ? void 0 : afterRef.current
|
|
65
69
|
});
|
|
66
70
|
if (response.error) {
|
|
67
71
|
setError(response.error);
|
|
68
72
|
onError?.(response.error);
|
|
73
|
+
setIsLoading(false);
|
|
74
|
+
setIsFetching(false);
|
|
69
75
|
} else if (response.data) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
const responseData = response.data;
|
|
77
|
+
onSuccess?.(responseData.notifications);
|
|
78
|
+
setData(responseData.notifications);
|
|
79
|
+
setHasMore(responseData.hasMore);
|
|
80
|
+
setIsLoading(false);
|
|
81
|
+
setIsFetching(false);
|
|
73
82
|
}
|
|
74
|
-
setIsLoading(false);
|
|
75
|
-
setIsFetching(false);
|
|
76
83
|
},
|
|
77
|
-
[
|
|
84
|
+
[novu, filterRef, afterRef, limit, onError, onSuccess]
|
|
78
85
|
);
|
|
79
86
|
useEffect(() => {
|
|
80
|
-
|
|
81
|
-
if (filterRef.current && isSameFilter(filterRef.current, newFilter)) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
notifications.clearCache({ filter: filterRef.current });
|
|
85
|
-
filterRef.current = newFilter;
|
|
87
|
+
novu.notifications.clearCache({ filter: filterRef.current });
|
|
86
88
|
fetchNotifications({ refetch: true });
|
|
87
|
-
}, [
|
|
88
|
-
const refetch = () => {
|
|
89
|
-
|
|
90
|
-
notifications.clearCache({ filter });
|
|
89
|
+
}, [filterRef, novu, JSON.stringify(filterRef.current), fetchNotifications]);
|
|
90
|
+
const refetch = useCallback(() => {
|
|
91
|
+
novu.notifications.clearCache({ filter: filterRef.current });
|
|
91
92
|
return fetchNotifications({ refetch: true });
|
|
92
|
-
};
|
|
93
|
-
const fetchMore = async () => {
|
|
93
|
+
}, [filterRef, novu, fetchNotifications]);
|
|
94
|
+
const fetchMore = useCallback(async () => {
|
|
94
95
|
if (!hasMore || isFetching) return;
|
|
95
96
|
return fetchNotifications();
|
|
96
|
-
};
|
|
97
|
-
const readAll = async () => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return await notifications.
|
|
108
|
-
};
|
|
109
|
-
const archiveAllRead = async () => {
|
|
110
|
-
const { tags: tags2, data: data2 } = getCurrentFilter();
|
|
111
|
-
return await notifications.archiveAllRead({ tags: tags2, data: data2 });
|
|
112
|
-
};
|
|
97
|
+
}, [hasMore, isFetching, fetchNotifications]);
|
|
98
|
+
const readAll = useCallback(async () => {
|
|
99
|
+
return await novu.notifications.readAll({ tags: filterRef.current.tags, data: filterRef.current.data });
|
|
100
|
+
}, [filterRef, novu]);
|
|
101
|
+
const seenAll = useCallback(async () => {
|
|
102
|
+
return await novu.notifications.seenAll({ tags: filterRef.current.tags, data: filterRef.current.data });
|
|
103
|
+
}, [filterRef, novu]);
|
|
104
|
+
const archiveAll = useCallback(async () => {
|
|
105
|
+
return await novu.notifications.archiveAll({ tags: filterRef.current.tags, data: filterRef.current.data });
|
|
106
|
+
}, [filterRef, novu]);
|
|
107
|
+
const archiveAllRead = useCallback(async () => {
|
|
108
|
+
return await novu.notifications.archiveAllRead({ tags: filterRef.current.tags, data: filterRef.current.data });
|
|
109
|
+
}, [filterRef, novu]);
|
|
113
110
|
return {
|
|
114
111
|
readAll,
|
|
115
112
|
seenAll,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hooks/useNotifications.ts"],"sourcesContent":["import { checkNotificationMatchesFilter, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useCallback, useEffect,
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useNotifications.ts"],"sourcesContent":["import { checkNotificationMatchesFilter, isSameFilter, Notification, NotificationFilter, NovuError } from '@novu/js';\nimport { useCallback, useEffect, useState } from 'react';\nimport { useDataRef } from './internal/useDataRef';\nimport { useWebSocketEvent } from './internal/useWebsocketEvent';\nimport { useNovu } from './NovuProvider';\n\n/**\n * Props for the useNotifications hook.\n *\n * @example\n * ```tsx\n * // Get unread notifications\n * const { notifications } = useNotifications({\n * read: false\n * });\n *\n * // Get unseen notifications with specific tags\n * const { notifications } = useNotifications({\n * seen: false,\n * tags: ['important']\n * });\n *\n * // Get notifications (auto-updates in real time when new notifications arrive)\n * const { notifications } = useNotifications({\n * read: false\n * });\n * ```\n */\nexport type UseNotificationsProps = {\n tags?: NotificationFilter['tags'];\n data?: NotificationFilter['data'];\n read?: NotificationFilter['read'];\n archived?: NotificationFilter['archived'];\n snoozed?: NotificationFilter['snoozed'];\n seen?: NotificationFilter['seen'];\n severity?: NotificationFilter['severity'];\n limit?: number;\n onSuccess?: (data: Notification[]) => void;\n onError?: (error: NovuError) => void;\n};\n\nexport type UseNotificationsResult = {\n notifications?: Notification[];\n error?: NovuError;\n isLoading: boolean;\n isFetching: boolean;\n hasMore: boolean;\n readAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n seenAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n archiveAll: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n archiveAllRead: () => Promise<{\n data?: void | undefined;\n error?: NovuError | undefined;\n }>;\n refetch: () => Promise<void>;\n fetchMore: () => Promise<void>;\n};\n\nexport const useNotifications = (props?: UseNotificationsProps): UseNotificationsResult => {\n const {\n tags,\n data: dataFilter,\n read,\n archived = false,\n snoozed = false,\n seen,\n severity,\n limit = 10,\n onSuccess,\n onError,\n } = props || {};\n const limitRef = useDataRef<number | undefined>(limit);\n const filterRef = useDataRef<NotificationFilter>({ tags, data: dataFilter, read, archived, snoozed, seen, severity });\n const novu = useNovu();\n const [data, setData] = useState<Array<Notification>>();\n const [error, setError] = useState<NovuError>();\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [hasMore, setHasMore] = useState(false);\n const length = data?.length;\n const after = length ? data[length - 1].id : undefined;\n const afterRef = useDataRef<string | undefined>(after);\n\n useEffect(() => {\n const listener = ({\n data,\n }: {\n data: { notifications: Notification[]; hasMore: boolean; filter: NotificationFilter };\n }) => {\n if (!data || !isSameFilter(filterRef.current, data.filter)) {\n return;\n }\n\n // the event is called with the list of all notifications cached matching the current filter\n setData(data.notifications);\n setHasMore(data.hasMore);\n };\n\n const cleanup = novu.on('notifications.list.updated', listener);\n\n return () => {\n cleanup();\n };\n }, [filterRef, novu]);\n\n useWebSocketEvent({\n event: 'notifications.notification_received',\n eventHandler: ({ result: notification }) => {\n const currentFilter = filterRef.current;\n const matches = checkNotificationMatchesFilter(notification, currentFilter);\n if (matches) {\n // the limit and after props are used to create a cache key\n // the first batch of notifications in the cache doesn't include the after prop and we want to push to the first batch\n const cacheKey = { ...currentFilter, limit: limitRef.current };\n novu.notifications.cache.unshift(cacheKey, notification);\n }\n },\n });\n\n const fetchNotifications = useCallback(\n async (options?: { refetch: boolean }) => {\n if (options?.refetch) {\n setError(undefined);\n setIsLoading(true);\n setIsFetching(false);\n }\n setIsFetching(true);\n\n const response = await novu.notifications.list({\n ...filterRef.current,\n limit,\n after: options?.refetch ? undefined : afterRef.current,\n });\n\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n setIsLoading(false);\n setIsFetching(false);\n } else if (response.data) {\n const responseData = response.data;\n onSuccess?.(responseData.notifications);\n setData(responseData.notifications);\n setHasMore(responseData.hasMore);\n setIsLoading(false);\n setIsFetching(false);\n }\n },\n [novu, filterRef, afterRef, limit, onError, onSuccess]\n );\n\n useEffect(() => {\n novu.notifications.clearCache({ filter: filterRef.current });\n fetchNotifications({ refetch: true });\n }, [filterRef, novu, JSON.stringify(filterRef.current), fetchNotifications]);\n\n const refetch = useCallback(() => {\n novu.notifications.clearCache({ filter: filterRef.current });\n return fetchNotifications({ refetch: true });\n }, [filterRef, novu, fetchNotifications]);\n\n const fetchMore = useCallback(async () => {\n if (!hasMore || isFetching) return;\n\n return fetchNotifications();\n }, [hasMore, isFetching, fetchNotifications]);\n\n const readAll = useCallback(async () => {\n return await novu.notifications.readAll({ tags: filterRef.current.tags, data: filterRef.current.data });\n }, [filterRef, novu]);\n\n const seenAll = useCallback(async () => {\n return await novu.notifications.seenAll({ tags: filterRef.current.tags, data: filterRef.current.data });\n }, [filterRef, novu]);\n\n const archiveAll = useCallback(async () => {\n return await novu.notifications.archiveAll({ tags: filterRef.current.tags, data: filterRef.current.data });\n }, [filterRef, novu]);\n\n const archiveAllRead = useCallback(async () => {\n return await novu.notifications.archiveAllRead({ tags: filterRef.current.tags, data: filterRef.current.data });\n }, [filterRef, novu]);\n\n return {\n readAll,\n seenAll,\n archiveAll,\n archiveAllRead,\n notifications: data,\n error,\n isLoading,\n isFetching,\n refetch,\n fetchMore,\n hasMore,\n };\n};\n"],"mappings":"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","names":["data"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NovuError, DeleteSubscriptionArgs } from '@novu/js';
|
|
2
|
+
|
|
3
|
+
type UseRemoveSubscriptionProps = {
|
|
4
|
+
onSuccess?: () => void;
|
|
5
|
+
onError?: (error: NovuError) => void;
|
|
6
|
+
};
|
|
7
|
+
type RemoveResult = Promise<{
|
|
8
|
+
error?: NovuError;
|
|
9
|
+
}>;
|
|
10
|
+
type UseRemoveSubscriptionResult = {
|
|
11
|
+
isRemoving: boolean;
|
|
12
|
+
error?: NovuError;
|
|
13
|
+
remove: (args: DeleteSubscriptionArgs) => RemoveResult;
|
|
14
|
+
};
|
|
15
|
+
declare const useRemoveSubscription: (props?: UseRemoveSubscriptionProps) => UseRemoveSubscriptionResult;
|
|
16
|
+
|
|
17
|
+
export { type UseRemoveSubscriptionProps, type UseRemoveSubscriptionResult, useRemoveSubscription };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/hooks/useRemoveSubscription.ts
|
|
2
|
+
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
import { useNovu } from "./NovuProvider.js";
|
|
4
|
+
var useRemoveSubscription = (props = {}) => {
|
|
5
|
+
const propsRef = useRef(props);
|
|
6
|
+
propsRef.current = props;
|
|
7
|
+
const novu = useNovu();
|
|
8
|
+
const [isRemoving, setIsRemoving] = useState(false);
|
|
9
|
+
const [error, setError] = useState();
|
|
10
|
+
const removeCallback = useCallback(
|
|
11
|
+
async (args) => {
|
|
12
|
+
const { onSuccess, onError } = propsRef.current;
|
|
13
|
+
setError(void 0);
|
|
14
|
+
setIsRemoving(true);
|
|
15
|
+
const response = await novu.subscriptions.delete(args);
|
|
16
|
+
setIsRemoving(false);
|
|
17
|
+
if (response.error) {
|
|
18
|
+
setError(response.error);
|
|
19
|
+
onError?.(response.error);
|
|
20
|
+
} else if (response.data) {
|
|
21
|
+
onSuccess?.();
|
|
22
|
+
}
|
|
23
|
+
return response;
|
|
24
|
+
},
|
|
25
|
+
[novu]
|
|
26
|
+
);
|
|
27
|
+
return {
|
|
28
|
+
remove: removeCallback,
|
|
29
|
+
isRemoving,
|
|
30
|
+
error
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export {
|
|
34
|
+
useRemoveSubscription
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=useRemoveSubscription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/hooks/useRemoveSubscription.ts"],"sourcesContent":["import { BaseDeleteSubscriptionArgs, NovuError, DeleteSubscriptionArgs as RemoveSubscriptionArgs } from '@novu/js';\nimport { useCallback, useRef, useState } from 'react';\nimport { useNovu } from './NovuProvider';\n\nexport type UseRemoveSubscriptionProps = {\n onSuccess?: () => void;\n onError?: (error: NovuError) => void;\n};\n\ntype RemoveResult = Promise<{\n error?: NovuError;\n}>;\n\nexport type UseRemoveSubscriptionResult = {\n isRemoving: boolean;\n error?: NovuError;\n remove: (args: RemoveSubscriptionArgs) => RemoveResult;\n};\n\nexport const useRemoveSubscription = (props: UseRemoveSubscriptionProps = {}): UseRemoveSubscriptionResult => {\n const propsRef = useRef<UseRemoveSubscriptionProps>(props);\n propsRef.current = props;\n const novu = useNovu();\n const [isRemoving, setIsRemoving] = useState(false);\n const [error, setError] = useState<NovuError>();\n\n const removeCallback = useCallback(\n async (args: RemoveSubscriptionArgs): RemoveResult => {\n const { onSuccess, onError } = propsRef.current;\n setError(undefined);\n setIsRemoving(true);\n\n const response = await novu.subscriptions.delete(args as BaseDeleteSubscriptionArgs);\n\n setIsRemoving(false);\n\n if (response.error) {\n setError(response.error);\n onError?.(response.error);\n } else if (response.data) {\n onSuccess?.();\n }\n\n return response;\n },\n [novu]\n );\n\n return {\n remove: removeCallback,\n isRemoving,\n error,\n };\n};\n"],"mappings":";AACA,SAAS,aAAa,QAAQ,gBAAgB;AAC9C,SAAS,eAAe;AAiBjB,IAAM,wBAAwB,CAAC,QAAoC,CAAC,MAAmC;AAC5G,QAAM,WAAW,OAAmC,KAAK;AACzD,WAAS,UAAU;AACnB,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAoB;AAE9C,QAAM,iBAAiB;AAAA,IACrB,OAAO,SAA+C;AACpD,YAAM,EAAE,WAAW,QAAQ,IAAI,SAAS;AACxC,eAAS,MAAS;AAClB,oBAAc,IAAI;AAElB,YAAM,WAAW,MAAM,KAAK,cAAc,OAAO,IAAkC;AAEnF,oBAAc,KAAK;AAEnB,UAAI,SAAS,OAAO;AAClB,iBAAS,SAAS,KAAK;AACvB,kBAAU,SAAS,KAAK;AAAA,MAC1B,WAAW,SAAS,MAAM;AACxB,oBAAY;AAAA,MACd;AAEA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,IAAI;AAAA,EACP;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TopicSubscription, NovuError } from '@novu/js';
|
|
2
|
+
|
|
3
|
+
type UseSubscriptionProps = {
|
|
4
|
+
topicKey: string;
|
|
5
|
+
identifier?: string;
|
|
6
|
+
onSuccess?: (data: TopicSubscription | null) => void;
|
|
7
|
+
onError?: (error: NovuError) => void;
|
|
8
|
+
};
|
|
9
|
+
type UseSubscriptionResult = {
|
|
10
|
+
subscription?: TopicSubscription | null;
|
|
11
|
+
error?: NovuError;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
isFetching: boolean;
|
|
14
|
+
refetch: () => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Get a subscription for a topic.
|
|
18
|
+
*/
|
|
19
|
+
declare const useSubscription: (props: UseSubscriptionProps) => UseSubscriptionResult;
|
|
20
|
+
|
|
21
|
+
export { type UseSubscriptionProps, type UseSubscriptionResult, useSubscription };
|