@voltro/plugin-notifications 0.54.0 → 0.56.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.
package/dist/rpc.d.ts CHANGED
@@ -9,6 +9,18 @@ export declare const archiveDescriptor: MutationProcedureDescriptor<"notificatio
9
9
  ok: typeof Schema.Boolean;
10
10
  }>, typeof Schema.Never>;
11
11
 
12
+ /**
13
+ * The plugin's canonical package name — the key an app's `alias` is recorded
14
+ * under, and what `./web`'s hooks resolve their tags through.
15
+ *
16
+ * It lives in this BROWSER-SAFE module rather than in `index.ts` because both
17
+ * halves need it and only one of them may reach the server graph: `index.ts`
18
+ * passes it to `pluginInstanceName` / `baseName`, and `web.ts` passes it to
19
+ * `pluginTag`. A second copy in `web.ts` would be a second definition of the
20
+ * plugin's identity with nothing comparing them.
21
+ */
22
+ export declare const BASE_NAME = "@voltro/plugin-notifications";
23
+
12
24
  export declare const clearQuietHoursDescriptor: MutationProcedureDescriptor<"notifications.clearQuietHours", Schema.Struct<{}>, Schema.Struct<{
13
25
  ok: typeof Schema.Boolean;
14
26
  }>, typeof Schema.Never>;
package/dist/rpc.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Schema as e } from "effect";
2
2
  import { defineMutation as t, defineQuery as n } from "@voltro/protocol";
3
3
  //#region src/rpc.ts
4
- var r = n({
4
+ var r = "@voltro/plugin-notifications", i = n({
5
5
  name: "notifications.inbox",
6
6
  input: e.Struct({
7
7
  unreadOnly: e.optional(e.Boolean),
@@ -12,37 +12,37 @@ var r = n({
12
12
  value: e.Unknown
13
13
  })),
14
14
  openAccess: "self-scoped read: returns only the calling subject's own inbox items"
15
- }), i = n({
15
+ }), a = n({
16
16
  name: "notifications.unreadCount",
17
17
  input: e.Struct({}),
18
18
  output: e.Struct({ count: e.Number }),
19
19
  openAccess: "self-scoped read: counts only the calling subject's own unread items"
20
- }), a = t({
20
+ }), o = t({
21
21
  name: "notifications.markRead",
22
22
  input: e.Struct({ id: e.String }),
23
23
  output: e.Struct({ ok: e.Boolean }),
24
24
  openAccess: "self-scoped write: marks an item read only within the calling subject's own inbox"
25
- }), o = t({
25
+ }), s = t({
26
26
  name: "notifications.markUnread",
27
27
  input: e.Struct({ id: e.String }),
28
28
  output: e.Struct({ ok: e.Boolean }),
29
29
  openAccess: "self-scoped write: marks an item unread only within the calling subject's own inbox"
30
- }), s = t({
30
+ }), c = t({
31
31
  name: "notifications.markAllRead",
32
32
  input: e.Struct({}),
33
33
  output: e.Struct({ count: e.Number }),
34
34
  openAccess: "self-scoped write: clears unread state only in the calling subject's own inbox"
35
- }), c = t({
35
+ }), l = t({
36
36
  name: "notifications.archive",
37
37
  input: e.Struct({ id: e.String }),
38
38
  output: e.Struct({ ok: e.Boolean }),
39
39
  openAccess: "self-scoped write: archives an item only within the calling subject's own inbox"
40
- }), l = t({
40
+ }), u = t({
41
41
  name: "notifications.unarchive",
42
42
  input: e.Struct({ id: e.String }),
43
43
  output: e.Struct({ ok: e.Boolean }),
44
44
  openAccess: "self-scoped write: unarchives an item only within the calling subject's own inbox"
45
- }), u = n({
45
+ }), d = n({
46
46
  name: "notifications.preferences",
47
47
  input: e.Struct({}),
48
48
  output: e.Array(e.Record({
@@ -50,7 +50,7 @@ var r = n({
50
50
  value: e.Unknown
51
51
  })),
52
52
  openAccess: "self-scoped read: returns only the calling subject's own channel preferences"
53
- }), d = t({
53
+ }), f = t({
54
54
  name: "notifications.setPreference",
55
55
  input: e.Struct({
56
56
  category: e.String,
@@ -59,17 +59,17 @@ var r = n({
59
59
  }),
60
60
  output: e.Struct({ ok: e.Boolean }),
61
61
  openAccess: "self-scoped write: toggles a channel only on the calling subject's own preferences"
62
- }), f = t({
62
+ }), p = t({
63
63
  name: "notifications.subscribe",
64
64
  input: e.Struct({ topic: e.String }),
65
65
  output: e.Struct({ ok: e.Boolean }),
66
66
  openAccess: "self-service: subscribes the calling subject itself to a topic (the subject is never caller-supplied)"
67
- }), p = t({
67
+ }), m = t({
68
68
  name: "notifications.unsubscribe",
69
69
  input: e.Struct({ topic: e.String }),
70
70
  output: e.Struct({ ok: e.Boolean }),
71
71
  openAccess: "self-service: unsubscribes the calling subject itself from a topic"
72
- }), m = t({
72
+ }), h = t({
73
73
  name: "notifications.setQuietHours",
74
74
  input: e.Struct({
75
75
  startMinute: e.Number,
@@ -79,17 +79,17 @@ var r = n({
79
79
  }),
80
80
  output: e.Struct({ ok: e.Boolean }),
81
81
  openAccess: "self-scoped write: sets only the calling subject's own quiet-hours window"
82
- }), h = t({
82
+ }), g = t({
83
83
  name: "notifications.clearQuietHours",
84
84
  input: e.Struct({}),
85
85
  output: e.Struct({ ok: e.Boolean }),
86
86
  openAccess: "self-scoped write: clears only the calling subject's own quiet-hours window"
87
- }), g = n({
87
+ }), _ = n({
88
88
  name: "notifications.webPushPublicKey",
89
89
  input: e.Struct({}),
90
90
  output: e.Struct({ key: e.String }),
91
91
  openAccess: "public application-server key — the value every subscribing browser is handed by design"
92
- }), _ = t({
92
+ }), v = t({
93
93
  name: "notifications.webPushSubscribe",
94
94
  input: e.Struct({
95
95
  endpoint: e.String,
@@ -99,17 +99,17 @@ var r = n({
99
99
  }),
100
100
  output: e.Struct({ ok: e.Boolean }),
101
101
  openAccess: "self-scoped write: registers the calling subject's own browser subscription (the subject is never caller-supplied)"
102
- }), v = t({
102
+ }), y = t({
103
103
  name: "notifications.webPushUnsubscribe",
104
104
  input: e.Struct({ endpoint: e.String }),
105
105
  output: e.Struct({ ok: e.Boolean }),
106
106
  openAccess: "self-scoped write: removes only a subscription the calling subject owns"
107
- }), y = n({
107
+ }), b = n({
108
108
  name: "notifications.webPushStatus",
109
109
  input: e.Struct({}),
110
110
  output: e.Struct({ endpoints: e.Number }),
111
111
  openAccess: "self-scoped read: counts only the calling subject's own subscriptions"
112
- }), b = [
112
+ }), x = [
113
113
  {
114
114
  tag: "notifications.webPushPublicKey",
115
115
  kind: "query",
@@ -142,7 +142,7 @@ var r = n({
142
142
  name: "webPushStatusDescriptor"
143
143
  }
144
144
  }
145
- ], x = [
145
+ ], S = [
146
146
  {
147
147
  tag: "notifications.inbox",
148
148
  kind: "query",
@@ -249,4 +249,4 @@ var r = n({
249
249
  }
250
250
  ];
251
251
  //#endregion
252
- export { c as archiveDescriptor, h as clearQuietHoursDescriptor, r as inboxDescriptor, s as markAllReadDescriptor, a as markReadDescriptor, o as markUnreadDescriptor, x as notificationsRpcClientImports, u as preferencesDescriptor, d as setPreferenceDescriptor, m as setQuietHoursDescriptor, f as subscribeDescriptor, l as unarchiveDescriptor, i as unreadCountDescriptor, p as unsubscribeDescriptor, g as webPushPublicKeyDescriptor, b as webPushRpcClientImports, y as webPushStatusDescriptor, _ as webPushSubscribeDescriptor, v as webPushUnsubscribeDescriptor };
252
+ export { r as BASE_NAME, l as archiveDescriptor, g as clearQuietHoursDescriptor, i as inboxDescriptor, c as markAllReadDescriptor, o as markReadDescriptor, s as markUnreadDescriptor, S as notificationsRpcClientImports, d as preferencesDescriptor, f as setPreferenceDescriptor, h as setQuietHoursDescriptor, p as subscribeDescriptor, u as unarchiveDescriptor, a as unreadCountDescriptor, m as unsubscribeDescriptor, _ as webPushPublicKeyDescriptor, x as webPushRpcClientImports, b as webPushStatusDescriptor, v as webPushSubscribeDescriptor, y as webPushUnsubscribeDescriptor };
package/dist/web.js CHANGED
@@ -1,88 +1,90 @@
1
- import { useEffect as e, useState as t } from "react";
2
- import { useMutation as n, useSubscription as r } from "@voltro/client";
1
+ import { BASE_NAME as e } from "./rpc.js";
2
+ import { pluginTag as t } from "@voltro/protocol";
3
+ import { useEffect as n, useState as r } from "react";
4
+ import { useMutation as i, useSubscription as a } from "@voltro/client";
3
5
  //#region src/web.ts
4
- var i = (e = {}, t = "app") => {
5
- let { data: n } = r(t, "notifications.inbox", e);
6
+ var o = (n) => t(e, n), s = (e = {}, t = "app") => {
7
+ let { data: n } = a(t, o("inbox"), e);
6
8
  return n ?? [];
7
- }, a = (e = "app") => {
8
- let { data: t } = r(e, "notifications.unreadCount", {});
9
+ }, c = (e = "app") => {
10
+ let { data: t } = a(e, o("unreadCount"), {});
9
11
  return t?.count ?? 0;
10
- }, o = (e = "app") => {
11
- let t = n(e, "notifications.markRead");
12
+ }, l = (e = "app") => {
13
+ let t = i(e, o("markRead"));
12
14
  return (e) => t.mutate({ id: e });
13
- }, s = (e = "app") => {
14
- let t = n(e, "notifications.setPreference");
15
+ }, u = (e = "app") => {
16
+ let t = i(e, o("setPreference"));
15
17
  return (e, n, r) => t.mutate({
16
18
  category: e,
17
19
  channel: n,
18
20
  enabled: r
19
21
  });
20
- }, c = (e = "app") => {
21
- let t = n(e, "notifications.subscribe"), r = n(e, "notifications.unsubscribe");
22
+ }, d = (e = "app") => {
23
+ let t = i(e, o("subscribe")), n = i(e, o("unsubscribe"));
22
24
  return {
23
25
  subscribe: (e) => t.mutate({ topic: e }),
24
- unsubscribe: (e) => r.mutate({ topic: e })
26
+ unsubscribe: (e) => n.mutate({ topic: e })
25
27
  };
26
- }, l = (e) => {
28
+ }, f = (e) => {
27
29
  let t = e.replace(/-/g, "+").replace(/_/g, "/"), n = atob(t), r = new Uint8Array(n.length);
28
30
  for (let e = 0; e < n.length; e++) r[e] = n.charCodeAt(e);
29
31
  return r;
30
- }, u = (i = {}) => {
31
- let a = i.apiName ?? "app", o = i.swUrl ?? "/sw.js", { data: s } = r(a, "notifications.webPushPublicKey", {}), c = n(a, "notifications.webPushSubscribe"), u = n(a, "notifications.webPushUnsubscribe"), d = typeof navigator < "u" && "serviceWorker" in navigator && typeof window < "u" && "PushManager" in window, [f, p] = t(d ? "idle" : "unsupported"), [m, h] = t(void 0);
32
- e(() => {
32
+ }, p = (e = {}) => {
33
+ let t = e.apiName ?? "app", s = e.swUrl ?? "/sw.js", { data: c } = a(t, o("webPushPublicKey"), {}), l = i(t, o("webPushSubscribe")), u = i(t, o("webPushUnsubscribe")), d = typeof navigator < "u" && "serviceWorker" in navigator && typeof window < "u" && "PushManager" in window, [p, m] = r(d ? "idle" : "unsupported"), [h, g] = r(void 0);
34
+ n(() => {
33
35
  if (!d) return;
34
36
  let e = !1;
35
- return navigator.serviceWorker.getRegistration(o).then(async (t) => {
37
+ return navigator.serviceWorker.getRegistration(s).then(async (t) => {
36
38
  let n = await t?.pushManager.getSubscription();
37
- !e && n && p("subscribed");
39
+ !e && n && m("subscribed");
38
40
  }).catch(() => {}), () => {
39
41
  e = !0;
40
42
  };
41
- }, [d, o]);
42
- let g = async () => {
43
+ }, [d, s]);
44
+ let _ = async () => {
43
45
  if (d) {
44
- p("working"), h(void 0);
46
+ m("working"), g(void 0);
45
47
  try {
46
48
  if (await Notification.requestPermission() !== "granted") {
47
- p("denied");
49
+ m("denied");
48
50
  return;
49
51
  }
50
- if (s?.key === void 0) throw Error("application server key not loaded yet — retry in a moment");
51
- let e = await navigator.serviceWorker.register(o);
52
+ if (c?.key === void 0) throw Error("application server key not loaded yet — retry in a moment");
53
+ let e = await navigator.serviceWorker.register(s);
52
54
  await navigator.serviceWorker.ready;
53
55
  let t = await e.pushManager.subscribe({
54
56
  userVisibleOnly: !0,
55
- applicationServerKey: l(s.key)
57
+ applicationServerKey: f(c.key)
56
58
  }), n = t.toJSON();
57
- await c.mutate({
59
+ await l.mutate({
58
60
  endpoint: t.endpoint,
59
61
  p256dh: n.keys?.p256dh ?? "",
60
62
  auth: n.keys?.auth ?? "",
61
63
  ua: navigator.userAgent
62
- }), p("subscribed");
64
+ }), m("subscribed");
63
65
  } catch (e) {
64
- h(e instanceof Error ? e.message : String(e)), p("error");
66
+ g(e instanceof Error ? e.message : String(e)), m("error");
65
67
  }
66
68
  }
67
- }, _ = async () => {
69
+ }, v = async () => {
68
70
  if (d) {
69
- p("working"), h(void 0);
71
+ m("working"), g(void 0);
70
72
  try {
71
- let e = await (await navigator.serviceWorker.getRegistration(o))?.pushManager.getSubscription();
72
- e && (await u.mutate({ endpoint: e.endpoint }), await e.unsubscribe()), p("idle");
73
+ let e = await (await navigator.serviceWorker.getRegistration(s))?.pushManager.getSubscription();
74
+ e && (await u.mutate({ endpoint: e.endpoint }), await e.unsubscribe()), m("idle");
73
75
  } catch (e) {
74
- h(e instanceof Error ? e.message : String(e)), p("error");
76
+ g(e instanceof Error ? e.message : String(e)), m("error");
75
77
  }
76
78
  }
77
79
  };
78
80
  return {
79
- status: f,
80
- ...m === void 0 ? {} : { error: m },
81
- subscribe: g,
82
- unsubscribe: _
81
+ status: p,
82
+ ...h === void 0 ? {} : { error: h },
83
+ subscribe: _,
84
+ unsubscribe: v
83
85
  };
84
- }, d = (e = "app") => {
85
- let t = n(e, "notifications.setQuietHours"), r = n(e, "notifications.clearQuietHours");
86
+ }, m = (e = "app") => {
87
+ let t = i(e, o("setQuietHours")), n = i(e, o("clearQuietHours"));
86
88
  return {
87
89
  set: (e, n, r) => t.mutate({
88
90
  startMinute: e,
@@ -90,8 +92,8 @@ var i = (e = {}, t = "app") => {
90
92
  ...r?.tz ? { tz: r.tz } : {},
91
93
  ...r?.policy ? { policy: r.policy } : {}
92
94
  }),
93
- clear: () => r.mutate({})
95
+ clear: () => n.mutate({})
94
96
  };
95
97
  };
96
98
  //#endregion
97
- export { i as useInbox, o as useMarkRead, d as useQuietHours, s as useSetNotificationPreference, c as useTopicSubscription, a as useUnreadCount, u as useWebPush };
99
+ export { s as useInbox, l as useMarkRead, m as useQuietHours, u as useSetNotificationPreference, d as useTopicSubscription, c as useUnreadCount, p as useWebPush };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-notifications",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "One unified notification surface — email, Slack/webhook, SMS, push, in-app — with per-subject preference routing, an in-app inbox, and a delivery log. NotificationService + typed routes + useInbox/useUnreadCount hooks.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -44,9 +44,9 @@
44
44
  "node": ">=24.0.0"
45
45
  },
46
46
  "dependencies": {
47
- "@voltro/client": "0.54.0",
48
- "@voltro/database": "0.54.0",
49
- "@voltro/protocol": "0.54.0"
47
+ "@voltro/client": "0.56.0",
48
+ "@voltro/database": "0.56.0",
49
+ "@voltro/protocol": "0.56.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "effect": "^3.22.0",