convex-notifications 1.2.0 → 1.3.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/README.md +26 -24
- package/dist/client/adapters.d.ts +54 -0
- package/dist/client/adapters.d.ts.map +1 -0
- package/dist/client/adapters.js +102 -0
- package/dist/client/adapters.js.map +1 -0
- package/dist/client/index.d.ts +137 -14
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +313 -16
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +107 -10
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/component.d.ts +22 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/delivery.d.ts +4 -4
- package/dist/component/inbox.d.ts +1 -1
- package/dist/component/notifications.d.ts +1 -1
- package/dist/component/pushTokens.d.ts +21 -0
- package/dist/component/pushTokens.d.ts.map +1 -0
- package/dist/component/pushTokens.js +70 -0
- package/dist/component/pushTokens.js.map +1 -0
- package/dist/component/schema.d.ts +20 -6
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +8 -0
- package/dist/component/schema.js.map +1 -1
- package/package.json +22 -2
- package/src/client/adapters.ts +155 -0
- package/src/client/index.test.ts +178 -66
- package/src/client/index.ts +469 -39
- package/src/client/types.ts +124 -4
- package/src/component/_generated/component.ts +35 -0
- package/src/component/pushTokens.ts +78 -0
- package/src/component/schema.ts +9 -0
package/README.md
CHANGED
|
@@ -10,7 +10,8 @@ A full-stack notifications engine for Convex apps. Real-time inbox, multi-channe
|
|
|
10
10
|
|
|
11
11
|
- Real-time inbox with `list`, `unreadCount`, `markRead`, `markAllRead`, `archive`
|
|
12
12
|
- Multi-channel delivery: push (Expo), email (Resend), SMS (Twilio)
|
|
13
|
-
- `
|
|
13
|
+
- `NotificationDefinition<T>` types — define an event in one file (~20 lines)
|
|
14
|
+
- `api()` method for plug-and-play query/mutation exports (no boilerplate!)
|
|
14
15
|
- 3-level user preferences: global > category > event
|
|
15
16
|
- Transactional notifications that bypass preferences
|
|
16
17
|
- Idempotency via deduplication keys
|
|
@@ -49,19 +50,10 @@ export default app;
|
|
|
49
50
|
|
|
50
51
|
```ts
|
|
51
52
|
// convex/notifications.ts
|
|
52
|
-
import {
|
|
53
|
+
import { Notifications } from "convex-notifications";
|
|
53
54
|
import { components } from "./_generated/api";
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
list,
|
|
57
|
-
unreadCount,
|
|
58
|
-
markRead,
|
|
59
|
-
markAllRead,
|
|
60
|
-
archive,
|
|
61
|
-
registerPushToken,
|
|
62
|
-
updatePreferences,
|
|
63
|
-
getPreferences,
|
|
64
|
-
} = createNotificationsApi(components.notifications, {
|
|
56
|
+
const notifications = new Notifications(components.notifications, {
|
|
65
57
|
auth: async (ctx) => {
|
|
66
58
|
const userId = await getAuthUserId(ctx);
|
|
67
59
|
if (!userId) throw new Error("Not authenticated");
|
|
@@ -82,6 +74,17 @@ export const {
|
|
|
82
74
|
},
|
|
83
75
|
},
|
|
84
76
|
});
|
|
77
|
+
|
|
78
|
+
// Use api() for plug-and-play exports (no boilerplate!)
|
|
79
|
+
export const {
|
|
80
|
+
list,
|
|
81
|
+
unreadCount,
|
|
82
|
+
markRead,
|
|
83
|
+
markAllRead,
|
|
84
|
+
archive,
|
|
85
|
+
getPreferences,
|
|
86
|
+
updatePreference,
|
|
87
|
+
} = notifications.api();
|
|
85
88
|
```
|
|
86
89
|
|
|
87
90
|
### 3. Deploy
|
|
@@ -211,16 +214,16 @@ Users can control which channels are enabled at three levels: global, category,
|
|
|
211
214
|
const prefs = useQuery(api.notifications.getPreferences);
|
|
212
215
|
|
|
213
216
|
// Update preferences
|
|
214
|
-
const update = useMutation(api.notifications.
|
|
217
|
+
const update = useMutation(api.notifications.updatePreference);
|
|
215
218
|
|
|
216
219
|
// Disable email globally
|
|
217
220
|
await update({ level: "global", channel: "email", enabled: false });
|
|
218
221
|
|
|
219
222
|
// Enable email for a specific category
|
|
220
|
-
await update({ level: "category",
|
|
223
|
+
await update({ level: "category", key: "social", channel: "email", enabled: true });
|
|
221
224
|
|
|
222
225
|
// Disable push for a specific event
|
|
223
|
-
await update({ level: "event",
|
|
226
|
+
await update({ level: "event", key: "comment.reply", channel: "push", enabled: false });
|
|
224
227
|
```
|
|
225
228
|
|
|
226
229
|
## Push Token Registration
|
|
@@ -297,22 +300,21 @@ email: {
|
|
|
297
300
|
| `markRead` | mutation | required | Mark a notification as read |
|
|
298
301
|
| `markAllRead` | mutation | required | Mark all notifications as read (timestamp-based) |
|
|
299
302
|
| `archive` | mutation | required | Archive a notification |
|
|
300
|
-
| `registerPushToken` | mutation | required | Register an Expo push token |
|
|
301
|
-
| `updatePreferences` | mutation | required | Update channel preferences (global/category/event) |
|
|
302
303
|
| `getPreferences` | query | required | Get user's notification preferences |
|
|
304
|
+
| `updatePreference` | mutation | required | Update channel preferences (global/category/event) |
|
|
303
305
|
|
|
304
306
|
## Configuration
|
|
305
307
|
|
|
306
308
|
```ts
|
|
307
|
-
interface
|
|
309
|
+
interface NotificationsOptions {
|
|
308
310
|
/** Resolve the current user ID from the request context. */
|
|
309
|
-
auth: (ctx:
|
|
311
|
+
auth: (ctx: { auth: Auth }) => Promise<string>;
|
|
310
312
|
|
|
311
313
|
/** Resolve delivery addresses per channel. Return null to skip the channel. */
|
|
312
|
-
resolvers
|
|
313
|
-
email?: (ctx:
|
|
314
|
-
phone?: (ctx:
|
|
315
|
-
pushToken?: (ctx:
|
|
314
|
+
resolvers?: {
|
|
315
|
+
email?: (ctx: { auth: Auth }, userId: string) => Promise<string | null>;
|
|
316
|
+
phone?: (ctx: { auth: Auth }, userId: string) => Promise<string | null>;
|
|
317
|
+
pushToken?: (ctx: { auth: Auth }, userId: string) => Promise<string | null>;
|
|
316
318
|
};
|
|
317
319
|
}
|
|
318
320
|
```
|
|
@@ -348,7 +350,7 @@ npx convex dev
|
|
|
348
350
|
|
|
349
351
|
### Auth provider mismatch
|
|
350
352
|
|
|
351
|
-
The `auth` function in `
|
|
353
|
+
The `auth` function in `new Notifications()` must match your auth setup. For Convex Auth:
|
|
352
354
|
```ts
|
|
353
355
|
auth: async (ctx) => {
|
|
354
356
|
const userId = await getAuthUserId(ctx);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel adapters for dispatching notifications through child components.
|
|
3
|
+
*
|
|
4
|
+
* These adapters wrap the child component clients (expo-push-notifications,
|
|
5
|
+
* resend, twilio) and provide a unified interface for the Notifications class.
|
|
6
|
+
*/
|
|
7
|
+
import type { PushNotifications } from "@convex-dev/expo-push-notifications";
|
|
8
|
+
import type { Resend } from "@convex-dev/resend";
|
|
9
|
+
import type { Twilio } from "@convex-dev/twilio";
|
|
10
|
+
import type { RunMutationCtx, RunActionCtx, DeliveryResult } from "./types.js";
|
|
11
|
+
export type { PushNotifications } from "@convex-dev/expo-push-notifications";
|
|
12
|
+
export type { Resend } from "@convex-dev/resend";
|
|
13
|
+
export type { Twilio } from "@convex-dev/twilio";
|
|
14
|
+
/**
|
|
15
|
+
* Rendered content for each channel type
|
|
16
|
+
*/
|
|
17
|
+
export type RenderedEmail = {
|
|
18
|
+
from: string;
|
|
19
|
+
to: string;
|
|
20
|
+
subject: string;
|
|
21
|
+
body: string;
|
|
22
|
+
html?: string;
|
|
23
|
+
};
|
|
24
|
+
export type RenderedPush = {
|
|
25
|
+
userId: string;
|
|
26
|
+
title: string;
|
|
27
|
+
body: string;
|
|
28
|
+
data?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
export type RenderedSms = {
|
|
31
|
+
from: string;
|
|
32
|
+
to: string;
|
|
33
|
+
body: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Email adapter using the Resend component
|
|
37
|
+
*/
|
|
38
|
+
export declare function dispatchEmail(ctx: RunMutationCtx, resend: Resend, rendered: RenderedEmail): Promise<DeliveryResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Push notification adapter using the Expo Push Notifications component
|
|
41
|
+
*/
|
|
42
|
+
export declare function dispatchPush(ctx: RunMutationCtx, pushNotifications: PushNotifications<string>, rendered: RenderedPush, allowUnregisteredTokens?: boolean): Promise<DeliveryResult>;
|
|
43
|
+
/**
|
|
44
|
+
* SMS adapter using the Twilio component.
|
|
45
|
+
* Note: Twilio requires action context, so this must be called from an action.
|
|
46
|
+
*/
|
|
47
|
+
export declare function dispatchSms(ctx: RunActionCtx, twilio: Twilio<{
|
|
48
|
+
defaultFrom: string;
|
|
49
|
+
}>, rendered: RenderedSms): Promise<DeliveryResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if the context has action capabilities (runAction)
|
|
52
|
+
*/
|
|
53
|
+
export declare function isActionContext(ctx: RunMutationCtx | RunActionCtx): ctx is RunActionCtx;
|
|
54
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/client/adapters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG/E,YAAY,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,cAAc,CAAC,CAuBzB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,cAAc,EACnB,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAC5C,QAAQ,EAAE,YAAY,EACtB,uBAAuB,GAAE,OAAc,GACtC,OAAO,CAAC,cAAc,CAAC,CAiCzB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,MAAM,CAAC;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,EACvC,QAAQ,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,CAqBzB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,cAAc,GAAG,YAAY,GACjC,GAAG,IAAI,YAAY,CAErB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel adapters for dispatching notifications through child components.
|
|
3
|
+
*
|
|
4
|
+
* These adapters wrap the child component clients (expo-push-notifications,
|
|
5
|
+
* resend, twilio) and provide a unified interface for the Notifications class.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Email adapter using the Resend component
|
|
9
|
+
*/
|
|
10
|
+
export async function dispatchEmail(ctx, resend, rendered) {
|
|
11
|
+
try {
|
|
12
|
+
const emailId = await resend.sendEmail(ctx, {
|
|
13
|
+
from: rendered.from,
|
|
14
|
+
to: rendered.to,
|
|
15
|
+
subject: rendered.subject,
|
|
16
|
+
html: rendered.html,
|
|
17
|
+
text: rendered.body,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
channel: "email",
|
|
21
|
+
status: "sent",
|
|
22
|
+
externalId: emailId,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
27
|
+
return {
|
|
28
|
+
channel: "email",
|
|
29
|
+
status: "failed",
|
|
30
|
+
error: errorMessage,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Push notification adapter using the Expo Push Notifications component
|
|
36
|
+
*/
|
|
37
|
+
export async function dispatchPush(ctx, pushNotifications, rendered, allowUnregisteredTokens = true) {
|
|
38
|
+
try {
|
|
39
|
+
const notificationId = await pushNotifications.sendPushNotification(ctx, {
|
|
40
|
+
userId: rendered.userId,
|
|
41
|
+
notification: {
|
|
42
|
+
title: rendered.title,
|
|
43
|
+
body: rendered.body,
|
|
44
|
+
data: rendered.data,
|
|
45
|
+
},
|
|
46
|
+
allowUnregisteredTokens,
|
|
47
|
+
});
|
|
48
|
+
if (notificationId === null) {
|
|
49
|
+
return {
|
|
50
|
+
channel: "push",
|
|
51
|
+
status: "skipped",
|
|
52
|
+
error: "User has paused notifications or no token registered",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
channel: "push",
|
|
57
|
+
status: "sent",
|
|
58
|
+
externalId: notificationId,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
63
|
+
return {
|
|
64
|
+
channel: "push",
|
|
65
|
+
status: "failed",
|
|
66
|
+
error: errorMessage,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* SMS adapter using the Twilio component.
|
|
72
|
+
* Note: Twilio requires action context, so this must be called from an action.
|
|
73
|
+
*/
|
|
74
|
+
export async function dispatchSms(ctx, twilio, rendered) {
|
|
75
|
+
try {
|
|
76
|
+
const result = await twilio.sendMessage(ctx, {
|
|
77
|
+
from: rendered.from,
|
|
78
|
+
to: rendered.to,
|
|
79
|
+
body: rendered.body,
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
channel: "sms",
|
|
83
|
+
status: "sent",
|
|
84
|
+
externalId: result.sid,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
89
|
+
return {
|
|
90
|
+
channel: "sms",
|
|
91
|
+
status: "failed",
|
|
92
|
+
error: errorMessage,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if the context has action capabilities (runAction)
|
|
98
|
+
*/
|
|
99
|
+
export function isActionContext(ctx) {
|
|
100
|
+
return "runAction" in ctx;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/client/adapters.ts"],"names":[],"mappings":"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"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,12 +1,42 @@
|
|
|
1
|
-
import type { Auth, FunctionReference, FunctionArgs, FunctionReturnType } from "convex/server";
|
|
2
1
|
import type { ComponentApi } from "../component/_generated/component.js";
|
|
3
|
-
import type { NotificationsOptions, NotificationDefinition } from "./types.js";
|
|
2
|
+
import type { NotificationsOptions, NotificationDefinition, RunQueryCtx, RunMutationCtx, RunActionCtx, SendResult } from "./types.js";
|
|
3
|
+
import type { PushNotifications } from "@convex-dev/expo-push-notifications";
|
|
4
|
+
import type { Resend } from "@convex-dev/resend";
|
|
5
|
+
import type { Twilio } from "@convex-dev/twilio";
|
|
4
6
|
export type { NotificationsOptions, NotificationDefinition } from "./types.js";
|
|
5
|
-
export type { ChannelTemplates, EmailTemplate, InboxTemplate, PushTemplate, SmsTemplate, } from "./types.js";
|
|
7
|
+
export type { ChannelTemplates, EmailTemplate, InboxTemplate, PushTemplate, SmsTemplate, ChannelConfig, EmailChannelConfig, PushChannelConfig, SmsChannelConfig, DeliveryResult, SendResult, RunQueryCtx, RunMutationCtx, RunActionCtx, } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Extended options that include child component clients for delivery.
|
|
10
|
+
*/
|
|
11
|
+
export type NotificationsWithChannelsOptions = NotificationsOptions & {
|
|
12
|
+
/**
|
|
13
|
+
* Child component clients for channel delivery.
|
|
14
|
+
* Pass these to enable actual delivery through each channel.
|
|
15
|
+
*/
|
|
16
|
+
clients?: {
|
|
17
|
+
/**
|
|
18
|
+
* Resend client for email delivery.
|
|
19
|
+
* Create with: new Resend(components.resend, { ... })
|
|
20
|
+
*/
|
|
21
|
+
email?: Resend;
|
|
22
|
+
/**
|
|
23
|
+
* Expo Push Notifications client for push delivery.
|
|
24
|
+
* Create with: new PushNotifications(components.pushNotifications, { ... })
|
|
25
|
+
*/
|
|
26
|
+
push?: PushNotifications<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Twilio client for SMS delivery.
|
|
29
|
+
* Create with: new Twilio(components.twilio, { ... })
|
|
30
|
+
*/
|
|
31
|
+
sms?: Twilio<{
|
|
32
|
+
defaultFrom: string;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
6
36
|
export declare class Notifications {
|
|
7
37
|
component: ComponentApi;
|
|
8
|
-
options:
|
|
9
|
-
constructor(component: ComponentApi, options:
|
|
38
|
+
options: NotificationsWithChannelsOptions;
|
|
39
|
+
constructor(component: ComponentApi, options: NotificationsWithChannelsOptions);
|
|
10
40
|
list(ctx: RunQueryCtx, opts?: {
|
|
11
41
|
limit?: number;
|
|
12
42
|
cursor?: number;
|
|
@@ -25,20 +55,113 @@ export declare class Notifications {
|
|
|
25
55
|
channel: string;
|
|
26
56
|
enabled: boolean;
|
|
27
57
|
}): Promise<string>;
|
|
28
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Register a push notification token for a user.
|
|
60
|
+
* Uses the component's internal push token storage.
|
|
61
|
+
*/
|
|
62
|
+
registerPushToken(ctx: RunMutationCtx, args: {
|
|
63
|
+
token: string;
|
|
64
|
+
platform?: "ios" | "android" | "web";
|
|
65
|
+
deviceId?: string;
|
|
66
|
+
}): Promise<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Get all push tokens for the current user.
|
|
69
|
+
*/
|
|
70
|
+
getPushTokens(ctx: RunQueryCtx): Promise<{
|
|
71
|
+
_id: string;
|
|
72
|
+
_creationTime: number;
|
|
73
|
+
userId: string;
|
|
74
|
+
token: string;
|
|
75
|
+
platform?: "ios" | "android" | "web";
|
|
76
|
+
deviceId?: string;
|
|
77
|
+
}[]>;
|
|
78
|
+
/**
|
|
79
|
+
* Delete a push token.
|
|
80
|
+
*/
|
|
81
|
+
deletePushToken(ctx: RunMutationCtx, token: string): Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Send a notification through all enabled channels.
|
|
84
|
+
*
|
|
85
|
+
* @returns The notification ID and delivery results for each channel
|
|
86
|
+
*/
|
|
87
|
+
send<T>(ctx: RunMutationCtx | RunActionCtx, definition: NotificationDefinition<T>, args: {
|
|
29
88
|
userId: string;
|
|
30
89
|
data: T;
|
|
31
90
|
transactional?: boolean;
|
|
32
91
|
deduplicationKey?: string;
|
|
33
92
|
deduplicationTtlSeconds?: number;
|
|
34
|
-
}): Promise<
|
|
93
|
+
}): Promise<SendResult>;
|
|
94
|
+
/**
|
|
95
|
+
* Dispatch a notification to a specific channel.
|
|
96
|
+
*/
|
|
97
|
+
private dispatchChannel;
|
|
98
|
+
/**
|
|
99
|
+
* Update delivery status for a notification channel.
|
|
100
|
+
* Call this from webhook handlers or after async delivery completes.
|
|
101
|
+
*/
|
|
102
|
+
updateDeliveryStatus(ctx: RunMutationCtx, args: {
|
|
103
|
+
deliveryLogId: string;
|
|
104
|
+
status: "sent" | "delivered" | "failed";
|
|
105
|
+
error?: string;
|
|
106
|
+
sentAt?: number;
|
|
107
|
+
}): Promise<null>;
|
|
108
|
+
/**
|
|
109
|
+
* Get delivery logs for a notification.
|
|
110
|
+
*/
|
|
111
|
+
getDeliveryLogs(ctx: RunQueryCtx, notificationId: string): Promise<any[]>;
|
|
112
|
+
/**
|
|
113
|
+
* Returns pre-built query and mutation functions for direct export.
|
|
114
|
+
*
|
|
115
|
+
* Usage:
|
|
116
|
+
* ```ts
|
|
117
|
+
* export const { list, unreadCount, markRead, markAllRead, archive, getPreferences, updatePreference } = notifications.api();
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
api(): {
|
|
121
|
+
/**
|
|
122
|
+
* List notifications for the current user (paginated)
|
|
123
|
+
*/
|
|
124
|
+
list: import("convex/server").RegisteredQuery<"public", {
|
|
125
|
+
limit?: number;
|
|
126
|
+
cursor?: number;
|
|
127
|
+
}, Promise<{
|
|
128
|
+
cursor: number | null;
|
|
129
|
+
notifications: any[];
|
|
130
|
+
}>>;
|
|
131
|
+
/**
|
|
132
|
+
* Get unread notification count for the current user
|
|
133
|
+
*/
|
|
134
|
+
unreadCount: import("convex/server").RegisteredQuery<"public", {}, Promise<number>>;
|
|
135
|
+
/**
|
|
136
|
+
* Mark a notification as read
|
|
137
|
+
*/
|
|
138
|
+
markRead: import("convex/server").RegisteredMutation<"public", {
|
|
139
|
+
notificationId: string;
|
|
140
|
+
}, Promise<null>>;
|
|
141
|
+
/**
|
|
142
|
+
* Mark all notifications as read for the current user
|
|
143
|
+
*/
|
|
144
|
+
markAllRead: import("convex/server").RegisteredMutation<"public", {}, Promise<null>>;
|
|
145
|
+
/**
|
|
146
|
+
* Archive a notification
|
|
147
|
+
*/
|
|
148
|
+
archive: import("convex/server").RegisteredMutation<"public", {
|
|
149
|
+
notificationId: string;
|
|
150
|
+
}, Promise<null>>;
|
|
151
|
+
/**
|
|
152
|
+
* Get notification preferences for the current user
|
|
153
|
+
*/
|
|
154
|
+
getPreferences: import("convex/server").RegisteredQuery<"public", {}, Promise<any[]>>;
|
|
155
|
+
/**
|
|
156
|
+
* Update a notification preference
|
|
157
|
+
*/
|
|
158
|
+
updatePreference: import("convex/server").RegisteredMutation<"public", {
|
|
159
|
+
level: "global" | "category" | "event";
|
|
160
|
+
key?: string;
|
|
161
|
+
channel: string;
|
|
162
|
+
enabled: boolean;
|
|
163
|
+
}, Promise<string>>;
|
|
164
|
+
};
|
|
35
165
|
}
|
|
36
166
|
export default Notifications;
|
|
37
|
-
export type RunQueryCtx = {
|
|
38
|
-
runQuery: <Query extends FunctionReference<"query", "internal">>(query: Query, args: FunctionArgs<Query>) => Promise<FunctionReturnType<Query>>;
|
|
39
|
-
auth: Auth;
|
|
40
|
-
};
|
|
41
|
-
export type RunMutationCtx = RunQueryCtx & {
|
|
42
|
-
runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(mutation: Mutation, args: FunctionArgs<Mutation>) => Promise<FunctionReturnType<Mutation>>;
|
|
43
|
-
};
|
|
44
167
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|