@digimuza/system-core 0.2.0 → 0.3.0-rc.1

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.
Files changed (151) hide show
  1. package/INTEGRATION.md +209 -3
  2. package/README.md +23 -0
  3. package/dist/ai/api.d.ts +120 -0
  4. package/dist/ai/api.d.ts.map +1 -0
  5. package/dist/ai/api.js +446 -0
  6. package/dist/ai/api.js.map +1 -0
  7. package/dist/ai/card.d.ts +27 -0
  8. package/dist/ai/card.d.ts.map +1 -0
  9. package/dist/ai/card.js +84 -0
  10. package/dist/ai/card.js.map +1 -0
  11. package/dist/ai/contract.d.ts +364 -0
  12. package/dist/ai/contract.d.ts.map +1 -0
  13. package/dist/ai/contract.js +101 -0
  14. package/dist/ai/contract.js.map +1 -0
  15. package/dist/ai/display.d.ts +20 -0
  16. package/dist/ai/display.d.ts.map +1 -0
  17. package/dist/ai/display.js +35 -0
  18. package/dist/ai/display.js.map +1 -0
  19. package/dist/ai/index.d.ts +7 -0
  20. package/dist/ai/index.d.ts.map +1 -0
  21. package/dist/ai/index.js +10 -0
  22. package/dist/ai/index.js.map +1 -0
  23. package/dist/ai/manifest.d.ts +25 -0
  24. package/dist/ai/manifest.d.ts.map +1 -0
  25. package/dist/ai/manifest.js +15 -0
  26. package/dist/ai/manifest.js.map +1 -0
  27. package/dist/ai/runner.d.ts +71 -0
  28. package/dist/ai/runner.d.ts.map +1 -0
  29. package/dist/ai/runner.js +246 -0
  30. package/dist/ai/runner.js.map +1 -0
  31. package/dist/ai/tools.d.ts +42 -0
  32. package/dist/ai/tools.d.ts.map +1 -0
  33. package/dist/ai/tools.js +117 -0
  34. package/dist/ai/tools.js.map +1 -0
  35. package/dist/audit/csv.d.ts +31 -0
  36. package/dist/audit/csv.d.ts.map +1 -0
  37. package/dist/audit/csv.js +39 -0
  38. package/dist/audit/csv.js.map +1 -0
  39. package/dist/audit/index.d.ts +5 -0
  40. package/dist/audit/index.d.ts.map +1 -0
  41. package/dist/audit/index.js +6 -0
  42. package/dist/audit/index.js.map +1 -0
  43. package/dist/convex/functions.d.ts +39 -0
  44. package/dist/convex/functions.d.ts.map +1 -1
  45. package/dist/convex/functions.js +38 -6
  46. package/dist/convex/functions.js.map +1 -1
  47. package/dist/convex/index.d.ts +1 -1
  48. package/dist/convex/index.d.ts.map +1 -1
  49. package/dist/convex/index.js.map +1 -1
  50. package/dist/core/access.d.ts +14 -0
  51. package/dist/core/access.d.ts.map +1 -1
  52. package/dist/core/access.js +62 -0
  53. package/dist/core/access.js.map +1 -1
  54. package/dist/core/audit-module.d.ts +5 -0
  55. package/dist/core/audit-module.d.ts.map +1 -0
  56. package/dist/core/audit-module.js +25 -0
  57. package/dist/core/audit-module.js.map +1 -0
  58. package/dist/core/audit.d.ts +31 -0
  59. package/dist/core/audit.d.ts.map +1 -1
  60. package/dist/core/audit.js +46 -2
  61. package/dist/core/audit.js.map +1 -1
  62. package/dist/core/catalog.d.ts +41 -0
  63. package/dist/core/catalog.d.ts.map +1 -1
  64. package/dist/core/catalog.js +45 -0
  65. package/dist/core/catalog.js.map +1 -1
  66. package/dist/core/context.d.ts +8 -2
  67. package/dist/core/context.d.ts.map +1 -1
  68. package/dist/core/context.js +4 -1
  69. package/dist/core/context.js.map +1 -1
  70. package/dist/core/index.d.ts +2 -0
  71. package/dist/core/index.d.ts.map +1 -1
  72. package/dist/core/index.js +2 -0
  73. package/dist/core/index.js.map +1 -1
  74. package/dist/core/notify.d.ts +37 -0
  75. package/dist/core/notify.d.ts.map +1 -0
  76. package/dist/core/notify.js +16 -0
  77. package/dist/core/notify.js.map +1 -0
  78. package/dist/core/roles.d.ts.map +1 -1
  79. package/dist/core/roles.js +5 -1
  80. package/dist/core/roles.js.map +1 -1
  81. package/dist/core/system-modules.d.ts +4 -0
  82. package/dist/core/system-modules.d.ts.map +1 -1
  83. package/dist/core/system-modules.js +11 -0
  84. package/dist/core/system-modules.js.map +1 -1
  85. package/dist/finance/ai-tools.d.ts +55 -0
  86. package/dist/finance/ai-tools.d.ts.map +1 -0
  87. package/dist/finance/ai-tools.js +65 -0
  88. package/dist/finance/ai-tools.js.map +1 -0
  89. package/dist/finance/index.d.ts +87 -1
  90. package/dist/finance/index.d.ts.map +1 -1
  91. package/dist/finance/index.js +92 -38
  92. package/dist/finance/index.js.map +1 -1
  93. package/dist/finance/search.d.ts +15 -0
  94. package/dist/finance/search.d.ts.map +1 -0
  95. package/dist/finance/search.js +51 -0
  96. package/dist/finance/search.js.map +1 -0
  97. package/dist/index.d.ts +2 -0
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +2 -0
  100. package/dist/index.js.map +1 -1
  101. package/dist/modules/index.d.ts +1 -1
  102. package/dist/modules/index.d.ts.map +1 -1
  103. package/dist/modules/index.js +1 -1
  104. package/dist/modules/index.js.map +1 -1
  105. package/dist/notifications/api.d.ts +130 -0
  106. package/dist/notifications/api.d.ts.map +1 -0
  107. package/dist/notifications/api.js +384 -0
  108. package/dist/notifications/api.js.map +1 -0
  109. package/dist/notifications/contract.d.ts +132 -0
  110. package/dist/notifications/contract.d.ts.map +1 -0
  111. package/dist/notifications/contract.js +59 -0
  112. package/dist/notifications/contract.js.map +1 -0
  113. package/dist/notifications/index.d.ts +6 -0
  114. package/dist/notifications/index.d.ts.map +1 -0
  115. package/dist/notifications/index.js +9 -0
  116. package/dist/notifications/index.js.map +1 -0
  117. package/dist/search/index.d.ts +95 -0
  118. package/dist/search/index.d.ts.map +1 -0
  119. package/dist/search/index.js +151 -0
  120. package/dist/search/index.js.map +1 -0
  121. package/package.json +41 -2
  122. package/src/ai/api.ts +535 -0
  123. package/src/ai/card.ts +91 -0
  124. package/src/ai/contract.ts +245 -0
  125. package/src/ai/display.ts +38 -0
  126. package/src/ai/index.ts +9 -0
  127. package/src/ai/manifest.ts +16 -0
  128. package/src/ai/runner.ts +275 -0
  129. package/src/ai/tools.ts +128 -0
  130. package/src/audit/csv.ts +60 -0
  131. package/src/audit/index.ts +7 -0
  132. package/src/convex/functions.ts +54 -7
  133. package/src/convex/index.ts +1 -1
  134. package/src/core/access.ts +55 -1
  135. package/src/core/audit-module.ts +26 -0
  136. package/src/core/audit.ts +68 -2
  137. package/src/core/catalog.ts +63 -0
  138. package/src/core/context.ts +13 -2
  139. package/src/core/index.ts +2 -0
  140. package/src/core/notify.ts +52 -0
  141. package/src/core/roles.ts +5 -1
  142. package/src/core/system-modules.ts +12 -0
  143. package/src/finance/ai-tools.ts +68 -0
  144. package/src/finance/index.ts +119 -42
  145. package/src/finance/search.ts +58 -0
  146. package/src/index.ts +2 -0
  147. package/src/modules/index.ts +3 -0
  148. package/src/notifications/api.ts +477 -0
  149. package/src/notifications/contract.ts +142 -0
  150. package/src/notifications/index.ts +8 -0
  151. package/src/search/index.ts +198 -0
@@ -0,0 +1,384 @@
1
+ // Notifications (DIG-74): the per-transaction notifier, `notify` for modules,
2
+ // and the Convex functions of `defineNotifications`.
3
+ //
4
+ // Access: notifications are the user's own data, guarded like the profile
5
+ // (`getMyProfile`): a human session plus `profile:own:read` (reads) or
6
+ // `profile:own:update` (changes). Every active user holds both through the
7
+ // protected, implicit Profile role, so no catalog migration is needed; API keys
8
+ // get FORBIDDEN (human-only permissions); suspended users get FORBIDDEN.
9
+ import { internalActionGeneric, internalMutationGeneric, makeFunctionReference, mutationGeneric, queryGeneric } from "convex/server";
10
+ import { v } from "convex/values";
11
+ import { isModuleEnabled, isSuperActor, requireHuman, usersWithPermission } from "../core/access.js";
12
+ import { recordAudit } from "../core/audit.js";
13
+ import { notFound, validation } from "../core/errors.js";
14
+ import { P } from "../core/system-modules.js";
15
+ import { toConvexError } from "../convex/functions.js";
16
+ import { NOTIFICATION_MARK_ALL_BATCH, NOTIFICATION_PARAMS_MAX, NOTIFICATION_UNREAD_CAP, NOTIFICATIONS_AUDIT, NOTIFY_MAX_RECIPIENTS, } from "./contract.js";
17
+ const DEFAULT_LOCALE = "lt";
18
+ const SAFE_HREF = /^\/(?!\/)[^\s\\]*$/;
19
+ const db = (ctx) => ctx.db;
20
+ /** Created by `notificationsHook`; pass it to `defineConvexSystem({ notifications })`. */
21
+ export class NotificationsInstall {
22
+ functionsModule;
23
+ email;
24
+ defaultLocale;
25
+ extraTypes;
26
+ cache = new WeakMap();
27
+ constructor(options = {}) {
28
+ this.functionsModule = options.functionsModule ?? "notifications";
29
+ this.email = options.email ?? true;
30
+ this.defaultLocale = options.defaultLocale ?? DEFAULT_LOCALE;
31
+ this.extraTypes = options.types ?? [];
32
+ }
33
+ /** All notification types of the system: module manifests + `types`. Throws on unknown modules or collisions. */
34
+ typesOf(catalog) {
35
+ let map = this.cache.get(catalog);
36
+ if (map)
37
+ return map;
38
+ const out = new Map(catalog.notificationTypes);
39
+ for (const t of this.extraTypes) {
40
+ if (!catalog.modules.has(t.moduleId))
41
+ throw new Error(`notificationsHook: type ${t.id} belongs to unknown module ${t.moduleId}`);
42
+ if (out.has(t.id))
43
+ throw new Error(`notificationsHook: duplicate notification type ${t.id}`);
44
+ out.set(t.id, t);
45
+ }
46
+ map = out;
47
+ this.cache.set(catalog, map);
48
+ return map;
49
+ }
50
+ deliverRef() {
51
+ return makeFunctionReference(`${this.functionsModule}:_deliverNotificationEmail`);
52
+ }
53
+ bind(ctx, sys) {
54
+ return new BoundNotifier(this, ctx, sys);
55
+ }
56
+ }
57
+ class BoundNotifier {
58
+ install;
59
+ ctx;
60
+ sys;
61
+ constructor(install, ctx, sys) {
62
+ this.install = install;
63
+ this.ctx = ctx;
64
+ this.sys = sys;
65
+ }
66
+ notify(request) {
67
+ return send(this.ctx, this.sys, this.install, request);
68
+ }
69
+ }
70
+ /**
71
+ * The system hook that installs notifications:
72
+ *
73
+ * defineConvexSystem({ modules, notifications: notificationsHook() })
74
+ *
75
+ * Every mutation's SystemContext then carries a notifier, so core services
76
+ * (role assignment) and modules (finance) notify through `notifyIfInstalled`.
77
+ */
78
+ export function notificationsHook(options = {}) {
79
+ return new NotificationsInstall(options);
80
+ }
81
+ // --- Sending -----------------------------------------------------------------------------------
82
+ const isPlainObject = (x) => Object.prototype.toString.call(x) === "[object Object]";
83
+ function fail(sys, e) {
84
+ e.operationId ??= sys.operationId;
85
+ throw e;
86
+ }
87
+ /** The acting human (an agent acts for its owner). */
88
+ const actingUserId = (actor) => (!actor || actor === "system" ? null : actor.kind === "user" ? actor.userId : actor.ownerId);
89
+ async function recipients(sys, request) {
90
+ const to = request.to;
91
+ if ("userIds" in to) {
92
+ const ids = [...new Set(to.userIds)];
93
+ if (ids.length > NOTIFY_MAX_RECIPIENTS)
94
+ fail(sys, validation("too_many_recipients", ["to"]));
95
+ const out = [];
96
+ for (const id of ids) {
97
+ const user = await sys.store.get("users", id);
98
+ if (user?.status === "active")
99
+ out.push(id);
100
+ }
101
+ return out;
102
+ }
103
+ if (!sys.def.catalog.permissions.has(to.permission))
104
+ fail(sys, validation("unknown_permission", ["to"]));
105
+ const exclude = request.includeActor ? null : actingUserId(request.actor);
106
+ const { userIds, truncated } = await usersWithPermission(sys, to.permission, NOTIFY_MAX_RECIPIENTS + 1);
107
+ const out = userIds.filter((id) => id !== exclude).slice(0, NOTIFY_MAX_RECIPIENTS);
108
+ if (truncated || userIds.filter((id) => id !== exclude).length > NOTIFY_MAX_RECIPIENTS) {
109
+ sys.logger.warn("notify_recipients_capped", { type: request.type, max: NOTIFY_MAX_RECIPIENTS });
110
+ }
111
+ return out;
112
+ }
113
+ async function preference(ctx, userId, type) {
114
+ return db(ctx)
115
+ .query("notificationPreferences")
116
+ .withIndex("by_user_type", (q) => q.eq("userId", userId).eq("type", type))
117
+ .unique();
118
+ }
119
+ /**
120
+ * Validates, resolves recipients, applies each recipient's preferences, inserts
121
+ * rows and schedules emails. Returns the number of recipients notified.
122
+ */
123
+ async function send(ctx, sys, install, request) {
124
+ const type = install.typesOf(sys.def.catalog).get(request.type);
125
+ if (!type)
126
+ fail(sys, validation("unknown_notification_type", ["type"]));
127
+ if (!isPlainObject(request.params))
128
+ fail(sys, validation("invalid_params", ["params"]));
129
+ let json;
130
+ try {
131
+ json = JSON.stringify(request.params);
132
+ }
133
+ catch {
134
+ fail(sys, validation("invalid_params", ["params"]));
135
+ }
136
+ if (json.length > NOTIFICATION_PARAMS_MAX)
137
+ fail(sys, validation("params_too_large", ["params"]));
138
+ const params = JSON.parse(json);
139
+ if (request.href !== undefined && (request.href.length > 500 || !SAFE_HREF.test(request.href)))
140
+ fail(sys, validation("invalid_href", ["href"]));
141
+ const writer = db(ctx);
142
+ if (typeof writer.insert !== "function")
143
+ throw new Error("notify must run inside a mutation");
144
+ let userIds = await recipients(sys, request);
145
+ // A disabled module's notifications reach only those who can still use it (an effective Super).
146
+ if (!isModuleEnabled(sys, await sys.store.get("modules", type.moduleId))) {
147
+ const supers = [];
148
+ for (const id of userIds)
149
+ if (await isSuperActor(sys, { kind: "user", userId: id }))
150
+ supers.push(id);
151
+ userIds = supers;
152
+ }
153
+ const scheduler = ctx.scheduler;
154
+ const now = sys.now();
155
+ let count = 0;
156
+ for (const userId of userIds) {
157
+ const pref = await preference(ctx, userId, type.id);
158
+ const inApp = pref?.inApp ?? type.defaultChannels.inApp;
159
+ const email = pref?.email ?? type.defaultChannels.email;
160
+ if (!inApp && !email)
161
+ continue;
162
+ const emailStatus = !email ? "none" : install.email && scheduler ? "pending" : "skipped";
163
+ const row = { userId, type: type.id, params, inApp, createdAt: now, emailStatus, operationId: sys.operationId };
164
+ if (request.href !== undefined)
165
+ row.href = request.href;
166
+ const id = await db(ctx).insert("notifications", row);
167
+ if (emailStatus === "pending")
168
+ await scheduler.runAfter(0, install.deliverRef(), { notificationId: id });
169
+ count++;
170
+ }
171
+ sys.logger.info("notifications_sent", { type: type.id, count });
172
+ return count;
173
+ }
174
+ /**
175
+ * Sends a notification from any mutation of a module:
176
+ *
177
+ * await notify(ctx, sys, { to: { permission: "crm:lead:assign" }, type: "crm.lead_assigned", params: { name }, href: "/app/crm", actor })
178
+ *
179
+ * `to.permission` → active users holding it now (via `decide`; module state and
180
+ * role view apply), without the acting user unless `includeActor`. At most
181
+ * NOTIFY_MAX_RECIPIENTS. Each recipient's preferences apply; emails are scheduled
182
+ * only for those with email on. Returns the count; 0 when notifications are not
183
+ * installed. Throws VALIDATION for an unknown type, bad params or href.
184
+ * (Core services and package modules use the swallowing `notifyIfInstalled`.)
185
+ */
186
+ export async function notify(ctx, sys, request) {
187
+ const notifier = sys.notifier;
188
+ if (!(notifier instanceof BoundNotifier))
189
+ return 0;
190
+ return send(ctx, sys, notifier.install, request);
191
+ }
192
+ const PAGE_DEFAULT = 20;
193
+ const PAGE_MAX = 100;
194
+ const actorArgs = { apiKey: v.optional(v.string()), operationId: v.optional(v.string()) };
195
+ /**
196
+ * The notifications Convex functions, bound to the app's system (which must have
197
+ * `notifications: notificationsHook()`):
198
+ *
199
+ * // convex/notifications.ts
200
+ * export const { listNotifications, …, _deliverNotificationEmail, _claimNotificationEmail, _recordNotificationEmail } =
201
+ * defineNotifications(system, { renderEmail, deliverEmail }).functions
202
+ */
203
+ export function defineNotifications(system, options = {}) {
204
+ const install = system.notifications;
205
+ if (!(install instanceof NotificationsInstall)) {
206
+ throw new Error("defineNotifications: install the hook first: defineConvexSystem({ notifications: notificationsHook() })");
207
+ }
208
+ const types = install.typesOf(system.definition.catalog);
209
+ const ref = (name) => makeFunctionReference(`${install.functionsModule}:${name}`);
210
+ const canEmail = !!options.renderEmail && !!options.deliverEmail;
211
+ /** Own data, like the profile: human session + profile:own:read / profile:own:update. */
212
+ async function guard(ctx, a, permission) {
213
+ const { sys, actor } = await system.requirePermission(ctx, permission, { apiKey: a.apiKey, operationId: a.operationId });
214
+ try {
215
+ return { sys, actor: requireHuman(sys, actor) };
216
+ }
217
+ catch (e) {
218
+ throw toConvexError(e, sys.operationId);
219
+ }
220
+ }
221
+ const moduleOf = (type) => types.get(type)?.moduleId ?? type.split(".", 1)[0];
222
+ const view = (n) => ({
223
+ id: n._id,
224
+ type: n.type,
225
+ moduleId: moduleOf(n.type),
226
+ params: n.params,
227
+ href: n.href ?? null,
228
+ readAt: n.readAt ?? null,
229
+ createdAt: n.createdAt,
230
+ emailStatus: n.emailStatus,
231
+ });
232
+ /** Types whose module the actor can use now (an effective Super sees disabled modules too). */
233
+ async function visibleTypes(sys, actor) {
234
+ const isSuper = await isSuperActor(sys, actor);
235
+ const out = [];
236
+ for (const t of types.values()) {
237
+ if (isSuper || isModuleEnabled(sys, await sys.store.get("modules", t.moduleId)))
238
+ out.push(t);
239
+ }
240
+ return out.sort((a, b) => a.moduleId.localeCompare(b.moduleId) || a.id.localeCompare(b.id));
241
+ }
242
+ const prefView = (t, pref) => ({
243
+ type: t.id,
244
+ moduleId: t.moduleId,
245
+ description: t.description ?? null,
246
+ params: [...(t.params ?? [])],
247
+ defaultChannels: { inApp: t.defaultChannels.inApp, email: t.defaultChannels.email },
248
+ inApp: pref?.inApp ?? t.defaultChannels.inApp,
249
+ email: pref?.email ?? t.defaultChannels.email,
250
+ customized: !!pref,
251
+ });
252
+ const unread = (ctx, userId) => db(ctx)
253
+ .query("notifications")
254
+ .withIndex("by_user_unread", (q) => q.eq("userId", userId).eq("inApp", true).eq("readAt", undefined));
255
+ const functions = {
256
+ // --- Public ------------------------------------------------------------------------------
257
+ listNotifications: queryGeneric({
258
+ args: { ...actorArgs, cursor: v.optional(v.union(v.string(), v.null())), limit: v.optional(v.number()), unreadOnly: v.optional(v.boolean()) },
259
+ handler: async (ctx, a) => {
260
+ const { actor } = await guard(ctx, a, P.profileRead);
261
+ const numItems = Math.min(Math.max(1, Math.floor(a.limit ?? PAGE_DEFAULT)), PAGE_MAX);
262
+ const q = a.unreadOnly ? unread(ctx, actor.userId) : db(ctx).query("notifications").withIndex("by_user", (q) => q.eq("userId", actor.userId).eq("inApp", true));
263
+ const res = await q.order("desc").paginate({ cursor: a.cursor ?? null, numItems });
264
+ return { items: res.page.map(view), cursor: res.isDone ? null : res.continueCursor, done: res.isDone };
265
+ },
266
+ }),
267
+ unreadNotificationCount: queryGeneric({
268
+ args: { ...actorArgs },
269
+ handler: async (ctx, a) => {
270
+ const { actor } = await guard(ctx, a, P.profileRead);
271
+ return (await unread(ctx, actor.userId).take(NOTIFICATION_UNREAD_CAP)).length;
272
+ },
273
+ }),
274
+ markNotificationRead: mutationGeneric({
275
+ args: { ...actorArgs, notificationId: v.id("notifications") },
276
+ handler: async (ctx, a) => {
277
+ const { sys, actor } = await guard(ctx, a, P.profileUpdate);
278
+ const row = await db(ctx).get("notifications", a.notificationId);
279
+ // Someone else's notification and a missing one look the same.
280
+ if (!row || row.userId !== actor.userId)
281
+ throw toConvexError(notFound("notification_not_found"), sys.operationId);
282
+ if (row.readAt !== undefined)
283
+ return { read: false };
284
+ await db(ctx).patch("notifications", row._id, { readAt: sys.now() });
285
+ return { read: true };
286
+ },
287
+ }),
288
+ markAllNotificationsRead: mutationGeneric({
289
+ args: { ...actorArgs },
290
+ handler: async (ctx, a) => {
291
+ const { sys, actor } = await guard(ctx, a, P.profileUpdate);
292
+ const rows = await unread(ctx, actor.userId).take(NOTIFICATION_MARK_ALL_BATCH + 1);
293
+ const batch = rows.slice(0, NOTIFICATION_MARK_ALL_BATCH);
294
+ const now = sys.now();
295
+ for (const r of batch)
296
+ await db(ctx).patch("notifications", r._id, { readAt: now });
297
+ return { marked: batch.length, done: rows.length <= NOTIFICATION_MARK_ALL_BATCH };
298
+ },
299
+ }),
300
+ getNotificationPreferences: queryGeneric({
301
+ args: { ...actorArgs },
302
+ handler: async (ctx, a) => {
303
+ const { sys, actor } = await guard(ctx, a, P.profileRead);
304
+ const out = [];
305
+ for (const t of await visibleTypes(sys, actor))
306
+ out.push(prefView(t, await preference(ctx, actor.userId, t.id)));
307
+ return out;
308
+ },
309
+ }),
310
+ setNotificationPreference: mutationGeneric({
311
+ args: { ...actorArgs, type: v.string(), inApp: v.boolean(), email: v.boolean() },
312
+ handler: async (ctx, a) => {
313
+ const { sys, actor } = await guard(ctx, a, P.profileUpdate);
314
+ const type = (await visibleTypes(sys, actor)).find((t) => t.id === a.type);
315
+ if (!type)
316
+ throw toConvexError(validation("unknown_notification_type", ["type"]), sys.operationId);
317
+ const existing = await preference(ctx, actor.userId, type.id);
318
+ const now = sys.now();
319
+ if (existing)
320
+ await db(ctx).patch("notificationPreferences", existing._id, { inApp: a.inApp, email: a.email, updatedAt: now });
321
+ else
322
+ await db(ctx).insert("notificationPreferences", { userId: actor.userId, type: type.id, inApp: a.inApp, email: a.email, updatedAt: now });
323
+ await recordAudit(sys, actor, {
324
+ action: NOTIFICATIONS_AUDIT.preferenceUpdate,
325
+ targetType: "notification_type",
326
+ targetId: type.id,
327
+ changes: { inApp: a.inApp, email: a.email },
328
+ });
329
+ return prefView(type, { _id: existing?._id ?? "", userId: actor.userId, type: type.id, inApp: a.inApp, email: a.email, updatedAt: now });
330
+ },
331
+ }),
332
+ // --- Internal (email delivery) -------------------------------------------------------------
333
+ /** Scheduled by `notify` for each row with email `pending`. Never throws. */
334
+ _deliverNotificationEmail: internalActionGeneric({
335
+ args: { notificationId: v.id("notifications") },
336
+ handler: async (ctx, a) => {
337
+ const job = (await ctx.runMutation(ref("_claimNotificationEmail"), { notificationId: a.notificationId }));
338
+ if (!job)
339
+ return "skipped";
340
+ let ok = false;
341
+ try {
342
+ const email = await options.renderEmail(job.type, job.params, job.locale, { href: job.href, notificationId: a.notificationId });
343
+ if (!email || typeof email.subject !== "string" || typeof email.text !== "string")
344
+ throw new Error("renderEmail returned no subject/text");
345
+ const res = await options.deliverEmail({ to: job.to, subject: email.subject, text: email.text, type: job.type, notificationId: a.notificationId, operationId: job.operationId });
346
+ ok = res !== false;
347
+ }
348
+ catch (error) {
349
+ // The adapter's error may contain the address: log only its name.
350
+ system.definition.logger.warn("notification_email_failed", { notificationId: a.notificationId, type: job.type, errorName: error instanceof Error ? error.name : "unknown" });
351
+ }
352
+ await ctx.runMutation(ref("_recordNotificationEmail"), { notificationId: a.notificationId, ok });
353
+ return ok ? "sent" : "failed";
354
+ },
355
+ }),
356
+ /** → the email job, or null (and `skipped`) when there is nothing to send. */
357
+ _claimNotificationEmail: internalMutationGeneric({
358
+ args: { notificationId: v.id("notifications") },
359
+ handler: async (ctx, a) => {
360
+ const row = await db(ctx).get("notifications", a.notificationId);
361
+ if (!row || row.emailStatus !== "pending")
362
+ return null;
363
+ const { sys } = await system.context(ctx, { operationId: row.operationId });
364
+ const user = await sys.store.get("users", row.userId);
365
+ if (!canEmail || !types.has(row.type) || !user || user.status !== "active" || !user.emailVerified) {
366
+ await db(ctx).patch("notifications", row._id, { emailStatus: "skipped" });
367
+ return null;
368
+ }
369
+ return { to: user.email, locale: user.locale ?? install.defaultLocale, type: row.type, params: row.params, href: row.href ?? null, operationId: row.operationId };
370
+ },
371
+ }),
372
+ _recordNotificationEmail: internalMutationGeneric({
373
+ args: { notificationId: v.id("notifications"), ok: v.boolean() },
374
+ handler: async (ctx, a) => {
375
+ const row = await db(ctx).get("notifications", a.notificationId);
376
+ if (row?.emailStatus === "pending")
377
+ await db(ctx).patch("notifications", row._id, { emailStatus: a.ok ? "sent" : "failed" });
378
+ return null;
379
+ },
380
+ }),
381
+ };
382
+ return { functions, types };
383
+ }
384
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/notifications/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ import { type GenericId, type Infer } from "convex/values";
2
+ import type { NotificationParams } from "../core/notify.js";
3
+ export declare const emailStatus: import("convex/values").VUnion<"failed" | "none" | "pending" | "sent" | "skipped", [import("convex/values").VLiteral<"none", "required">, import("convex/values").VLiteral<"pending", "required">, import("convex/values").VLiteral<"sent", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"skipped", "required">], "required", never>;
4
+ /** Spread into the app schema next to `systemTables`. */
5
+ export declare const notificationTables: {
6
+ notifications: import("convex/server").TableDefinition<import("convex/values").VObject<{
7
+ createdAt: number;
8
+ emailStatus: "failed" | "none" | "pending" | "sent" | "skipped";
9
+ href?: string | undefined;
10
+ inApp: boolean;
11
+ operationId: string;
12
+ params: any;
13
+ readAt?: number | undefined;
14
+ type: string;
15
+ userId: string;
16
+ }, {
17
+ /** system-core user key of the recipient. Only they can see it. */
18
+ userId: import("convex/values").VString<string, "required">;
19
+ /** Notification type id, e.g. `finance.invoice_awaiting_approval`. */
20
+ type: import("convex/values").VString<string, "required">;
21
+ /** JSON params; the app renders the text (LT/EN) from them. */
22
+ params: import("convex/values").VAny<any, "required", string>;
23
+ /** App-relative link. */
24
+ href: import("convex/values").VString<string | undefined, "optional">;
25
+ /** False for email-only rows (the user turned the in-app channel off): never listed. */
26
+ inApp: import("convex/values").VBoolean<boolean, "required">;
27
+ readAt: import("convex/values").VFloat64<number | undefined, "optional">;
28
+ createdAt: import("convex/values").VFloat64<number, "required">;
29
+ /** none: email off · pending: scheduled · sent · failed · skipped: no adapter, no verified address. */
30
+ emailStatus: import("convex/values").VUnion<"failed" | "none" | "pending" | "sent" | "skipped", [import("convex/values").VLiteral<"none", "required">, import("convex/values").VLiteral<"pending", "required">, import("convex/values").VLiteral<"sent", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"skipped", "required">], "required", never>;
31
+ /** Operation that caused it (the business mutation's). */
32
+ operationId: import("convex/values").VString<string, "required">;
33
+ }, "required", "createdAt" | "emailStatus" | "href" | "inApp" | "operationId" | "params" | "readAt" | "type" | "userId" | `params.${string}`>, {
34
+ by_user: ["userId", "inApp", "createdAt", "_creationTime"];
35
+ by_user_unread: ["userId", "inApp", "readAt", "_creationTime"];
36
+ }, {}, {}>;
37
+ notificationPreferences: import("convex/server").TableDefinition<import("convex/values").VObject<{
38
+ email: boolean;
39
+ inApp: boolean;
40
+ type: string;
41
+ updatedAt: number;
42
+ userId: string;
43
+ }, {
44
+ userId: import("convex/values").VString<string, "required">;
45
+ type: import("convex/values").VString<string, "required">;
46
+ inApp: import("convex/values").VBoolean<boolean, "required">;
47
+ email: import("convex/values").VBoolean<boolean, "required">;
48
+ updatedAt: import("convex/values").VFloat64<number, "required">;
49
+ }, "required", "email" | "inApp" | "type" | "updatedAt" | "userId">, {
50
+ by_user_type: ["userId", "type", "_creationTime"];
51
+ }, {}, {}>;
52
+ };
53
+ export type EmailStatus = Infer<typeof emailStatus>;
54
+ export type NotificationId = GenericId<"notifications">;
55
+ export interface NotificationView {
56
+ id: NotificationId;
57
+ type: string;
58
+ /** Owning module of the type (`finance`, `roles`, …). */
59
+ moduleId: string;
60
+ params: NotificationParams;
61
+ href: string | null;
62
+ readAt: number | null;
63
+ createdAt: number;
64
+ emailStatus: EmailStatus;
65
+ }
66
+ export interface NotificationPreferenceView {
67
+ type: string;
68
+ moduleId: string;
69
+ /** Fallback text; the app translates by `type`. */
70
+ description: string | null;
71
+ /** Param names the type carries. */
72
+ params: string[];
73
+ defaultChannels: {
74
+ inApp: boolean;
75
+ email: boolean;
76
+ };
77
+ /** Effective channels (the user's preference, else the defaults). */
78
+ inApp: boolean;
79
+ email: boolean;
80
+ /** The user has set a preference for this type. */
81
+ customized: boolean;
82
+ }
83
+ export interface RenderedEmail {
84
+ subject: string;
85
+ text: string;
86
+ }
87
+ /**
88
+ * Renders a notification email in the recipient's locale (profile locale, else
89
+ * the default, `lt`). Build absolute links from `href` with the app's SITE_URL.
90
+ */
91
+ export type RenderNotificationEmail = (type: string, params: NotificationParams, locale: string, context: {
92
+ href: string | null;
93
+ notificationId: string;
94
+ }) => RenderedEmail | Promise<RenderedEmail>;
95
+ export interface NotificationEmailMessage {
96
+ /** Verified address of the recipient. Never logged by core. */
97
+ to: string;
98
+ subject: string;
99
+ text: string;
100
+ type: string;
101
+ notificationId: string;
102
+ /** Stable per notification: use it as an idempotency key with the provider. */
103
+ operationId: string;
104
+ }
105
+ /** Sends one email. Throw (or return false) on failure: the row becomes `failed`. */
106
+ export type DeliverNotificationEmail = (message: NotificationEmailMessage) => Promise<void | boolean>;
107
+ /** What `_claimNotificationEmail` hands the delivery action. */
108
+ export interface NotificationEmailJob {
109
+ to: string;
110
+ locale: string;
111
+ type: string;
112
+ params: NotificationParams;
113
+ href: string | null;
114
+ operationId: string;
115
+ }
116
+ /** Most recipients of one `notify` call. Explicit `userIds` above it are VALIDATION. */
117
+ export declare const NOTIFY_MAX_RECIPIENTS = 100;
118
+ /** `unreadNotificationCount` stops counting here (show "99+"). */
119
+ export declare const NOTIFICATION_UNREAD_CAP = 100;
120
+ /** Rows one `markAllNotificationsRead` call marks; call again while `done` is false. */
121
+ export declare const NOTIFICATION_MARK_ALL_BATCH = 200;
122
+ /** Serialized params size limit (characters of JSON). */
123
+ export declare const NOTIFICATION_PARAMS_MAX = 4000;
124
+ /** Public functions in `functionsModule` (default convex/notifications.ts). */
125
+ export declare const NOTIFICATIONS_PUBLIC_FUNCTIONS: readonly ["listNotifications", "unreadNotificationCount", "markNotificationRead", "markAllNotificationsRead", "getNotificationPreferences", "setNotificationPreference"];
126
+ /** Internal functions in `functionsModule` (email delivery). */
127
+ export declare const NOTIFICATIONS_INTERNAL_FUNCTIONS: readonly ["_deliverNotificationEmail", "_claimNotificationEmail", "_recordNotificationEmail"];
128
+ /** Audit action of a preference change. */
129
+ export declare const NOTIFICATIONS_AUDIT: {
130
+ readonly preferenceUpdate: "profile.notification_preference.update";
131
+ };
132
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/notifications/contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ // Shared contract of `@digimuza/system-core/notifications` (DIG-74): tables,
2
+ // views, adapters and function names. No server-only imports: safe in Convex's
3
+ // default runtime and in the browser (types).
4
+ import { defineTable } from "convex/server";
5
+ import { v } from "convex/values";
6
+ export const emailStatus = v.union(v.literal("none"), v.literal("pending"), v.literal("sent"), v.literal("failed"), v.literal("skipped"));
7
+ /** Spread into the app schema next to `systemTables`. */
8
+ export const notificationTables = {
9
+ notifications: defineTable({
10
+ /** system-core user key of the recipient. Only they can see it. */
11
+ userId: v.string(),
12
+ /** Notification type id, e.g. `finance.invoice_awaiting_approval`. */
13
+ type: v.string(),
14
+ /** JSON params; the app renders the text (LT/EN) from them. */
15
+ params: v.any(),
16
+ /** App-relative link. */
17
+ href: v.optional(v.string()),
18
+ /** False for email-only rows (the user turned the in-app channel off): never listed. */
19
+ inApp: v.boolean(),
20
+ readAt: v.optional(v.number()),
21
+ createdAt: v.number(),
22
+ /** none: email off · pending: scheduled · sent · failed · skipped: no adapter, no verified address. */
23
+ emailStatus,
24
+ /** Operation that caused it (the business mutation's). */
25
+ operationId: v.string(),
26
+ })
27
+ .index("by_user", ["userId", "inApp", "createdAt"])
28
+ .index("by_user_unread", ["userId", "inApp", "readAt"]),
29
+ notificationPreferences: defineTable({
30
+ userId: v.string(),
31
+ type: v.string(),
32
+ inApp: v.boolean(),
33
+ email: v.boolean(),
34
+ updatedAt: v.number(),
35
+ }).index("by_user_type", ["userId", "type"]),
36
+ };
37
+ // --- Limits & function names ---------------------------------------------------------------
38
+ /** Most recipients of one `notify` call. Explicit `userIds` above it are VALIDATION. */
39
+ export const NOTIFY_MAX_RECIPIENTS = 100;
40
+ /** `unreadNotificationCount` stops counting here (show "99+"). */
41
+ export const NOTIFICATION_UNREAD_CAP = 100;
42
+ /** Rows one `markAllNotificationsRead` call marks; call again while `done` is false. */
43
+ export const NOTIFICATION_MARK_ALL_BATCH = 200;
44
+ /** Serialized params size limit (characters of JSON). */
45
+ export const NOTIFICATION_PARAMS_MAX = 4000;
46
+ /** Public functions in `functionsModule` (default convex/notifications.ts). */
47
+ export const NOTIFICATIONS_PUBLIC_FUNCTIONS = [
48
+ "listNotifications", // ({ cursor?, limit?, unreadOnly? }) → { items: NotificationView[], cursor, done }
49
+ "unreadNotificationCount", // () → number (≤ NOTIFICATION_UNREAD_CAP)
50
+ "markNotificationRead", // ({ notificationId }) → { read } (NOT_FOUND unless own)
51
+ "markAllNotificationsRead", // () → { marked, done }
52
+ "getNotificationPreferences", // () → NotificationPreferenceView[]
53
+ "setNotificationPreference", // ({ type, inApp, email }) → NotificationPreferenceView
54
+ ];
55
+ /** Internal functions in `functionsModule` (email delivery). */
56
+ export const NOTIFICATIONS_INTERNAL_FUNCTIONS = ["_deliverNotificationEmail", "_claimNotificationEmail", "_recordNotificationEmail"];
57
+ /** Audit action of a preference change. */
58
+ export const NOTIFICATIONS_AUDIT = { preferenceUpdate: "profile.notification_preference.update" };
59
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/notifications/contract.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,8CAA8C;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,CAAC,EAA8B,MAAM,eAAe,CAAA;AAG7D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;AAEzI,yDAAyD;AACzD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,aAAa,EAAE,WAAW,CAAC;QACzB,mEAAmE;QACnE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,sEAAsE;QACtE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,+DAA+D;QAC/D,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE;QACf,yBAAyB;QACzB,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5B,wFAAwF;QACxF,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;QAClB,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,uGAAuG;QACvG,WAAW;QACX,0DAA0D;QAC1D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;KACxB,CAAC;SACC,KAAK,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;SAClD,KAAK,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEzD,uBAAuB,EAAE,WAAW,CAAC;QACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;QAClB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;QAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CAC7C,CAAA;AA6ED,8FAA8F;AAE9F,wFAAwF;AACxF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAA;AACxC,kEAAkE;AAClE,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAA;AAC1C,wFAAwF;AACxF,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAA;AAC9C,yDAAyD;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAA;AAE3C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,mBAAmB,EAAE,mFAAmF;IACxG,yBAAyB,EAAE,0CAA0C;IACrE,sBAAsB,EAAE,yDAAyD;IACjF,0BAA0B,EAAE,wBAAwB;IACpD,4BAA4B,EAAE,oCAAoC;IAClE,2BAA2B,EAAE,wDAAwD;CAC7E,CAAA;AAEV,gEAAgE;AAChE,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,2BAA2B,EAAE,yBAAyB,EAAE,0BAA0B,CAAU,CAAA;AAE7I,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,gBAAgB,EAAE,wCAAwC,EAAW,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from "./contract.js";
2
+ export { defineNotifications, notificationsHook, notify, NotificationsInstall, type NotificationsHookOptions, type NotificationsOptions, type NotificationsSystem } from "./api.js";
3
+ export { defineNotificationType, NOTIFICATION_TYPE_ID, type NotificationTypeDefinition } from "../core/catalog.js";
4
+ export { notifyIfInstalled, type Notifier, type NotifyRequest, type NotifyTarget, type NotificationParams } from "../core/notify.js";
5
+ export { CORE_NOTIFICATION_TYPES } from "../core/system-modules.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAGA,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnL,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,KAAK,0BAA0B,EAAE,MAAM,oBAAoB,CAAA;AAClH,OAAO,EAAE,iBAAiB,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACpI,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA"}