@happyvertical/smrt-messages 0.51.39 → 0.52.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.
Files changed (31) hide show
  1. package/AGENTS.md +20 -0
  2. package/README.md +31 -0
  3. package/dist/chunks/{AccountCollection-DCF0TWbR.js → AccountCollection-Br2mRkSe.js} +2 -2
  4. package/dist/chunks/{AccountCollection-DCF0TWbR.js.map → AccountCollection-Br2mRkSe.js.map} +1 -1
  5. package/dist/chunks/{Email-vrwFmhSB.js → Email-C6TU_YXp.js} +3 -3
  6. package/dist/chunks/{Email-vrwFmhSB.js.map → Email-C6TU_YXp.js.map} +1 -1
  7. package/dist/chunks/{EmailFolder-DfL2gUXy.js → EmailFolder-CvGCE75K.js} +2 -2
  8. package/dist/chunks/{EmailFolder-DfL2gUXy.js.map → EmailFolder-CvGCE75K.js.map} +1 -1
  9. package/dist/chunks/{Message-CwXVgr93.js → Message-jz7qKbcY.js} +4 -4
  10. package/dist/chunks/{Message-CwXVgr93.js.map → Message-jz7qKbcY.js.map} +1 -1
  11. package/dist/chunks/{MessageCollection-BatENTTm.js → MessageCollection-B9mLJ6Jt.js} +2 -2
  12. package/dist/chunks/{MessageCollection-BatENTTm.js.map → MessageCollection-B9mLJ6Jt.js.map} +1 -1
  13. package/dist/chunks/__smrt-register__-Mwpskcnl.js +6 -0
  14. package/dist/chunks/{__smrt-register__-CQyfwBLY.js.map → __smrt-register__-Mwpskcnl.js.map} +1 -1
  15. package/dist/collections/UserNotificationCollection.d.ts +6 -0
  16. package/dist/collections/UserNotificationCollection.d.ts.map +1 -0
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +293 -41
  20. package/dist/index.js.map +1 -1
  21. package/dist/manifest.json +409 -1
  22. package/dist/models/UserNotification.d.ts +60 -0
  23. package/dist/models/UserNotification.d.ts.map +1 -0
  24. package/dist/services/UserNotificationService.d.ts +74 -0
  25. package/dist/services/UserNotificationService.d.ts.map +1 -0
  26. package/dist/smrt-knowledge.json +131 -9
  27. package/dist/ui.d.ts.map +1 -1
  28. package/dist/ui.js +3 -1
  29. package/dist/ui.js.map +1 -1
  30. package/package.json +16 -16
  31. package/dist/chunks/__smrt-register__-CQyfwBLY.js +0 -6
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-messages",
5
- "packageVersion": "0.51.39",
5
+ "packageVersion": "0.52.0",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-messages:AccountCollection": {
8
8
  "name": "accountcollection",
@@ -3418,6 +3418,156 @@
3418
3418
  },
3419
3419
  "importPath": "@happyvertical/smrt-messages"
3420
3420
  },
3421
+ "@happyvertical/smrt-messages:UserNotificationCollection": {
3422
+ "name": "usernotificationcollection",
3423
+ "className": "UserNotificationCollection",
3424
+ "qualifiedName": "@happyvertical/smrt-messages:UserNotificationCollection",
3425
+ "collection": "usernotifications",
3426
+ "filePath": "/home/runner/work/smrt/smrt/packages/messages/src/collections/UserNotificationCollection.ts",
3427
+ "packageName": "@happyvertical/smrt-messages",
3428
+ "fields": {},
3429
+ "methods": {},
3430
+ "decoratorConfig": {
3431
+ "tableName": "user_notifications",
3432
+ "api": false,
3433
+ "mcp": false,
3434
+ "cli": false
3435
+ },
3436
+ "extends": "SmrtCollection",
3437
+ "extendsTypeArg": "UserNotification",
3438
+ "exportName": "UserNotificationCollection",
3439
+ "collectionExportName": "UserNotificationCollectionCollection",
3440
+ "schema": {
3441
+ "tableName": "user_notifications",
3442
+ "ddl": "CREATE TABLE IF NOT EXISTS \"user_notifications\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"tenant_id\" UUID NOT NULL,\n \"recipient_user_id\" UUID NOT NULL,\n \"kind\" TEXT NOT NULL,\n \"title\" TEXT NOT NULL,\n \"body\" TEXT,\n \"href\" TEXT,\n \"severity\" TEXT DEFAULT 'info',\n \"source_ref\" TEXT NOT NULL,\n \"occurred_at\" TEXT,\n \"read_at\" TIMESTAMP,\n \"dismissed_at\" TIMESTAMP\n);",
3443
+ "columns": {
3444
+ "id": {
3445
+ "type": "UUID",
3446
+ "primaryKey": true,
3447
+ "referenceKind": "id",
3448
+ "notNull": true
3449
+ },
3450
+ "slug": {
3451
+ "type": "TEXT",
3452
+ "notNull": true
3453
+ },
3454
+ "context": {
3455
+ "type": "TEXT",
3456
+ "notNull": true,
3457
+ "default": ""
3458
+ },
3459
+ "created_at": {
3460
+ "type": "TIMESTAMP",
3461
+ "notNull": true,
3462
+ "default": "current_timestamp"
3463
+ },
3464
+ "updated_at": {
3465
+ "type": "TIMESTAMP",
3466
+ "notNull": true,
3467
+ "default": "current_timestamp"
3468
+ },
3469
+ "tenant_id": {
3470
+ "type": "UUID",
3471
+ "referenceKind": "tenantId",
3472
+ "notNull": true,
3473
+ "unique": false
3474
+ },
3475
+ "recipient_user_id": {
3476
+ "type": "UUID",
3477
+ "referenceKind": "crossPackageRef",
3478
+ "notNull": true,
3479
+ "unique": false
3480
+ },
3481
+ "kind": {
3482
+ "type": "TEXT",
3483
+ "notNull": true,
3484
+ "unique": false
3485
+ },
3486
+ "title": {
3487
+ "type": "TEXT",
3488
+ "notNull": true,
3489
+ "unique": false
3490
+ },
3491
+ "body": {
3492
+ "type": "TEXT",
3493
+ "notNull": false,
3494
+ "unique": false
3495
+ },
3496
+ "href": {
3497
+ "type": "TEXT",
3498
+ "notNull": false,
3499
+ "unique": false
3500
+ },
3501
+ "severity": {
3502
+ "type": "TEXT",
3503
+ "notNull": false,
3504
+ "unique": false,
3505
+ "default": "info"
3506
+ },
3507
+ "source_ref": {
3508
+ "type": "TEXT",
3509
+ "notNull": true,
3510
+ "unique": false
3511
+ },
3512
+ "occurred_at": {
3513
+ "type": "TEXT",
3514
+ "notNull": false,
3515
+ "unique": false
3516
+ },
3517
+ "read_at": {
3518
+ "type": "TIMESTAMP",
3519
+ "notNull": false,
3520
+ "unique": false
3521
+ },
3522
+ "dismissed_at": {
3523
+ "type": "TIMESTAMP",
3524
+ "notNull": false,
3525
+ "unique": false
3526
+ }
3527
+ },
3528
+ "indexes": [
3529
+ {
3530
+ "name": "user_notifications_tenant_id_recipient_user_id_idx",
3531
+ "columns": [
3532
+ "tenant_id",
3533
+ "recipient_user_id",
3534
+ "source_ref"
3535
+ ],
3536
+ "unique": true
3537
+ },
3538
+ {
3539
+ "name": "user_notifications_slug_context_idx",
3540
+ "columns": [
3541
+ "slug",
3542
+ "context"
3543
+ ]
3544
+ },
3545
+ {
3546
+ "name": "user_notifications_recipient_occurred_idx",
3547
+ "columns": [
3548
+ "tenant_id",
3549
+ "recipient_user_id",
3550
+ "occurred_at"
3551
+ ]
3552
+ },
3553
+ {
3554
+ "name": "user_notifications_tenant_id_created_at_idx",
3555
+ "columns": [
3556
+ "tenant_id",
3557
+ "created_at"
3558
+ ]
3559
+ },
3560
+ {
3561
+ "name": "user_notifications_recipient_user_id_idx",
3562
+ "columns": [
3563
+ "recipient_user_id"
3564
+ ]
3565
+ }
3566
+ ],
3567
+ "version": "0e68a388"
3568
+ },
3569
+ "importPath": "@happyvertical/smrt-messages"
3570
+ },
3421
3571
  "@happyvertical/smrt-messages:WhitelistCollection": {
3422
3572
  "name": "whitelistcollection",
3423
3573
  "className": "WhitelistCollection",
@@ -10225,6 +10375,264 @@
10225
10375
  },
10226
10376
  "importPath": "@happyvertical/smrt-messages"
10227
10377
  },
10378
+ "@happyvertical/smrt-messages:UserNotification": {
10379
+ "name": "usernotification",
10380
+ "className": "UserNotification",
10381
+ "qualifiedName": "@happyvertical/smrt-messages:UserNotification",
10382
+ "collection": "usernotifications",
10383
+ "filePath": "/home/runner/work/smrt/smrt/packages/messages/src/models/UserNotification.ts",
10384
+ "packageName": "@happyvertical/smrt-messages",
10385
+ "fields": {
10386
+ "tenantId": {
10387
+ "type": "text",
10388
+ "required": true,
10389
+ "_meta": {
10390
+ "sqlType": "UUID",
10391
+ "__tenancy": {
10392
+ "isTenantIdField": true,
10393
+ "autoFilter": true,
10394
+ "required": true,
10395
+ "autoPopulate": true,
10396
+ "nullable": false,
10397
+ "mode": "required",
10398
+ "field": "tenantId",
10399
+ "allowSuperAdminBypass": false
10400
+ }
10401
+ }
10402
+ },
10403
+ "recipientUserId": {
10404
+ "type": "crossPackageRef",
10405
+ "required": true,
10406
+ "related": "@happyvertical/smrt-users:User"
10407
+ },
10408
+ "kind": {
10409
+ "type": "text",
10410
+ "required": true,
10411
+ "_meta": {
10412
+ "required": true
10413
+ }
10414
+ },
10415
+ "title": {
10416
+ "type": "text",
10417
+ "required": true,
10418
+ "_meta": {
10419
+ "required": true
10420
+ }
10421
+ },
10422
+ "body": {
10423
+ "type": "text",
10424
+ "required": false
10425
+ },
10426
+ "href": {
10427
+ "type": "text",
10428
+ "required": false
10429
+ },
10430
+ "severity": {
10431
+ "type": "text",
10432
+ "required": false,
10433
+ "default": "info"
10434
+ },
10435
+ "sourceRef": {
10436
+ "type": "text",
10437
+ "required": true,
10438
+ "_meta": {
10439
+ "required": true
10440
+ }
10441
+ },
10442
+ "occurredAt": {
10443
+ "type": "text",
10444
+ "required": false
10445
+ },
10446
+ "readAt": {
10447
+ "type": "datetime",
10448
+ "required": false
10449
+ },
10450
+ "dismissedAt": {
10451
+ "type": "datetime",
10452
+ "required": false
10453
+ }
10454
+ },
10455
+ "methods": {},
10456
+ "decoratorConfig": {
10457
+ "tableName": "user_notifications",
10458
+ "api": false,
10459
+ "mcp": false,
10460
+ "cli": false,
10461
+ "conflictColumns": [
10462
+ "tenant_id",
10463
+ "recipient_user_id",
10464
+ "source_ref"
10465
+ ],
10466
+ "indexes": [
10467
+ {
10468
+ "name": "user_notifications_recipient_occurred_idx",
10469
+ "columns": [
10470
+ "tenantId",
10471
+ "recipientUserId",
10472
+ "occurredAt"
10473
+ ]
10474
+ }
10475
+ ],
10476
+ "tenantScoped": {
10477
+ "mode": "required"
10478
+ }
10479
+ },
10480
+ "extends": "SmrtObject",
10481
+ "exportName": "UserNotification",
10482
+ "collectionExportName": "UserNotificationCollection",
10483
+ "validationRules": [
10484
+ {
10485
+ "field": "recipientUserId",
10486
+ "rule": "required",
10487
+ "fieldType": "crossPackageRef"
10488
+ },
10489
+ {
10490
+ "field": "kind",
10491
+ "rule": "required",
10492
+ "fieldType": "text"
10493
+ },
10494
+ {
10495
+ "field": "title",
10496
+ "rule": "required",
10497
+ "fieldType": "text"
10498
+ },
10499
+ {
10500
+ "field": "sourceRef",
10501
+ "rule": "required",
10502
+ "fieldType": "text"
10503
+ }
10504
+ ],
10505
+ "schema": {
10506
+ "tableName": "user_notifications",
10507
+ "ddl": "CREATE TABLE IF NOT EXISTS \"user_notifications\" (\n \"id\" UUID PRIMARY KEY NOT NULL,\n \"slug\" TEXT NOT NULL,\n \"context\" TEXT NOT NULL DEFAULT '',\n \"created_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"updated_at\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\n \"tenant_id\" UUID NOT NULL,\n \"recipient_user_id\" UUID NOT NULL,\n \"kind\" TEXT NOT NULL,\n \"title\" TEXT NOT NULL,\n \"body\" TEXT,\n \"href\" TEXT,\n \"severity\" TEXT DEFAULT 'info',\n \"source_ref\" TEXT NOT NULL,\n \"occurred_at\" TEXT,\n \"read_at\" TIMESTAMP,\n \"dismissed_at\" TIMESTAMP\n);",
10508
+ "columns": {
10509
+ "id": {
10510
+ "type": "UUID",
10511
+ "primaryKey": true,
10512
+ "referenceKind": "id",
10513
+ "notNull": true
10514
+ },
10515
+ "slug": {
10516
+ "type": "TEXT",
10517
+ "notNull": true
10518
+ },
10519
+ "context": {
10520
+ "type": "TEXT",
10521
+ "notNull": true,
10522
+ "default": ""
10523
+ },
10524
+ "created_at": {
10525
+ "type": "TIMESTAMP",
10526
+ "notNull": true,
10527
+ "default": "current_timestamp"
10528
+ },
10529
+ "updated_at": {
10530
+ "type": "TIMESTAMP",
10531
+ "notNull": true,
10532
+ "default": "current_timestamp"
10533
+ },
10534
+ "tenant_id": {
10535
+ "type": "UUID",
10536
+ "referenceKind": "tenantId",
10537
+ "notNull": true,
10538
+ "unique": false
10539
+ },
10540
+ "recipient_user_id": {
10541
+ "type": "UUID",
10542
+ "referenceKind": "crossPackageRef",
10543
+ "notNull": true,
10544
+ "unique": false
10545
+ },
10546
+ "kind": {
10547
+ "type": "TEXT",
10548
+ "notNull": true,
10549
+ "unique": false
10550
+ },
10551
+ "title": {
10552
+ "type": "TEXT",
10553
+ "notNull": true,
10554
+ "unique": false
10555
+ },
10556
+ "body": {
10557
+ "type": "TEXT",
10558
+ "notNull": false,
10559
+ "unique": false
10560
+ },
10561
+ "href": {
10562
+ "type": "TEXT",
10563
+ "notNull": false,
10564
+ "unique": false
10565
+ },
10566
+ "severity": {
10567
+ "type": "TEXT",
10568
+ "notNull": false,
10569
+ "unique": false,
10570
+ "default": "info"
10571
+ },
10572
+ "source_ref": {
10573
+ "type": "TEXT",
10574
+ "notNull": true,
10575
+ "unique": false
10576
+ },
10577
+ "occurred_at": {
10578
+ "type": "TEXT",
10579
+ "notNull": false,
10580
+ "unique": false
10581
+ },
10582
+ "read_at": {
10583
+ "type": "TIMESTAMP",
10584
+ "notNull": false,
10585
+ "unique": false
10586
+ },
10587
+ "dismissed_at": {
10588
+ "type": "TIMESTAMP",
10589
+ "notNull": false,
10590
+ "unique": false
10591
+ }
10592
+ },
10593
+ "indexes": [
10594
+ {
10595
+ "name": "user_notifications_tenant_id_recipient_user_id_idx",
10596
+ "columns": [
10597
+ "tenant_id",
10598
+ "recipient_user_id",
10599
+ "source_ref"
10600
+ ],
10601
+ "unique": true
10602
+ },
10603
+ {
10604
+ "name": "user_notifications_slug_context_idx",
10605
+ "columns": [
10606
+ "slug",
10607
+ "context"
10608
+ ]
10609
+ },
10610
+ {
10611
+ "name": "user_notifications_recipient_occurred_idx",
10612
+ "columns": [
10613
+ "tenant_id",
10614
+ "recipient_user_id",
10615
+ "occurred_at"
10616
+ ]
10617
+ },
10618
+ {
10619
+ "name": "user_notifications_tenant_id_created_at_idx",
10620
+ "columns": [
10621
+ "tenant_id",
10622
+ "created_at"
10623
+ ]
10624
+ },
10625
+ {
10626
+ "name": "user_notifications_recipient_user_id_idx",
10627
+ "columns": [
10628
+ "recipient_user_id"
10629
+ ]
10630
+ }
10631
+ ],
10632
+ "version": "0e68a388"
10633
+ },
10634
+ "importPath": "@happyvertical/smrt-messages"
10635
+ },
10228
10636
  "@happyvertical/smrt-messages:Whitelist": {
10229
10637
  "name": "whitelist",
10230
10638
  "className": "Whitelist",
@@ -0,0 +1,60 @@
1
+ import type { SmrtObjectOptions } from '@happyvertical/smrt-core';
2
+ import '../__smrt-register__.js';
3
+ import { SmrtObject } from '@happyvertical/smrt-core';
4
+ /** How much a notification matters to its recipient. */
5
+ export type UserNotificationSeverity = 'info' | 'success' | 'warning' | 'error';
6
+ export declare const USER_NOTIFICATION_SEVERITIES: readonly UserNotificationSeverity[];
7
+ export interface UserNotificationOptions extends SmrtObjectOptions {
8
+ tenantId?: string;
9
+ recipientUserId?: string;
10
+ kind?: string;
11
+ title?: string;
12
+ body?: string;
13
+ href?: string | null;
14
+ severity?: UserNotificationSeverity;
15
+ sourceRef?: string;
16
+ occurredAt?: Date;
17
+ readAt?: Date | null;
18
+ dismissedAt?: Date | null;
19
+ }
20
+ /**
21
+ * One in-app notification for one person, with its own read state.
22
+ *
23
+ * The in-app channel of smrt-messages: where `Message` is delivered through
24
+ * an external provider, a `UserNotification` is stored for a user and shown
25
+ * by the host (a bell, a notifications page). Create, list, and change read
26
+ * state through `UserNotificationService`, which checks the recipient on
27
+ * every write; the generated REST/MCP/CLI surfaces are off because a plain
28
+ * tenant-scoped list would show every member's notifications.
29
+ *
30
+ * `sourceRef` is the dedupe key: one row per `(tenant, recipient, sourceRef)`
31
+ * (the conflict identity), so re-deriving the same event (a failed social
32
+ * post, a failed render) never notifies twice. The service generates a unique
33
+ * ref when the caller has none.
34
+ */
35
+ export declare class UserNotification extends SmrtObject {
36
+ tenantId: string;
37
+ /** The person this notification is for (`smrt-users:User`, uuid). */
38
+ recipientUserId: string;
39
+ /** Host-defined type, e.g. `social-post.failed` (used for icons/filters). */
40
+ kind: string;
41
+ /** One short plain sentence. */
42
+ title: string;
43
+ /** Optional detail line. */
44
+ body: string;
45
+ /** Where the notification leads (host-relative path or URL). */
46
+ href: string | null;
47
+ severity: UserNotificationSeverity;
48
+ /** Dedupe key, unique per tenant and recipient (see class docs). */
49
+ sourceRef: string;
50
+ /** When the underlying event happened (sort key). */
51
+ occurredAt: Date;
52
+ /** Set when the recipient has seen it. */
53
+ readAt: Date | null;
54
+ /** Set when the recipient has cleared it; dismissed rows are hidden. */
55
+ dismissedAt: Date | null;
56
+ constructor(options?: UserNotificationOptions);
57
+ get isRead(): boolean;
58
+ get isDismissed(): boolean;
59
+ }
60
+ //# sourceMappingURL=UserNotification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserNotification.d.ts","sourceRoot":"","sources":["../../src/models/UserNotification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAGlC,wDAAwD;AACxD,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhF,eAAO,MAAM,4BAA4B,EAAE,SAAS,wBAAwB,EACnC,CAAC;AAE1C,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAea,gBAAiB,SAAQ,UAAU;IAE9C,QAAQ,SAAM;IAEd,qEAAqE;IAErE,eAAe,SAAM;IAErB,6EAA6E;IAE7E,IAAI,SAAM;IAEV,gCAAgC;IAEhC,KAAK,SAAM;IAEX,4BAA4B;IAC5B,IAAI,SAAM;IAEV,gEAAgE;IAChE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE3B,QAAQ,EAAE,wBAAwB,CAAU;IAE5C,oEAAoE;IAEpE,SAAS,SAAM;IAEf,qDAAqD;IACrD,UAAU,OAAc;IAExB,0CAA0C;IAC1C,MAAM,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE3B,wEAAwE;IACxE,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;gBAEpB,OAAO,GAAE,uBAA4B;IAiBjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;CACF"}
@@ -0,0 +1,74 @@
1
+ import { type SmrtClassOptions } from '@happyvertical/smrt-core';
2
+ import { type UserNotification, type UserNotificationSeverity } from '../models/UserNotification.js';
3
+ /** What to tell one person. */
4
+ export interface UserNotificationInput {
5
+ tenantId: string;
6
+ recipientUserId: string;
7
+ /** Host-defined type, e.g. `social-post.failed`. */
8
+ kind: string;
9
+ title: string;
10
+ body?: string;
11
+ href?: string | null;
12
+ severity?: UserNotificationSeverity;
13
+ /**
14
+ * Dedupe key for the underlying event (e.g. `social-post:<id>:failed`). A
15
+ * second `notify()` with the same `(tenantId, recipientUserId, sourceRef)`
16
+ * returns the existing row untouched, read state included. Omit for
17
+ * one-off notifications; a unique ref is generated.
18
+ */
19
+ sourceRef?: string;
20
+ /** When the event happened (default: now). */
21
+ occurredAt?: Date;
22
+ }
23
+ export interface UserNotificationNotifyResult {
24
+ notification: UserNotification;
25
+ /** False when `sourceRef` matched an existing notification. */
26
+ created: boolean;
27
+ }
28
+ export interface UserNotificationListOptions {
29
+ /** Tenants to read (at least one). Each is read under its own tenant scope. */
30
+ tenantIds: readonly string[];
31
+ /** Only rows not yet read. */
32
+ unreadOnly?: boolean;
33
+ /** Include dismissed rows (default false). */
34
+ includeDismissed?: boolean;
35
+ /** Only rows that happened at or after this time. */
36
+ since?: Date;
37
+ /** Newest-first cap across all tenants (default 50, max 200). */
38
+ limit?: number;
39
+ }
40
+ export interface UserNotificationScope {
41
+ tenantId: string;
42
+ }
43
+ /**
44
+ * Creates, lists, and updates per-user notifications (`UserNotification`).
45
+ *
46
+ * The service is the authorization boundary for the model: every read and
47
+ * write is filtered to one recipient and runs under an explicit tenant
48
+ * scope. The host decides who may be notified (e.g. the poster of a failed
49
+ * social post) and passes the signed-in user's id for reads; it never lets
50
+ * a request choose another user's id.
51
+ */
52
+ export declare class UserNotificationService {
53
+ private readonly options;
54
+ constructor(options: {
55
+ db: SmrtClassOptions['db'];
56
+ });
57
+ private collection;
58
+ /** Store a notification unless its `sourceRef` already exists. */
59
+ notify(input: UserNotificationInput): Promise<UserNotificationNotifyResult>;
60
+ /** `notify()` for each recipient (duplicates in the list are ignored). */
61
+ notifyMany(recipientUserIds: readonly string[], input: Omit<UserNotificationInput, 'recipientUserId'>): Promise<UserNotificationNotifyResult[]>;
62
+ /** A user's notifications across the given tenants, newest first. */
63
+ listForUser(userId: string, options: UserNotificationListOptions): Promise<UserNotification[]>;
64
+ /** Unread, undismissed count across the given tenants. */
65
+ countUnread(userId: string, options: Pick<UserNotificationListOptions, 'tenantIds' | 'since'>): Promise<number>;
66
+ /** Mark the user's own notifications read; returns how many changed. */
67
+ markRead(userId: string, ids: readonly string[], scope: UserNotificationScope): Promise<number>;
68
+ /** Dismiss (and mark read) the user's own notifications. */
69
+ dismiss(userId: string, ids: readonly string[], scope: UserNotificationScope): Promise<number>;
70
+ /** Mark every unread notification of the user in these tenants read. */
71
+ markAllRead(userId: string, options: Pick<UserNotificationListOptions, 'tenantIds'>): Promise<number>;
72
+ private stamp;
73
+ }
74
+ //# sourceMappingURL=UserNotificationService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserNotificationService.d.ts","sourceRoot":"","sources":["../../src/services/UserNotificationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC9B,MAAM,+BAA+B,CAAC;AAEvC,+BAA+B;AAC/B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,gBAAgB,CAAC;IAC/B,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,8BAA8B;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qDAAqD;IACrD,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAuBD;;;;;;;;GAQG;AACH,qBAAa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE;QAAE,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAA;KAAE;IAEpE,OAAO,CAAC,UAAU;IAIlB,kEAAkE;IAC5D,MAAM,CACV,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,4BAA4B,CAAC;IAsDxC,0EAA0E;IACpE,UAAU,CACd,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,GACpD,OAAO,CAAC,4BAA4B,EAAE,CAAC;IAQ1C,qEAAqE;IAC/D,WAAW,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA8B9B,0DAA0D;IACpD,WAAW,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,IAAI,CAAC,2BAA2B,EAAE,WAAW,GAAG,OAAO,CAAC,GAChE,OAAO,CAAC,MAAM,CAAC;IAqBlB,wEAAwE;IAClE,QAAQ,CACZ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC;IAIlB,4DAA4D;IACtD,OAAO,CACX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC;IAIlB,wEAAwE;IAClE,WAAW,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,IAAI,CAAC,2BAA2B,EAAE,WAAW,CAAC,GACtD,OAAO,CAAC,MAAM,CAAC;YAoBJ,KAAK;CAyCpB"}