@notificationapi/react 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,26 +1,59 @@
1
- import { jsx as te } from "react/jsx-runtime";
2
- import { useMemo as B, useState as b, useCallback as N, useRef as R, useEffect as y, useContext as oe } from "react";
1
+ import { jsx as oe } from "react/jsx-runtime";
2
+ import { useMemo as z, useState as N, useCallback as A, useRef as F, useEffect as E, useContext as ie } from "react";
3
3
  import { NotificationAPIContext as V } from "./context.js";
4
- import { createDebugLogger as ie, formatApiCall as k } from "../../utils/debug.js";
5
- const ne = async (i, e, g, s, c, p, w) => {
6
- const h = re(s, c, p), f = await fetch(
7
- `https://${e}/${s}/users/${encodeURIComponent(
8
- c
9
- )}/${g}`,
10
- {
11
- method: i,
12
- body: JSON.stringify(w),
13
- headers: {
14
- Authorization: `Basic ${h}`
15
- }
16
- }
17
- );
4
+ import { createDebugLogger as ne, formatApiCall as C } from "../../utils/debug.js";
5
+ const re = async (o, e, u, a, c, h, I, l) => {
6
+ const p = se(a, c, h), b = `https://${e}/${a}/users/${encodeURIComponent(
7
+ c
8
+ )}/${u}`, w = {
9
+ Authorization: `Basic ${p}`
10
+ };
11
+ l && l.log("HTTP Request:", {
12
+ method: o,
13
+ host: e,
14
+ url: b,
15
+ body: I
16
+ });
17
+ const v = Date.now();
18
18
  try {
19
- return await f.json();
20
- } catch {
21
- return;
19
+ const m = await fetch(b, {
20
+ method: o,
21
+ body: JSON.stringify(I),
22
+ headers: w
23
+ });
24
+ l && l.log("HTTP Response:", m);
25
+ try {
26
+ const P = await m.json();
27
+ return l && l.log("Response Data:", P), P;
28
+ } catch (P) {
29
+ l && l.warn("Failed to parse response as JSON:", P);
30
+ return;
31
+ }
32
+ } catch (m) {
33
+ const P = Date.now() - v;
34
+ throw l && l.error("HTTP Request Failed:", {
35
+ error: m,
36
+ url: b,
37
+ headers: w,
38
+ duration: `${P}ms`
39
+ }), m;
40
+ }
41
+ }, se = (o, e, u) => btoa(u ? o + ":" + e + ":" + u : o + ":" + e);
42
+ class B {
43
+ constructor(e = !1) {
44
+ this.debug = e;
45
+ }
46
+ log(...e) {
47
+ this.debug && console.log("[NotificationAPI js core SDK Debug]", ...e);
48
+ }
49
+ warn(...e) {
50
+ this.debug && console.warn("[NotificationAPI js core SDK Debug]", ...e);
22
51
  }
23
- }, re = (i, e, g) => btoa(g ? i + ":" + e + ":" + g : i + ":" + e), K = {
52
+ error(...e) {
53
+ this.debug && console.error("[NotificationAPI js core SDK Debug]", ...e);
54
+ }
55
+ }
56
+ const J = {
24
57
  host: "api.notificationapi.com",
25
58
  websocketHost: "ws.notificationapi.com",
26
59
  userId: "",
@@ -28,84 +61,114 @@ const ne = async (i, e, g, s, c, p, w) => {
28
61
  hashedUserId: "",
29
62
  getInAppDefaultCount: 100,
30
63
  getInAppDefaultOldest: new Date(
31
- Date.now() - 2592e6
64
+ Date.now() - 30 * 24 * 60 * 60 * 1e3
32
65
  ).toISOString(),
33
66
  onNewInAppNotifications: void 0,
34
- keepWebSocketAliveForSeconds: 86400
67
+ keepWebSocketAliveForSeconds: 24 * 60 * 60,
35
68
  // 24 hours
36
- }, a = {
37
- config: K,
38
- init: function(i) {
39
- return this.config = { ...K, ...i }, {
69
+ debug: !1
70
+ }, s = {
71
+ config: J,
72
+ logger: new B(!1),
73
+ init: function(o) {
74
+ return this.config = { ...J, ...o }, this.logger = new B(this.config.debug), this.logger.log("Initialized with config:", {
75
+ userId: this.config.userId,
76
+ clientId: this.config.clientId,
77
+ host: this.config.host,
78
+ websocketHost: this.config.websocketHost,
79
+ debug: this.config.debug,
80
+ hasHashedUserId: !!this.config.hashedUserId
81
+ }), {
40
82
  ...this
41
83
  };
42
84
  },
43
85
  rest: {
44
- generic: function(i, e, g) {
45
- return ne(
46
- i,
47
- a.config.host,
86
+ generic: function(o, e, u) {
87
+ return s.logger.log(
88
+ `API Call: ${o} ${e}`,
89
+ u ? { body: u } : ""
90
+ ), re(
91
+ o,
92
+ s.config.host,
48
93
  e,
49
- a.config.clientId,
50
- a.config.userId,
51
- a.config.hashedUserId,
52
- g
94
+ s.config.clientId,
95
+ s.config.userId,
96
+ s.config.hashedUserId,
97
+ u,
98
+ s.logger
53
99
  );
54
100
  },
55
101
  // The functions below are nice wrappers over the generic
56
102
  // rest api function above. They must follow REST API naming:
57
103
  // Method + Resource, representing the end-point.
58
- getNotifications: function(i, e) {
59
- return a.rest.generic(
104
+ getNotifications: function(o, e) {
105
+ return s.rest.generic(
60
106
  "GET",
61
- `notifications/INAPP_WEB?count=${e}&before=${i}`
107
+ `notifications/INAPP_WEB?count=${e}&before=${o}`
62
108
  );
63
109
  },
64
- patchNotifications: function(i) {
65
- return a.rest.generic(
110
+ patchNotifications: function(o) {
111
+ return s.rest.generic(
66
112
  "PATCH",
67
113
  "notifications/INAPP_WEB",
68
- i
114
+ o
69
115
  );
70
116
  },
71
117
  getPreferences: function() {
72
- return a.rest.generic("GET", "preferences");
118
+ return s.rest.generic("GET", "preferences");
73
119
  },
74
- postPreferences: function(i) {
75
- return a.rest.generic(
120
+ postPreferences: function(o) {
121
+ return s.rest.generic(
76
122
  "POST",
77
123
  "preferences",
78
- i
124
+ o
79
125
  );
80
126
  },
81
- postUser: function(i) {
82
- return a.rest.generic("POST", "", i);
127
+ postUser: function(o) {
128
+ return s.rest.generic("POST", "", o);
83
129
  },
84
130
  getUserAccountMetadata: function() {
85
- return a.rest.generic("GET", "account_metadata");
131
+ return s.rest.generic("GET", "account_metadata");
86
132
  }
87
133
  },
88
134
  websocket: {
89
135
  object: void 0,
90
136
  connect: function() {
91
- let i = `wss://${a.config.websocketHost}?userId=${encodeURIComponent(a.config.userId)}&envId=${a.config.clientId}`;
92
- return a.config.hashedUserId && (i += `&userIdHash=${encodeURIComponent(a.config.hashedUserId)}`), a.websocket.object = new WebSocket(i), a.websocket.object.onmessage = (e) => {
93
- const g = JSON.parse(e.data);
94
- if (!(!g || !g.route) && g.route === "inapp_web/new_notifications") {
95
- const s = g;
96
- a.config.onNewInAppNotifications && a.config.onNewInAppNotifications(
97
- s.payload.notifications
137
+ let o = `wss://${s.config.websocketHost}?userId=${encodeURIComponent(s.config.userId)}&envId=${s.config.clientId}`;
138
+ return s.config.hashedUserId && (o += `&userIdHash=${encodeURIComponent(s.config.hashedUserId)}`), s.logger.log("WebSocket connecting to:", o), s.websocket.object = new WebSocket(o), s.websocket.object.onopen = () => {
139
+ s.logger.log("WebSocket connection opened");
140
+ }, s.websocket.object.onclose = (e) => {
141
+ s.logger.log("WebSocket connection closed:", {
142
+ code: e.code,
143
+ reason: e.reason,
144
+ wasClean: e.wasClean
145
+ });
146
+ }, s.websocket.object.onerror = (e) => {
147
+ s.logger.error("WebSocket error:", e);
148
+ }, s.websocket.object.onmessage = (e) => {
149
+ s.logger.log(
150
+ "WebSocket message received:",
151
+ e.data
152
+ );
153
+ const u = JSON.parse(e.data);
154
+ if (!(!u || !u.route) && u.route === "inapp_web/new_notifications") {
155
+ const a = u;
156
+ s.logger.log(
157
+ "New notifications received:",
158
+ a.payload.notifications
159
+ ), s.config.onNewInAppNotifications && s.config.onNewInAppNotifications(
160
+ a.payload.notifications
98
161
  );
99
162
  }
100
- }, a.websocket.object;
163
+ }, s.websocket.object;
101
164
  },
102
- disconnect: function(i) {
165
+ disconnect: function(o) {
103
166
  var e;
104
- a.websocket.object && ((e = a.websocket.object) == null || e.close(), i && i(a.websocket.object));
167
+ s.websocket.object && (s.logger.log("WebSocket disconnecting"), (e = s.websocket.object) == null || e.close(), o && o(s.websocket.object));
105
168
  }
106
169
  },
107
170
  openWebSocket: function() {
108
- return a.websocket.connect(() => {
171
+ return s.websocket.connect(() => {
109
172
  setTimeout(
110
173
  () => {
111
174
  this.websocket.disconnect(() => {
@@ -119,55 +182,83 @@ const ne = async (i, e, g, s, c, p, w) => {
119
182
  // These functions are developer friendly wrappers over the rest APIs
120
183
  // They may or may not do additional tasks.
121
184
  // e.g. identify simply maps to postUsers
122
- getInAppNotifications: async (i) => {
123
- const e = i.maxCountNeeded || a.config.getInAppDefaultCount, g = i.oldestNeeded || a.config.getInAppDefaultOldest;
124
- let s = [], c = i.before, p = !0, w = !0;
125
- for (; w; ) {
126
- const h = (await a.rest.getNotifications(
185
+ getInAppNotifications: async (o) => {
186
+ s.logger.log(
187
+ "getInAppNotifications called with params:",
188
+ o
189
+ );
190
+ const e = o.maxCountNeeded || s.config.getInAppDefaultCount, u = o.oldestNeeded || s.config.getInAppDefaultOldest;
191
+ s.logger.log("Fetching notifications with:", {
192
+ maxCountNeeded: e,
193
+ oldestNeeded: u,
194
+ before: o.before
195
+ });
196
+ let a = [], c = o.before, h = !0, I = !0;
197
+ for (; I; ) {
198
+ const l = (await s.rest.getNotifications(
127
199
  c,
128
200
  e
129
- )).notifications.filter(
130
- (f) => !s.find((I) => I.id === f.id)
201
+ )).notifications, p = l.filter(
202
+ (b) => !a.find((w) => w.id === b.id)
131
203
  );
132
- c = h.reduce(
133
- (f, I) => f < I.date ? f : I.date,
134
- i.before
135
- ), s = [...s, ...h], p = h.length > 0, w = !0, (!p || s.length >= e || c < g) && (w = !1);
204
+ s.logger.log(
205
+ `Received ${l.length} notifications, ${p.length} unique`
206
+ ), c = p.reduce(
207
+ (b, w) => b < w.date ? b : w.date,
208
+ o.before
209
+ ), a = [...a, ...p], h = p.length > 0, I = !0, (!h || a.length >= e || c < u) && (I = !1, s.logger.log("Stopping fetch loop:", {
210
+ hasMore: h,
211
+ totalResults: a.length,
212
+ maxCountNeeded: e,
213
+ oldestReceived: c,
214
+ oldestNeeded: u
215
+ }));
136
216
  }
137
- return {
138
- items: s,
139
- hasMore: p,
217
+ return s.logger.log("getInAppNotifications completed:", {
218
+ totalItems: a.length,
219
+ hasMore: h,
220
+ oldestReceived: c
221
+ }), {
222
+ items: a,
223
+ hasMore: h,
140
224
  oldestReceived: c
141
225
  };
142
226
  },
143
- updateInAppNotifications: async (i) => {
227
+ updateInAppNotifications: async (o) => {
228
+ s.logger.log(
229
+ "updateInAppNotifications called with params:",
230
+ o
231
+ );
144
232
  const e = {
145
- trackingIds: i.ids
233
+ trackingIds: o.ids
146
234
  };
147
- return i.archived === !0 ? e.archived = (/* @__PURE__ */ new Date()).toISOString() : i.archived === !1 && (e.archived = null), i.clicked === !0 ? e.clicked = (/* @__PURE__ */ new Date()).toISOString() : i.clicked === !1 && (e.clicked = null), i.opened === !0 ? e.opened = (/* @__PURE__ */ new Date()).toISOString() : i.opened === !1 && (e.opened = null), a.rest.patchNotifications(e);
235
+ return o.archived === !0 ? e.archived = (/* @__PURE__ */ new Date()).toISOString() : o.archived === !1 && (e.archived = null), o.clicked === !0 ? e.clicked = (/* @__PURE__ */ new Date()).toISOString() : o.clicked === !1 && (e.clicked = null), o.opened === !0 ? e.opened = (/* @__PURE__ */ new Date()).toISOString() : o.opened === !1 && (e.opened = null), s.logger.log(
236
+ "Updating notifications with body:",
237
+ e
238
+ ), s.rest.patchNotifications(e);
148
239
  },
149
- getPreferences: async () => a.rest.getPreferences(),
150
- updateDeliveryOption: async (i) => a.rest.postPreferences([i]),
151
- identify: async (i) => {
152
- if (i.id && i.id !== a.config.userId)
240
+ getPreferences: async () => s.rest.getPreferences(),
241
+ updateDeliveryOption: async (o) => s.rest.postPreferences([o]),
242
+ identify: async (o) => {
243
+ if (o.id && o.id !== s.config.userId)
153
244
  throw new Error(
154
245
  "The id in the parameters does not match the initialized userId."
155
246
  );
156
- return a.rest.postUser(i);
247
+ return s.rest.postUser(o);
157
248
  },
158
- getUserAccountMetadata: async () => a.rest.getUserAccountMetadata()
159
- }, G = typeof window < "u", se = (i) => {
160
- const e = B(
161
- () => ie(i.debug || !1),
162
- [i.debug]
249
+ getUserAccountMetadata: async () => s.rest.getUserAccountMetadata()
250
+ }, G = typeof window < "u", ae = (o) => {
251
+ const e = z(
252
+ () => ne(o.debug || !1),
253
+ [o.debug]
163
254
  );
164
255
  e.log("NotificationAPI Provider initializing", {
165
- clientId: i.clientId,
166
- userId: "userId" in i ? i.userId : i.user.id,
167
- debug: i.debug || !1,
256
+ clientId: o.clientId,
257
+ userId: "userId" in o ? o.userId : o.user.id,
258
+ debug: o.debug || !1,
168
259
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
169
260
  });
170
- const s = {
261
+ const a = {
171
262
  ...{
172
263
  apiURL: "api.notificationapi.com",
173
264
  wsURL: "ws.notificationapi.com",
@@ -178,44 +269,44 @@ const ne = async (i, e, g, s, c, p, w) => {
178
269
  webPushOptInMessage: "AUTOMATIC",
179
270
  customServiceWorkerPath: "/notificationapi-service-worker.js"
180
271
  },
181
- ...i,
182
- user: "userId" in i ? { id: i.userId } : i.user
272
+ ...o,
273
+ user: "userId" in o ? { id: o.userId } : o.user
183
274
  };
184
- e.log("Configuration loaded", s);
185
- const [c, p] = b(), [w, h] = b(), [f, I] = b(), [E, C] = b(!1), [O, F] = b((/* @__PURE__ */ new Date()).toISOString()), [M, x] = b(!0), [P, m] = b(s.webPushOptInMessage), [S, J] = b(!1), q = N(() => {
186
- s.playSoundOnNewNotification && (e.log("Playing notification sound", {
187
- soundPath: s.newNotificationSoundPath
188
- }), new Audio(s.newNotificationSoundPath).play().catch((n) => {
275
+ e.log("Configuration loaded", a);
276
+ const [c, h] = N(), [I, l] = N(), [p, b] = N(), [w, v] = N(!1), [m, P] = N((/* @__PURE__ */ new Date()).toISOString()), [D, x] = N(!0), [k, y] = N(a.webPushOptInMessage), [M, Q] = N(!1), $ = A(() => {
277
+ a.playSoundOnNewNotification && (e.log("Playing notification sound", {
278
+ soundPath: a.newNotificationSoundPath
279
+ }), new Audio(a.newNotificationSoundPath).play().catch((n) => {
189
280
  e.error("Failed to play new notification sound", n), console.log("Failed to play new notification sound:", n);
190
281
  }));
191
282
  }, [
192
- s.newNotificationSoundPath,
193
- s.playSoundOnNewNotification,
283
+ a.newNotificationSoundPath,
284
+ a.playSoundOnNewNotification,
194
285
  e
195
- ]), A = N(
286
+ ]), O = A(
196
287
  (t) => {
197
288
  e.group("Adding notifications to state"), e.log("Received notifications", {
198
289
  count: (t == null ? void 0 : t.length) || 0,
199
290
  notifications: t
200
291
  });
201
292
  const n = (/* @__PURE__ */ new Date()).toISOString();
202
- p((o) => {
203
- const r = (o == null ? void 0 : o.length) || 0;
204
- e.log("Current notifications count", r), t = Array.isArray(t) ? t : [], t = t.filter((u) => {
205
- const v = u.expDate && new Date(u.expDate).toISOString() > n, T = new Date(u.date).getTime() > new Date(n).getTime() + 1e3, z = !v && !T;
206
- return z || e.log("Filtering out notification", {
207
- id: u.id,
208
- reason: v ? "expired" : "future",
209
- expDate: u.expDate,
210
- date: u.date
211
- }), z;
212
- }), o = Array.isArray(o) ? o : [];
293
+ h((i) => {
294
+ const r = (i == null ? void 0 : i.length) || 0;
295
+ e.log("Current notifications count", r), t = Array.isArray(t) ? t : [], t = t.filter((g) => {
296
+ const S = g.expDate && new Date(g.expDate).toISOString() > n, L = new Date(g.date).getTime() > new Date(n).getTime() + 1e3, K = !S && !L;
297
+ return K || e.log("Filtering out notification", {
298
+ id: g.id,
299
+ reason: S ? "expired" : "future",
300
+ expDate: g.expDate,
301
+ date: g.date
302
+ }), K;
303
+ }), i = Array.isArray(i) ? i : [];
213
304
  const d = [
214
- ...t.filter((u) => {
215
- const v = o.find((T) => T.id === u.id);
216
- return v && e.log("Filtering out duplicate notification", { id: u.id }), !v;
305
+ ...t.filter((g) => {
306
+ const S = i.find((L) => L.id === g.id);
307
+ return S && e.log("Filtering out duplicate notification", { id: g.id }), !S;
217
308
  }),
218
- ...o
309
+ ...i
219
310
  ];
220
311
  return e.log("State updated", {
221
312
  previousCount: r,
@@ -225,121 +316,123 @@ const ne = async (i, e, g, s, c, p, w) => {
225
316
  });
226
317
  },
227
318
  [e]
228
- ), l = B(() => {
319
+ ), f = z(() => {
229
320
  e.group("Initializing NotificationAPI client");
230
321
  const t = {
231
- clientId: s.clientId,
232
- userId: s.user.id,
233
- hashedUserId: s.hashedUserId,
234
- host: s.apiURL,
235
- websocketHost: s.wsURL
322
+ clientId: a.clientId,
323
+ userId: a.user.id,
324
+ hashedUserId: a.hashedUserId,
325
+ host: a.apiURL,
326
+ websocketHost: a.wsURL,
327
+ debug: a.debug
236
328
  };
237
329
  e.log("Client configuration", t);
238
- const n = i.client ? i.client : a.init({
330
+ const n = o.client ? o.client : s.init({
239
331
  ...t,
240
332
  onNewInAppNotifications: (r) => {
241
333
  e.log("Received new in-app notifications via WebSocket", {
242
334
  count: (r == null ? void 0 : r.length) || 0,
243
335
  notifications: r
244
- }), q(), A(r);
336
+ }), $(), O(r);
245
337
  }
246
- }), o = {
247
- email: s.user.email,
248
- number: s.user.number
338
+ }), i = {
339
+ email: a.user.email,
340
+ number: a.user.number
249
341
  };
250
- return e.log("Identifying user", o), n.identify(o), e.groupEnd(), n;
342
+ return e.log("Identifying user", i), n.identify(i), e.groupEnd(), n;
251
343
  }, [
252
- s.clientId,
253
- s.user.id,
254
- s.user.email,
255
- s.user.number,
256
- s.hashedUserId,
257
- A,
258
- q,
259
- i.client,
260
- s.apiURL,
261
- s.wsURL,
344
+ a.clientId,
345
+ a.user.id,
346
+ a.user.email,
347
+ a.user.number,
348
+ a.hashedUserId,
349
+ a.debug,
350
+ O,
351
+ $,
352
+ o.client,
353
+ a.apiURL,
354
+ a.wsURL,
262
355
  e
263
- ]), $ = N(
356
+ ]), j = A(
264
357
  async (t, n) => {
265
- var o;
358
+ var i;
266
359
  e.group("Fetching notifications"), e.log(
267
360
  "Fetch parameters",
268
- k("GET", "/notifications", { date: t, count: n })
361
+ C("GET", "/notifications", { date: t, count: n })
269
362
  );
270
363
  try {
271
- const r = await l.rest.getNotifications(t, n);
364
+ const r = await f.rest.getNotifications(t, n);
272
365
  e.log("Fetch successful", {
273
- notificationsCount: ((o = r.notifications) == null ? void 0 : o.length) || 0,
366
+ notificationsCount: ((i = r.notifications) == null ? void 0 : i.length) || 0,
274
367
  oldestReceived: r.oldestReceived,
275
368
  couldLoadMore: r.couldLoadMore
276
- }), F(r.oldestReceived), x(r.couldLoadMore), A(r.notifications), e.groupEnd();
369
+ }), P(r.oldestReceived), x(r.couldLoadMore), O(r.notifications), e.groupEnd();
277
370
  } catch (r) {
278
371
  throw e.error("Failed to fetch notifications", r, { date: t, count: n }), e.groupEnd(), r;
279
372
  }
280
373
  },
281
- [A, l.rest, e]
282
- ), U = R(M), D = R(E), j = R(O);
283
- y(() => {
284
- U.current = M, D.current = E, j.current = O;
285
- }, [M, E, O]);
286
- const L = N(
374
+ [O, f.rest, e]
375
+ ), U = F(D), W = F(w), q = F(m);
376
+ E(() => {
377
+ U.current = D, W.current = w, q.current = m;
378
+ }, [D, w, m]);
379
+ const T = A(
287
380
  async (t) => {
288
381
  if (e.group(`Loading notifications (${t ? "initial" : "more"})`), e.log("Load conditions", {
289
382
  initial: t,
290
383
  hasMore: U.current,
291
- loading: D.current
292
- }), !t && (!U.current || D.current)) {
384
+ loading: W.current
385
+ }), !t && (!U.current || W.current)) {
293
386
  e.log("Skipping load - conditions not met"), e.groupEnd();
294
387
  return;
295
388
  }
296
- C(!0), e.log("Loading started");
389
+ v(!0), e.log("Loading started");
297
390
  try {
298
- await $(
299
- t ? (/* @__PURE__ */ new Date()).toISOString() : j.current,
300
- t ? s.initialLoadMaxCount : 1e3
391
+ await j(
392
+ t ? (/* @__PURE__ */ new Date()).toISOString() : q.current,
393
+ t ? a.initialLoadMaxCount : 1e3
301
394
  ), e.log("Loading completed successfully");
302
395
  } catch (n) {
303
396
  throw e.error("Loading failed", n), n;
304
397
  } finally {
305
- C(!1), e.groupEnd();
398
+ v(!1), e.groupEnd();
306
399
  }
307
400
  },
308
- [s.initialLoadMaxCount, $, e]
309
- ), Q = async (t) => {
401
+ [a.initialLoadMaxCount, j, e]
402
+ ), X = async (t) => {
310
403
  if (e.group("Marking notifications as clicked"), e.log("Requested IDs", t), !c) {
311
404
  e.warn("No notifications available"), e.groupEnd();
312
405
  return;
313
406
  }
314
- const n = (/* @__PURE__ */ new Date()).toISOString(), o = c.filter((r) => t.includes(r.id) && !r.clicked).map((r) => r.id);
407
+ const n = (/* @__PURE__ */ new Date()).toISOString(), i = c.filter((r) => t.includes(r.id) && !r.clicked).map((r) => r.id);
315
408
  if (e.log("Filtered IDs for update", {
316
409
  requestedCount: t.length,
317
- actualCount: o.length,
318
- ids: o
319
- }), o.length === 0) {
410
+ actualCount: i.length,
411
+ ids: i
412
+ }), i.length === 0) {
320
413
  e.log("No notifications to update"), e.groupEnd();
321
414
  return;
322
415
  }
323
416
  try {
324
417
  e.log(
325
418
  "Updating notifications via API",
326
- k("PUT", "/notifications/clicked", { ids: o })
327
- ), l.updateInAppNotifications({ ids: o, clicked: !0 }), p((r) => {
419
+ C("PUT", "/notifications/clicked", { ids: i })
420
+ ), f.updateInAppNotifications({ ids: i, clicked: !0 }), h((r) => {
328
421
  if (!r) return [];
329
422
  const d = [...r];
330
- return d.filter((u) => o.includes(u.id)).forEach((u) => {
331
- u.clicked = n;
332
- }), e.log("Local state updated", { updatedCount: o.length }), d;
423
+ return d.filter((g) => i.includes(g.id)).forEach((g) => {
424
+ g.clicked = n;
425
+ }), e.log("Local state updated", { updatedCount: i.length }), d;
333
426
  }), e.groupEnd();
334
427
  } catch (r) {
335
- throw e.error("Failed to mark notifications as clicked", r, { ids: o }), e.groupEnd(), r;
428
+ throw e.error("Failed to mark notifications as clicked", r, { ids: i }), e.groupEnd(), r;
336
429
  }
337
- }, X = async () => {
430
+ }, Y = async () => {
338
431
  if (e.group("Marking notifications as opened"), !c) {
339
432
  e.warn("No notifications available"), e.groupEnd();
340
433
  return;
341
434
  }
342
- const t = (/* @__PURE__ */ new Date()).toISOString(), n = c.filter((o) => !o.opened || !o.seen).map((o) => o.id);
435
+ const t = (/* @__PURE__ */ new Date()).toISOString(), n = c.filter((i) => !i.opened || !i.seen).map((i) => i.id);
343
436
  if (e.log("Notifications to mark as opened", { count: n.length, ids: n }), n.length === 0) {
344
437
  e.log("All notifications already opened"), e.groupEnd();
345
438
  return;
@@ -347,26 +440,26 @@ const ne = async (i, e, g, s, c, p, w) => {
347
440
  try {
348
441
  e.log(
349
442
  "Updating notifications via API",
350
- k("PUT", "/notifications/opened", { ids: n })
351
- ), l.updateInAppNotifications({
443
+ C("PUT", "/notifications/opened", { ids: n })
444
+ ), f.updateInAppNotifications({
352
445
  ids: n,
353
446
  opened: !0
354
- }), p((o) => {
355
- if (!o) return [];
356
- const r = [...o];
447
+ }), h((i) => {
448
+ if (!i) return [];
449
+ const r = [...i];
357
450
  return r.filter((d) => n.includes(d.id)).forEach((d) => {
358
451
  d.opened = t, d.seen = !0;
359
452
  }), e.log("Local state updated", { updatedCount: n.length }), r;
360
453
  }), e.groupEnd();
361
- } catch (o) {
362
- throw e.error("Failed to mark notifications as opened", o, { ids: n }), e.groupEnd(), o;
454
+ } catch (i) {
455
+ throw e.error("Failed to mark notifications as opened", i, { ids: n }), e.groupEnd(), i;
363
456
  }
364
- }, Y = async (t) => {
457
+ }, Z = async (t) => {
365
458
  if (e.group("Marking notifications as unarchived"), e.log("Requested operation", { ids: t }), !c) {
366
459
  e.warn("No notifications available"), e.groupEnd();
367
460
  return;
368
461
  }
369
- const n = c.filter((o) => o.archived && (t === "ALL" || t.includes(o.id))).map((o) => o.id);
462
+ const n = c.filter((i) => i.archived && (t === "ALL" || t.includes(i.id))).map((i) => i.id);
370
463
  if (e.log("Filtered notifications for unarchiving", {
371
464
  count: n.length,
372
465
  ids: n
@@ -377,72 +470,72 @@ const ne = async (i, e, g, s, c, p, w) => {
377
470
  try {
378
471
  e.log(
379
472
  "Updating notifications via API",
380
- k("PUT", "/notifications/unarchived", { ids: n })
381
- ), l.updateInAppNotifications({
473
+ C("PUT", "/notifications/unarchived", { ids: n })
474
+ ), f.updateInAppNotifications({
382
475
  ids: n,
383
476
  archived: !1
384
- }), p((o) => {
385
- if (!o) return [];
386
- const r = [...o];
477
+ }), h((i) => {
478
+ if (!i) return [];
479
+ const r = [...i];
387
480
  return r.filter((d) => n.includes(d.id)).forEach((d) => {
388
481
  d.archived = void 0;
389
482
  }), e.log("Local state updated", { unarchivedCount: n.length }), r;
390
483
  }), e.groupEnd();
391
- } catch (o) {
392
- throw e.error("Failed to unarchive notifications", o, { ids: n }), e.groupEnd(), o;
484
+ } catch (i) {
485
+ throw e.error("Failed to unarchive notifications", i, { ids: n }), e.groupEnd(), i;
393
486
  }
394
- }, Z = async (t) => {
487
+ }, _ = async (t) => {
395
488
  if (e.group("Marking notifications as archived"), e.log("Requested operation", { ids: t }), !c) {
396
489
  e.warn("No notifications available"), e.groupEnd();
397
490
  return;
398
491
  }
399
- const n = (/* @__PURE__ */ new Date()).toISOString(), o = c.filter((r) => !r.archived && (t === "ALL" || t.includes(r.id))).map((r) => r.id);
492
+ const n = (/* @__PURE__ */ new Date()).toISOString(), i = c.filter((r) => !r.archived && (t === "ALL" || t.includes(r.id))).map((r) => r.id);
400
493
  if (e.log("Filtered notifications for archiving", {
401
- count: o.length,
402
- ids: o
403
- }), o.length === 0) {
494
+ count: i.length,
495
+ ids: i
496
+ }), i.length === 0) {
404
497
  e.log("No unarchived notifications to archive"), e.groupEnd();
405
498
  return;
406
499
  }
407
500
  try {
408
501
  e.log(
409
502
  "Updating notifications via API",
410
- k("PUT", "/notifications/archived", { ids: o })
411
- ), l.updateInAppNotifications({ ids: o, archived: !0 }), p((r) => {
503
+ C("PUT", "/notifications/archived", { ids: i })
504
+ ), f.updateInAppNotifications({ ids: i, archived: !0 }), h((r) => {
412
505
  if (!r) return [];
413
506
  const d = [...r];
414
- return d.filter((u) => o.includes(u.id)).forEach((u) => {
415
- u.archived = n;
416
- }), e.log("Local state updated", { archivedCount: o.length }), d;
507
+ return d.filter((g) => i.includes(g.id)).forEach((g) => {
508
+ g.archived = n;
509
+ }), e.log("Local state updated", { archivedCount: i.length }), d;
417
510
  }), e.groupEnd();
418
511
  } catch (r) {
419
- throw e.error("Failed to archive notifications", r, { ids: o }), e.groupEnd(), r;
512
+ throw e.error("Failed to archive notifications", r, { ids: i }), e.groupEnd(), r;
420
513
  }
421
- }, _ = (t, n, o, r) => (e.log("Updating single delivery preference", {
514
+ }, ee = (t, n, i, r) => (e.log("Updating single delivery preference", {
422
515
  notificationId: t,
423
516
  channel: n,
424
- delivery: o,
517
+ delivery: i,
425
518
  subNotificationId: r
426
519
  }), H([
427
520
  {
428
521
  notificationId: t,
429
522
  channel: n,
430
- delivery: o,
523
+ delivery: i,
431
524
  subNotificationId: r
432
525
  }
433
526
  ])), H = (t) => {
434
527
  e.group("Updating delivery preferences"), e.log("Preference updates", { count: t.length, params: t });
435
528
  try {
436
- l.rest.postPreferences(t).then(() => {
529
+ f.rest.postPreferences(t).then(() => {
437
530
  e.log(
438
531
  "Preferences updated successfully, fetching latest preferences"
439
- ), l.getPreferences().then((n) => {
440
- var o, r, d;
532
+ ), f.getPreferences().then((n) => {
533
+ var i, r, d;
441
534
  e.log("Latest preferences fetched", {
442
- preferencesCount: ((o = n.preferences) == null ? void 0 : o.length) || 0,
535
+ preferencesCount: ((i = n.preferences) == null ? void 0 : i.length) || 0,
443
536
  notificationsCount: ((r = n.notifications) == null ? void 0 : r.length) || 0,
444
537
  subNotificationsCount: ((d = n.subNotifications) == null ? void 0 : d.length) || 0
445
- }), h(n), e.groupEnd();
538
+ }), l(n), e.groupEnd();
446
539
  }).catch((n) => {
447
540
  e.error("Failed to fetch updated preferences", n), e.groupEnd();
448
541
  });
@@ -452,28 +545,28 @@ const ne = async (i, e, g, s, c, p, w) => {
452
545
  } catch (n) {
453
546
  throw e.error("Error in updateDeliveries", n, { params: t }), e.groupEnd(), n;
454
547
  }
455
- }, W = N(() => {
548
+ }, R = A(() => {
456
549
  e.group("Requesting web push permission"), e.log("Service worker support check", {
457
550
  supported: "serviceWorker" in navigator,
458
- customServiceWorkerPath: s.customServiceWorkerPath
459
- }), "serviceWorker" in navigator ? (e.log("Registering service worker"), navigator.serviceWorker.register(s.customServiceWorkerPath).then(async (t) => {
460
- e.log("Service worker registered successfully"), m(!1), ce().then(async (n) => {
551
+ customServiceWorkerPath: a.customServiceWorkerPath
552
+ }), "serviceWorker" in navigator ? (e.log("Registering service worker"), navigator.serviceWorker.register(a.customServiceWorkerPath).then(async (t) => {
553
+ e.log("Service worker registered successfully"), y(!1), de().then(async (n) => {
461
554
  e.log("Notification permission result", { permission: n }), n === "granted" ? (e.log("Permission granted, subscribing to push manager"), await t.pushManager.subscribe({
462
555
  userVisibleOnly: !0,
463
- applicationServerKey: f == null ? void 0 : f.userAccountMetadata.environmentVapidPublicKey
464
- }).then(async (o) => {
556
+ applicationServerKey: p == null ? void 0 : p.userAccountMetadata.environmentVapidPublicKey
557
+ }).then(async (i) => {
465
558
  e.log("Push subscription successful");
466
559
  const r = {
467
560
  webPushTokens: [
468
561
  {
469
562
  sub: {
470
- endpoint: o.toJSON().endpoint,
471
- keys: o.toJSON().keys
563
+ endpoint: i.toJSON().endpoint,
564
+ keys: i.toJSON().keys
472
565
  }
473
566
  }
474
567
  ]
475
568
  };
476
- e.log("Identifying user with web push tokens"), await l.identify(r), localStorage.setItem("hideWebPushOptInMessage", "true"), e.log("Web push setup completed successfully"), e.groupEnd();
569
+ e.log("Identifying user with web push tokens"), await f.identify(r), localStorage.setItem("hideWebPushOptInMessage", "true"), e.log("Web push setup completed successfully"), e.groupEnd();
477
570
  })) : n === "denied" && (e.warn("Permission for notifications was denied"), console.log("Permission for notifications was denied"), e.groupEnd());
478
571
  });
479
572
  }).catch((t) => {
@@ -482,7 +575,7 @@ const ne = async (i, e, g, s, c, p, w) => {
482
575
  t,
483
576
  {
484
577
  errorCode: t.code,
485
- customServiceWorkerPath: s.customServiceWorkerPath
578
+ customServiceWorkerPath: a.customServiceWorkerPath
486
579
  }
487
580
  ), t.code === 18 ? console.error(
488
581
  "NotificationAPI guide: Probably you are not setup the service worker correctly. Please check the documentation at https://docs.notificationapi.com/guides/web-push#step-by-step-implementation Step 3: Service Worker Setup."
@@ -497,92 +590,92 @@ const ne = async (i, e, g, s, c, p, w) => {
497
590
  ) : console.error(t), e.groupEnd();
498
591
  })) : (e.warn("Service worker not supported in this browser"), e.groupEnd());
499
592
  }, [
500
- l,
501
- s.customServiceWorkerPath,
502
- f == null ? void 0 : f.userAccountMetadata.environmentVapidPublicKey,
593
+ f,
594
+ a.customServiceWorkerPath,
595
+ p == null ? void 0 : p.userAccountMetadata.environmentVapidPublicKey,
503
596
  e
504
597
  ]);
505
- y(() => {
506
- e.group("Provider initialization effect"), e.log("Resetting state and loading initial data"), p([]), C(!1), h(void 0), F((/* @__PURE__ */ new Date()).toISOString()), x(!0), L(!0), e.log("Opening WebSocket connection"), l.openWebSocket(), e.log("Fetching user preferences"), l.getPreferences().then((t) => {
507
- var n, o, r;
598
+ E(() => {
599
+ e.group("Provider initialization effect"), e.log("Resetting state and loading initial data"), h([]), v(!1), l(void 0), P((/* @__PURE__ */ new Date()).toISOString()), x(!0), T(!0), e.log("Opening WebSocket connection"), f.openWebSocket(), e.log("Fetching user preferences"), f.getPreferences().then((t) => {
600
+ var n, i, r;
508
601
  e.log("Initial preferences loaded", {
509
602
  preferencesCount: ((n = t.preferences) == null ? void 0 : n.length) || 0,
510
- notificationsCount: ((o = t.notifications) == null ? void 0 : o.length) || 0,
603
+ notificationsCount: ((i = t.notifications) == null ? void 0 : i.length) || 0,
511
604
  subNotificationsCount: ((r = t.subNotifications) == null ? void 0 : r.length) || 0
512
- }), h(t), e.groupEnd();
605
+ }), l(t), e.groupEnd();
513
606
  }).catch((t) => {
514
607
  e.error("Failed to fetch initial preferences", t), e.groupEnd();
515
608
  });
516
- }, [l, L, W, e]), y(() => {
517
- e.group("Fetching user account metadata"), l.getUserAccountMetadata().then((t) => {
609
+ }, [f, T, R, e]), E(() => {
610
+ e.group("Fetching user account metadata"), f.getUserAccountMetadata().then((t) => {
518
611
  e.log("User account metadata loaded", {
519
612
  hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled,
520
613
  environmentVapidPublicKey: t.userAccountMetadata.environmentVapidPublicKey ? "present" : "missing"
521
- }), I(t), G && "Notification" in window && typeof Notification.requestPermission == "function" ? (e.log("Browser notification support detected", {
614
+ }), b(t), G && "Notification" in window && typeof Notification.requestPermission == "function" ? (e.log("Browser notification support detected", {
522
615
  permission: Notification.permission
523
616
  }), Notification.permission !== "default" && (e.log(
524
617
  "Setting webPushOptInMessage to false (permission already set)"
525
- ), m(!1))) : (e.log(
618
+ ), y(!1))) : (e.log(
526
619
  "Browser notification not supported, using server setting",
527
620
  {
528
621
  hasWebPushEnabled: t.userAccountMetadata.hasWebPushEnabled
529
622
  }
530
- ), m(t.userAccountMetadata.hasWebPushEnabled)), e.groupEnd();
623
+ ), y(t.userAccountMetadata.hasWebPushEnabled)), e.groupEnd();
531
624
  }).catch((t) => {
532
625
  e.error("Failed to fetch user account metadata", t), e.groupEnd();
533
626
  });
534
- }, [l, e]), y(() => {
535
- if (e.group("Handling webPushOptInMessage state"), e.log("webPushOptInMessage value", P), P === "AUTOMATIC") {
627
+ }, [f, e]), E(() => {
628
+ if (e.group("Handling webPushOptInMessage state"), e.log("webPushOptInMessage value", k), k === "AUTOMATIC") {
536
629
  const t = localStorage.getItem("hideWebPushOptInMessage") === "true";
537
630
  e.log("Automatic mode - checking localStorage", {
538
631
  hideMessage: t,
539
632
  shouldShow: !t
540
- }), m(!t);
633
+ }), y(!t);
541
634
  }
542
635
  e.groupEnd();
543
- }, [P, e]), y(() => {
544
- e.group("Handling webPushOptIn state"), e.log("webPushOptIn state", S), S && (e.log("User opted in for web push, requesting permission"), W()), e.groupEnd();
545
- }, [S, W, e]);
546
- const ee = {
636
+ }, [k, e]), E(() => {
637
+ e.group("Handling webPushOptIn state"), e.log("webPushOptIn state", M), M && (e.log("User opted in for web push, requesting permission"), R()), e.groupEnd();
638
+ }, [M, R, e]);
639
+ const te = {
547
640
  notifications: c,
548
- preferences: w,
549
- userAccountMetaData: f,
550
- webPushOptInMessage: P,
551
- loadNotifications: L,
552
- markAsOpened: X,
553
- markAsArchived: Z,
554
- markAsUnarchived: Y,
555
- markAsClicked: Q,
556
- updateDelivery: _,
641
+ preferences: I,
642
+ userAccountMetaData: p,
643
+ webPushOptInMessage: k,
644
+ loadNotifications: T,
645
+ markAsOpened: Y,
646
+ markAsArchived: _,
647
+ markAsUnarchived: Z,
648
+ markAsClicked: X,
649
+ updateDelivery: ee,
557
650
  updateDeliveries: H,
558
- getClient: () => l,
559
- setWebPushOptInMessage: m,
560
- setWebPushOptIn: J
651
+ getClient: () => f,
652
+ setWebPushOptInMessage: y,
653
+ setWebPushOptIn: Q
561
654
  };
562
655
  return e.log("NotificationAPI Provider rendering", {
563
656
  notificationsCount: (c == null ? void 0 : c.length) || 0,
564
- hasPreferences: !!w,
565
- hasUserAccountMetaData: !!f,
566
- webPushOptInMessage: P,
567
- webPushOptIn: S
568
- }), /* @__PURE__ */ te(V.Provider, { value: ee, children: i.children });
569
- }, ae = () => {
570
- const i = oe(V);
571
- if (!i)
657
+ hasPreferences: !!I,
658
+ hasUserAccountMetaData: !!p,
659
+ webPushOptInMessage: k,
660
+ webPushOptIn: M
661
+ }), /* @__PURE__ */ oe(V.Provider, { value: te, children: o.children });
662
+ }, ce = () => {
663
+ const o = ie(V);
664
+ if (!o)
572
665
  throw new Error("useMyContext must be used within a MyProvider");
573
- return i;
666
+ return o;
574
667
  };
575
- se.useNotificationAPIContext = ae;
576
- const ce = async () => {
668
+ ae.useNotificationAPIContext = ce;
669
+ const de = async () => {
577
670
  if (G && "Notification" in window && typeof Notification.requestPermission == "function")
578
671
  try {
579
672
  return await Notification.requestPermission();
580
- } catch (i) {
581
- return console.error("Error requesting notification permission:", i), "default";
673
+ } catch (o) {
674
+ return console.error("Error requesting notification permission:", o), "default";
582
675
  }
583
676
  else
584
677
  return console.warn("Web Push Notifications are not supported in this browser."), "default";
585
678
  };
586
679
  export {
587
- se as NotificationAPIProvider
680
+ ae as NotificationAPIProvider
588
681
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@notificationapi/react",
3
3
  "private": false,
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "type": "module",
6
6
  "overrides": {
7
7
  "esbuild": "^0.25.0",
@@ -51,7 +51,7 @@
51
51
  "@playwright/test": "^1.48.0",
52
52
  "prettier": "^3.3.3",
53
53
  "typescript": "^5.2.2",
54
- "vite": "^5.4.18",
54
+ "vite": "^5.4.19",
55
55
  "vite-plugin-dts": "^3.9.1",
56
56
  "vite-plugin-lib-inject-css": "^2.1.1"
57
57
  },
@@ -67,7 +67,7 @@
67
67
  "@fontsource/roboto": "^5.1.1",
68
68
  "@mui/icons-material": "^6.3.1",
69
69
  "@mui/material": "^6.3.1",
70
- "@notificationapi/core": "^0.0.16",
70
+ "@notificationapi/core": "^0.0.17",
71
71
  "javascript-time-ago": "^2.5.10",
72
72
  "liquidjs": "^10.14.0",
73
73
  "rc-virtual-list": "^3.11.5",