@notificationapi/react 0.0.28 → 0.0.29

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.
@@ -1,5 +1,6 @@
1
1
  import { PropsWithChildren } from 'react';
2
- import { GetPreferencesResponse, InAppNotification, BaseDeliveryOptions, Channels, DeliveryOptionsForEmail, DeliveryOptionsForInappWeb } from '@notificationapi/core/dist/interfaces';
2
+ import { NotificationAPIClientSDK } from '@notificationapi/core';
3
+ import { GetPreferencesResponse, InAppNotification, User, BaseDeliveryOptions, Channels, DeliveryOptionsForEmail, DeliveryOptionsForInappWeb } from '@notificationapi/core/dist/interfaces';
3
4
 
4
5
  export type Context = {
5
6
  notifications?: InAppNotification[];
@@ -16,11 +17,15 @@ export type Context = {
16
17
  delivery: DeliveryOptionsForEmail | DeliveryOptionsForInappWeb | BaseDeliveryOptions;
17
18
  subNotificationId?: string;
18
19
  }[]) => void;
20
+ getClient: () => typeof NotificationAPIClientSDK;
19
21
  };
20
22
  export declare const NotificationAPIContext: import('react').Context<Context | undefined>;
21
- type Props = {
22
- clientId: string;
23
+ type Props = ({
23
24
  userId: string;
25
+ } | {
26
+ user: Omit<User, 'createdAt' | 'updatedAt' | 'lastSeenTime'>;
27
+ }) & {
28
+ clientId: string;
24
29
  hashedUserId?: string;
25
30
  apiURL?: string;
26
31
  wsURL?: string;
@@ -1,10 +1,10 @@
1
1
  import { jsx as B } from "react/jsx-runtime";
2
- import { createContext as F, useState as N, useCallback as b, useMemo as G, useRef as m, useEffect as M, useContext as J } from "react";
3
- const _ = async (e, c, r, a, f, w, p) => {
4
- const h = z(a, f, w), l = await fetch(
5
- `https://${c}/${a}/users/${encodeURIComponent(
2
+ import { createContext as z, useState as N, useCallback as A, useMemo as F, useRef as y, useEffect as U, useContext as G } from "react";
3
+ const J = async (e, s, c, a, f, w, p) => {
4
+ const h = _(a, f, w), l = await fetch(
5
+ `https://${s}/${a}/users/${encodeURIComponent(
6
6
  f
7
- )}/${r}`,
7
+ )}/${c}`,
8
8
  {
9
9
  method: e,
10
10
  body: JSON.stringify(p),
@@ -18,7 +18,7 @@ const _ = async (e, c, r, a, f, w, p) => {
18
18
  } catch {
19
19
  return;
20
20
  }
21
- }, z = (e, c, r) => btoa(r ? e + ":" + c + ":" + r : e + ":" + c), U = {
21
+ }, _ = (e, s, c) => btoa(c ? e + ":" + s + ":" + c : e + ":" + s), M = {
22
22
  host: "api.notificationapi.com",
23
23
  websocketHost: "ws.notificationapi.com",
24
24
  userId: "",
@@ -31,70 +31,76 @@ const _ = async (e, c, r, a, f, w, p) => {
31
31
  onNewInAppNotifications: void 0,
32
32
  keepWebSocketAliveForSeconds: 86400
33
33
  // 24 hours
34
- }, o = {
35
- config: U,
34
+ }, n = {
35
+ config: M,
36
36
  init: function(e) {
37
- return this.config = { ...U, ...e }, {
37
+ return this.config = { ...M, ...e }, {
38
38
  ...this
39
39
  };
40
40
  },
41
41
  rest: {
42
- generic: function(e, c, r) {
43
- return _(
42
+ generic: function(e, s, c) {
43
+ return J(
44
44
  e,
45
- o.config.host,
46
- c,
47
- o.config.clientId,
48
- o.config.userId,
49
- o.config.hashedUserId,
50
- r
45
+ n.config.host,
46
+ s,
47
+ n.config.clientId,
48
+ n.config.userId,
49
+ n.config.hashedUserId,
50
+ c
51
51
  );
52
52
  },
53
- getNotifications: function(e, c) {
54
- return o.rest.generic(
53
+ // The functions below are nice wrappers over the generic
54
+ // rest api function above. They must follow REST API naming:
55
+ // Method + Resource, representing the end-point.
56
+ getNotifications: function(e, s) {
57
+ return n.rest.generic(
55
58
  "GET",
56
- `notifications/INAPP_WEB?count=${c}&before=${e}`
59
+ `notifications/INAPP_WEB?count=${s}&before=${e}`
57
60
  );
58
61
  },
59
62
  patchNotifications: function(e) {
60
- return o.rest.generic(
63
+ return n.rest.generic(
61
64
  "PATCH",
62
65
  "notifications/INAPP_WEB",
63
66
  e
64
67
  );
65
68
  },
66
69
  getPreferences: function() {
67
- return o.rest.generic("GET", "preferences");
70
+ return n.rest.generic("GET", "preferences");
68
71
  },
69
72
  postPreferences: function(e) {
70
- return o.rest.generic(
73
+ return n.rest.generic(
71
74
  "POST",
72
75
  "preferences",
73
76
  e
74
77
  );
78
+ },
79
+ postUser: function(e) {
80
+ return n.rest.generic("POST", "", e);
75
81
  }
76
82
  },
77
83
  websocket: {
78
84
  object: void 0,
79
85
  connect: function() {
80
- let e = `wss://${o.config.websocketHost}?userId=${encodeURIComponent(o.config.userId)}&envId=${o.config.clientId}`;
81
- return o.config.hashedUserId && (e += `&userIdHash=${encodeURIComponent(o.config.hashedUserId)}`), o.websocket.object = new WebSocket(e), o.websocket.object.onmessage = (c) => {
82
- const r = JSON.parse(c.data);
83
- if (!(!r || !r.route) && r.route === "inapp_web/new_notifications") {
84
- const a = r;
85
- o.config.onNewInAppNotifications && o.config.onNewInAppNotifications(
86
+ let e = `wss://${n.config.websocketHost}?userId=${encodeURIComponent(n.config.userId)}&envId=${n.config.clientId}`;
87
+ return n.config.hashedUserId && (e += `&userIdHash=${encodeURIComponent(n.config.hashedUserId)}`), n.websocket.object = new WebSocket(e), n.websocket.object.onmessage = (s) => {
88
+ const c = JSON.parse(s.data);
89
+ if (!(!c || !c.route) && c.route === "inapp_web/new_notifications") {
90
+ const a = c;
91
+ n.config.onNewInAppNotifications && n.config.onNewInAppNotifications(
86
92
  a.payload.notifications
87
93
  );
88
94
  }
89
- }, o.websocket.object;
95
+ }, n.websocket.object;
90
96
  },
91
97
  disconnect: function(e) {
92
- var c;
93
- o.websocket.object && ((c = o.websocket.object) == null || c.close(), e && e(o.websocket.object));
98
+ var s;
99
+ n.websocket.object && ((s = n.websocket.object) == null || s.close(), e && e(n.websocket.object));
94
100
  }
95
101
  },
96
102
  openWebSocket: function() {
97
- return o.websocket.connect(() => {
103
+ return n.websocket.connect(() => {
98
104
  setTimeout(
99
105
  () => {
100
106
  this.websocket.disconnect(() => {
@@ -105,20 +111,23 @@ const _ = async (e, c, r, a, f, w, p) => {
105
111
  );
106
112
  });
107
113
  },
114
+ // These functions are developer friendly wrappers over the rest APIs
115
+ // They may or may not do additional tasks.
116
+ // e.g. identify simply maps to postUsers
108
117
  getInAppNotifications: async (e) => {
109
- const c = e.maxCountNeeded || o.config.getInAppDefaultCount, r = e.oldestNeeded || o.config.getInAppDefaultOldest;
118
+ const s = e.maxCountNeeded || n.config.getInAppDefaultCount, c = e.oldestNeeded || n.config.getInAppDefaultOldest;
110
119
  let a = [], f = e.before, w = !0, p = !0;
111
120
  for (; p; ) {
112
- const h = (await o.rest.getNotifications(
121
+ const h = (await n.rest.getNotifications(
113
122
  f,
114
- c
123
+ s
115
124
  )).notifications.filter(
116
125
  (l) => !a.find((g) => g.id === l.id)
117
126
  );
118
127
  f = h.reduce(
119
128
  (l, g) => l < g.date ? l : g.date,
120
129
  e.before
121
- ), a = [...a, ...h], w = h.length > 0, p = !0, (!w || a.length >= c || f < r) && (p = !1);
130
+ ), a = [...a, ...h], w = h.length > 0, p = !0, (!w || a.length >= s || f < c) && (p = !1);
122
131
  }
123
132
  return {
124
133
  items: a,
@@ -127,17 +136,24 @@ const _ = async (e, c, r, a, f, w, p) => {
127
136
  };
128
137
  },
129
138
  updateInAppNotifications: async (e) => {
130
- const c = {
139
+ const s = {
131
140
  trackingIds: e.ids
132
141
  };
133
- return e.archived === !0 ? c.archived = (/* @__PURE__ */ new Date()).toISOString() : e.archived === !1 && (c.archived = null), e.clicked === !0 ? c.clicked = (/* @__PURE__ */ new Date()).toISOString() : e.clicked === !1 && (c.clicked = null), e.opened === !0 ? c.opened = (/* @__PURE__ */ new Date()).toISOString() : e.opened === !1 && (c.opened = null), o.rest.patchNotifications(c);
142
+ return e.archived === !0 ? s.archived = (/* @__PURE__ */ new Date()).toISOString() : e.archived === !1 && (s.archived = null), e.clicked === !0 ? s.clicked = (/* @__PURE__ */ new Date()).toISOString() : e.clicked === !1 && (s.clicked = null), e.opened === !0 ? s.opened = (/* @__PURE__ */ new Date()).toISOString() : e.opened === !1 && (s.opened = null), n.rest.patchNotifications(s);
134
143
  },
135
- getPreferences: async () => o.rest.getPreferences(),
136
- updateDeliveryOption: async (e) => o.rest.postPreferences([e])
137
- }, R = F(
144
+ getPreferences: async () => n.rest.getPreferences(),
145
+ updateDeliveryOption: async (e) => n.rest.postPreferences([e]),
146
+ identify: async (e) => {
147
+ if (e.id && e.id !== n.config.userId)
148
+ throw new Error(
149
+ "The id in the parameters does not match the initialized userId."
150
+ );
151
+ return n.rest.postUser(e);
152
+ }
153
+ }, E = z(
138
154
  void 0
139
155
  ), q = (e) => {
140
- const r = {
156
+ const c = {
141
157
  ...{
142
158
  apiURL: "https://api.notificationapi.com",
143
159
  wsURL: "wss://ws.notificationapi.com",
@@ -146,148 +162,153 @@ const _ = async (e, c, r, a, f, w, p) => {
146
162
  playSoundOnNewNotification: !1,
147
163
  newNotificationSoundPath: "https://proxy.notificationsounds.com/notification-sounds/elegant-notification-sound/download/file-sounds-1233-elegant.mp3"
148
164
  },
149
- ...e
150
- }, [a, f] = N(), [w, p] = N(), [h, l] = N(!1), [g, y] = N((/* @__PURE__ */ new Date()).toISOString()), [A, D] = N(!0), P = b(() => {
151
- r.playSoundOnNewNotification && new Audio(r.newNotificationSoundPath).play().catch((s) => {
152
- console.log("Failed to play new notification sound:", s);
165
+ ...e,
166
+ user: "userId" in e ? { id: e.userId } : e.user
167
+ }, [a, f] = N(), [w, p] = N(), [h, l] = N(!1), [g, m] = N((/* @__PURE__ */ new Date()).toISOString()), [b, P] = N(!0), D = A(() => {
168
+ c.playSoundOnNewNotification && new Audio(c.newNotificationSoundPath).play().catch((r) => {
169
+ console.log("Failed to play new notification sound:", r);
153
170
  });
154
- }, [r.newNotificationSoundPath, r.playSoundOnNewNotification]), S = b((n) => {
155
- const s = (/* @__PURE__ */ new Date()).toISOString();
156
- f((t) => (n = n.filter((i) => !(i.expDate && new Date(i.expDate * 1e3).toISOString() > s || i.date > s)), t ? [
157
- ...n.filter((i) => !t.find((d) => d.id === i.id)),
171
+ }, [c.newNotificationSoundPath, c.playSoundOnNewNotification]), S = A((i) => {
172
+ const r = (/* @__PURE__ */ new Date()).toISOString();
173
+ f((t) => (i = i.filter((o) => !(o.expDate && new Date(o.expDate * 1e3).toISOString() > r || o.date > r)), t ? [
174
+ ...i.filter((o) => !t.find((d) => d.id === o.id)),
158
175
  ...t
159
- ] : n));
160
- }, []), u = G(() => o.init({
161
- clientId: e.clientId,
162
- userId: e.userId,
163
- hashedUserId: e.hashedUserId,
164
- onNewInAppNotifications: (n) => {
165
- P(), S(n);
166
- }
167
- }), [
168
- e.clientId,
169
- e.userId,
170
- e.hashedUserId,
176
+ ] : i));
177
+ }, []), u = F(() => {
178
+ const i = n.init({
179
+ clientId: c.clientId,
180
+ userId: c.user.id,
181
+ hashedUserId: c.hashedUserId,
182
+ onNewInAppNotifications: (r) => {
183
+ D(), S(r);
184
+ }
185
+ });
186
+ return i.identify(c.user), i;
187
+ }, [
188
+ c.clientId,
189
+ c.user,
190
+ c.hashedUserId,
171
191
  S,
172
- P
173
- ]), v = b(
174
- async (n, s) => {
175
- const t = await u.rest.getNotifications(n, s);
176
- y(t.oldestReceived), D(t.couldLoadMore), S(t.notifications);
192
+ D
193
+ ]), O = A(
194
+ async (i, r) => {
195
+ const t = await u.rest.getNotifications(i, r);
196
+ m(t.oldestReceived), P(t.couldLoadMore), S(t.notifications);
177
197
  },
178
198
  [S, u.rest]
179
- ), O = m(A), C = m(h), x = m(g);
180
- M(() => {
181
- O.current = A, C.current = h, x.current = g;
182
- }, [A, h, g]);
183
- const k = b(
184
- async (n) => {
185
- if (!(!n && (!O.current || C.current))) {
199
+ ), v = y(b), C = y(h), x = y(g);
200
+ U(() => {
201
+ v.current = b, C.current = h, x.current = g;
202
+ }, [b, h, g]);
203
+ const k = A(
204
+ async (i) => {
205
+ if (!(!i && (!v.current || C.current))) {
186
206
  l(!0);
187
207
  try {
188
- await v(
189
- n ? (/* @__PURE__ */ new Date()).toISOString() : x.current,
190
- n ? r.initialLoadMaxCount : 1e3
208
+ await O(
209
+ i ? (/* @__PURE__ */ new Date()).toISOString() : x.current,
210
+ i ? c.initialLoadMaxCount : 1e3
191
211
  );
192
212
  } finally {
193
213
  l(!1);
194
214
  }
195
215
  }
196
216
  },
197
- [r.initialLoadMaxCount, v]
198
- ), $ = async (n) => {
217
+ [c.initialLoadMaxCount, O]
218
+ ), R = async (i) => {
199
219
  if (!a)
200
220
  return;
201
- const s = (/* @__PURE__ */ new Date()).toISOString(), t = a.filter((i) => n.includes(i.id) && !i.clicked).map((i) => i.id);
202
- u.updateInAppNotifications({ ids: t, clicked: !0 }), f((i) => {
203
- if (!i)
221
+ const r = (/* @__PURE__ */ new Date()).toISOString(), t = a.filter((o) => i.includes(o.id) && !o.clicked).map((o) => o.id);
222
+ u.updateInAppNotifications({ ids: t, clicked: !0 }), f((o) => {
223
+ if (!o)
204
224
  return [];
205
- const d = [...i];
225
+ const d = [...o];
206
226
  return d.filter((I) => t.includes(I.id)).forEach((I) => {
207
- I.clicked = s;
227
+ I.clicked = r;
208
228
  }), d;
209
229
  });
210
- }, E = async () => {
230
+ }, $ = async () => {
211
231
  if (!a)
212
232
  return;
213
- const n = (/* @__PURE__ */ new Date()).toISOString(), s = a.filter((t) => !t.opened || !t.seen).map((t) => t.id);
214
- s.length !== 0 && (u.updateInAppNotifications({
215
- ids: s,
233
+ const i = (/* @__PURE__ */ new Date()).toISOString(), r = a.filter((t) => !t.opened || !t.seen).map((t) => t.id);
234
+ r.length !== 0 && (u.updateInAppNotifications({
235
+ ids: r,
216
236
  opened: !0
217
237
  }), f((t) => {
218
238
  if (!t)
219
239
  return [];
220
- const i = [...t];
221
- return i.filter((d) => s.includes(d.id)).forEach((d) => {
222
- d.opened = n, d.seen = !0;
223
- }), i;
240
+ const o = [...t];
241
+ return o.filter((d) => r.includes(d.id)).forEach((d) => {
242
+ d.opened = i, d.seen = !0;
243
+ }), o;
224
244
  }));
225
- }, j = async (n) => {
245
+ }, j = async (i) => {
226
246
  if (!a)
227
247
  return;
228
- const s = a.filter((t) => t.archived && (n === "ALL" || n.includes(t.id))).map((t) => t.id);
229
- s.length !== 0 && (u.updateInAppNotifications({
230
- ids: s,
248
+ const r = a.filter((t) => t.archived && (i === "ALL" || i.includes(t.id))).map((t) => t.id);
249
+ r.length !== 0 && (u.updateInAppNotifications({
250
+ ids: r,
231
251
  archived: !1
232
252
  }), f((t) => {
233
253
  if (!t)
234
254
  return [];
235
- const i = [...t];
236
- return i.filter((d) => s.includes(d.id)).forEach((d) => {
255
+ const o = [...t];
256
+ return o.filter((d) => r.includes(d.id)).forEach((d) => {
237
257
  d.archived = void 0;
238
- }), i;
258
+ }), o;
239
259
  }));
240
- }, T = async (n) => {
260
+ }, T = async (i) => {
241
261
  if (!a)
242
262
  return;
243
- const s = (/* @__PURE__ */ new Date()).toISOString(), t = a.filter((i) => !i.archived && (n === "ALL" || n.includes(i.id))).map((i) => i.id);
244
- t.length !== 0 && (u.updateInAppNotifications({ ids: t, archived: !0 }), f((i) => {
245
- if (!i)
263
+ const r = (/* @__PURE__ */ new Date()).toISOString(), t = a.filter((o) => !o.archived && (i === "ALL" || i.includes(o.id))).map((o) => o.id);
264
+ t.length !== 0 && (u.updateInAppNotifications({ ids: t, archived: !0 }), f((o) => {
265
+ if (!o)
246
266
  return [];
247
- const d = [...i];
267
+ const d = [...o];
248
268
  return d.filter((I) => t.includes(I.id)).forEach((I) => {
249
- I.archived = s;
269
+ I.archived = r;
250
270
  }), d;
251
271
  }));
252
- }, W = (n, s, t, i) => L([
272
+ }, W = (i, r, t, o) => L([
253
273
  {
254
- notificationId: n,
255
- channel: s,
274
+ notificationId: i,
275
+ channel: r,
256
276
  delivery: t,
257
- subNotificationId: i
277
+ subNotificationId: o
258
278
  }
259
- ]), L = (n) => {
260
- u.rest.postPreferences(n).then(() => {
261
- u.getPreferences().then((s) => {
262
- p(s);
279
+ ]), L = (i) => {
280
+ u.rest.postPreferences(i).then(() => {
281
+ u.getPreferences().then((r) => {
282
+ p(r);
263
283
  });
264
284
  });
265
285
  };
266
- M(() => {
267
- f([]), l(!1), p(void 0), y((/* @__PURE__ */ new Date()).toISOString()), D(!0), k(!0), u.openWebSocket(), u.getPreferences().then((n) => {
268
- p(n);
286
+ U(() => {
287
+ f([]), l(!1), p(void 0), m((/* @__PURE__ */ new Date()).toISOString()), P(!0), k(!0), u.openWebSocket(), u.getPreferences().then((i) => {
288
+ p(i);
269
289
  });
270
290
  }, [u, k]);
271
291
  const H = {
272
292
  notifications: a,
273
293
  preferences: w,
274
294
  loadNotifications: k,
275
- markAsOpened: E,
295
+ markAsOpened: $,
276
296
  markAsArchived: T,
277
297
  markAsUnarchived: j,
278
- markAsClicked: $,
298
+ markAsClicked: R,
279
299
  updateDelivery: W,
280
- updateDeliveries: L
300
+ updateDeliveries: L,
301
+ getClient: () => u
281
302
  };
282
- return /* @__PURE__ */ B(R.Provider, { value: H, children: e.children });
303
+ return /* @__PURE__ */ B(E.Provider, { value: H, children: e.children });
283
304
  }, K = () => {
284
- const e = J(R);
305
+ const e = G(E);
285
306
  if (!e)
286
307
  throw new Error("useMyContext must be used within a MyProvider");
287
308
  return e;
288
309
  };
289
310
  q.useNotificationAPIContext = K;
290
311
  export {
291
- R as NotificationAPIContext,
312
+ E as NotificationAPIContext,
292
313
  q as NotificationAPIProvider
293
314
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@notificationapi/react",
3
3
  "private": false,
4
- "version": "0.0.28",
4
+ "version": "0.0.29",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
@@ -27,8 +27,8 @@
27
27
  "eslint": "^8.57.0",
28
28
  "eslint-plugin-react-hooks": "^4.6.0",
29
29
  "eslint-plugin-react-refresh": "^0.4.6",
30
- "prettier": "^3.3.3",
31
30
  "glob": "^10.4.1",
31
+ "prettier": "^3.3.3",
32
32
  "typescript": "^5.2.2",
33
33
  "vite": "^5.2.0",
34
34
  "vite-plugin-dts": "^3.9.1",
@@ -43,7 +43,7 @@
43
43
  "**/*.css"
44
44
  ],
45
45
  "dependencies": {
46
- "@notificationapi/core": "^0.0.8",
46
+ "@notificationapi/core": "^0.0.9",
47
47
  "antd": "^5.17.4",
48
48
  "javascript-time-ago": "^2.5.10",
49
49
  "liquidjs": "^10.14.0",