@voltro/plugin-notifications 0.53.0 → 0.55.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/CHANGELOG.md +335 -0
- package/dist/index.d.ts +21 -8
- package/dist/index.js +169 -169
- package/dist/rpc.d.ts +12 -0
- package/dist/rpc.js +20 -20
- package/dist/web.js +44 -42
- package/package.json +4 -4
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
}),
|
|
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
|
-
],
|
|
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 {
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
|
5
|
-
let { data: n } =
|
|
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
|
-
},
|
|
8
|
-
let { data: t } =
|
|
9
|
+
}, c = (e = "app") => {
|
|
10
|
+
let { data: t } = a(e, o("unreadCount"), {});
|
|
9
11
|
return t?.count ?? 0;
|
|
10
|
-
},
|
|
11
|
-
let t =
|
|
12
|
+
}, l = (e = "app") => {
|
|
13
|
+
let t = i(e, o("markRead"));
|
|
12
14
|
return (e) => t.mutate({ id: e });
|
|
13
|
-
},
|
|
14
|
-
let t =
|
|
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
|
-
},
|
|
21
|
-
let t =
|
|
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) =>
|
|
26
|
+
unsubscribe: (e) => n.mutate({ topic: e })
|
|
25
27
|
};
|
|
26
|
-
},
|
|
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
|
-
},
|
|
31
|
-
let
|
|
32
|
-
|
|
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(
|
|
37
|
+
return navigator.serviceWorker.getRegistration(s).then(async (t) => {
|
|
36
38
|
let n = await t?.pushManager.getSubscription();
|
|
37
|
-
!e && n &&
|
|
39
|
+
!e && n && m("subscribed");
|
|
38
40
|
}).catch(() => {}), () => {
|
|
39
41
|
e = !0;
|
|
40
42
|
};
|
|
41
|
-
}, [d,
|
|
42
|
-
let
|
|
43
|
+
}, [d, s]);
|
|
44
|
+
let _ = async () => {
|
|
43
45
|
if (d) {
|
|
44
|
-
|
|
46
|
+
m("working"), g(void 0);
|
|
45
47
|
try {
|
|
46
48
|
if (await Notification.requestPermission() !== "granted") {
|
|
47
|
-
|
|
49
|
+
m("denied");
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
|
-
if (
|
|
51
|
-
let e = await navigator.serviceWorker.register(
|
|
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:
|
|
57
|
+
applicationServerKey: f(c.key)
|
|
56
58
|
}), n = t.toJSON();
|
|
57
|
-
await
|
|
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
|
-
}),
|
|
64
|
+
}), m("subscribed");
|
|
63
65
|
} catch (e) {
|
|
64
|
-
|
|
66
|
+
g(e instanceof Error ? e.message : String(e)), m("error");
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
|
-
},
|
|
69
|
+
}, v = async () => {
|
|
68
70
|
if (d) {
|
|
69
|
-
|
|
71
|
+
m("working"), g(void 0);
|
|
70
72
|
try {
|
|
71
|
-
let e = await (await navigator.serviceWorker.getRegistration(
|
|
72
|
-
e && (await u.mutate({ endpoint: e.endpoint }), await e.unsubscribe()),
|
|
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
|
-
|
|
76
|
+
g(e instanceof Error ? e.message : String(e)), m("error");
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
};
|
|
78
80
|
return {
|
|
79
|
-
status:
|
|
80
|
-
...
|
|
81
|
-
subscribe:
|
|
82
|
-
unsubscribe:
|
|
81
|
+
status: p,
|
|
82
|
+
...h === void 0 ? {} : { error: h },
|
|
83
|
+
subscribe: _,
|
|
84
|
+
unsubscribe: v
|
|
83
85
|
};
|
|
84
|
-
},
|
|
85
|
-
let t =
|
|
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: () =>
|
|
95
|
+
clear: () => n.mutate({})
|
|
94
96
|
};
|
|
95
97
|
};
|
|
96
98
|
//#endregion
|
|
97
|
-
export {
|
|
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.
|
|
3
|
+
"version": "0.55.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.
|
|
48
|
-
"@voltro/database": "0.
|
|
49
|
-
"@voltro/protocol": "0.
|
|
47
|
+
"@voltro/client": "0.55.0",
|
|
48
|
+
"@voltro/database": "0.55.0",
|
|
49
|
+
"@voltro/protocol": "0.55.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"effect": "^3.22.0",
|