@warlock.js/notifications 5.44.0 → 5.46.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 +14 -0
- package/cjs/index.cjs +112 -32
- package/cjs/index.cjs.map +1 -1
- package/esm/channels/database-channel.d.mts.map +1 -1
- package/esm/channels/database-channel.mjs +10 -2
- package/esm/channels/database-channel.mjs.map +1 -1
- package/esm/contracts/channel.contract.d.mts +3 -1
- package/esm/contracts/channel.contract.d.mts.map +1 -1
- package/esm/errors.d.mts +9 -0
- package/esm/errors.d.mts.map +1 -1
- package/esm/errors.mjs +14 -1
- package/esm/errors.mjs.map +1 -1
- package/esm/in-app/base-notifications-repository.d.mts +21 -7
- package/esm/in-app/base-notifications-repository.d.mts.map +1 -1
- package/esm/in-app/base-notifications-repository.mjs +41 -19
- package/esm/in-app/base-notifications-repository.mjs.map +1 -1
- package/esm/in-app/column-map.d.mts +8 -0
- package/esm/in-app/column-map.d.mts.map +1 -1
- package/esm/in-app/column-map.mjs +3 -0
- package/esm/in-app/column-map.mjs.map +1 -1
- package/esm/in-app/in-app.d.mts +9 -8
- package/esm/in-app/in-app.d.mts.map +1 -1
- package/esm/in-app/in-app.mjs +7 -8
- package/esm/in-app/in-app.mjs.map +1 -1
- package/esm/in-app/index.d.mts +2 -1
- package/esm/in-app/index.mjs +2 -1
- package/esm/in-app/recipient.d.mts +17 -0
- package/esm/in-app/recipient.d.mts.map +1 -0
- package/esm/in-app/recipient.mjs +27 -0
- package/esm/in-app/recipient.mjs.map +1 -0
- package/esm/index.d.mts +4 -3
- package/esm/index.mjs +3 -2
- package/esm/migration/notification-columns.d.mts +12 -1
- package/esm/migration/notification-columns.d.mts.map +1 -1
- package/esm/migration/notification-columns.mjs +13 -3
- package/esm/migration/notification-columns.mjs.map +1 -1
- package/esm/types.d.mts +13 -1
- package/esm/types.d.mts.map +1 -1
- package/llms-full.txt +11 -4
- package/llms.txt +1 -1
- package/package.json +7 -7
- package/skills/use-in-app/SKILL.md +6 -1
- package/skills/write-notification-migration/SKILL.md +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to `@warlock.js/notifications` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.46.0 - 2026-11-06
|
|
8
|
+
|
|
9
|
+
### Upgrading
|
|
10
|
+
|
|
11
|
+
- **Security: different identity types could read each other's notifications.** Recipients were keyed by a bare id, so with several auth models (staff, customers, platform users) that each count ids from 1, staff `5` and customer `5` shared one inbox. Add a recipient type column and declare it: create a nullable `recipient_type` column, backfill existing rows with the type that owned them, then set `columnMap = { recipientType: "recipient_type", … }` on the notification model. Until you declare it, behavior is unchanged (ids are the only key), which is only safe for an app with a single identity type. See "Recipient types" in the in-app store guide.
|
|
12
|
+
- Once `recipientType` is declared, rows with no type match no read until backfilled, and a bare id passed to an `inApp` method or repository method throws `RecipientTypeRequiredError`; pass the model or `{ type, id }`.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `columnMap.recipientType`: stores the recipient's identity type next to its id. The `database` channel writes it from the recipient model (an auth model's `userType`, otherwise the table name), and `notificationColumns()` emits the column.
|
|
17
|
+
- `inApp` read, count, mark-read, mark-unread, find and dismiss methods (and the matching repository methods) accept `{ type, id }` (`RecipientRef`) as well as a model or bare id, and filter by type and id when the column is declared.
|
|
18
|
+
- `RecipientTypeRequiredError`, `recipientTypeOf()`, `RecipientRef`, `RecipientInput`.
|
|
19
|
+
- `notificationColumns(…, { recipientModel })` derives the id column type from the recipient model (`integer`, or `uuid` when it sets `autoGenerateId = false`). Without it the default stays UUID.
|
|
20
|
+
|
|
7
21
|
## 5.34.3 - 2026-10-20
|
|
8
22
|
|
|
9
23
|
### Changed
|
package/cjs/index.cjs
CHANGED
|
@@ -56,6 +56,19 @@ var UnresolvableRouteError = class UnresolvableRouteError extends Error {
|
|
|
56
56
|
captureStack$1(this, UnresolvableRouteError);
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Thrown when the notification table keys recipients by type and a read or
|
|
61
|
+
* write names the recipient by a bare id. A bare id cannot say which identity
|
|
62
|
+
* type it belongs to, so serving it would let types sharing that id read each
|
|
63
|
+
* other's notifications. Pass the recipient model, or `{ type, id }`.
|
|
64
|
+
*/
|
|
65
|
+
var RecipientTypeRequiredError = class RecipientTypeRequiredError extends Error {
|
|
66
|
+
constructor(recipientId) {
|
|
67
|
+
super(`The notifications table stores a recipient type, so recipient ${recipientId ?? "(unknown)"} must be given as the model or as \`{ type, id }\`, not as a bare id.`);
|
|
68
|
+
this.name = "RecipientTypeRequiredError";
|
|
69
|
+
captureStack$1(this, RecipientTypeRequiredError);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
59
72
|
|
|
60
73
|
//#endregion
|
|
61
74
|
//#region ../../packages/notifications/src/config.ts
|
|
@@ -489,17 +502,49 @@ const notify = new Proxy({}, { get(_target, prop) {
|
|
|
489
502
|
return (to, payload, options) => notifyImpl(prop, to, payload, options);
|
|
490
503
|
} });
|
|
491
504
|
|
|
505
|
+
//#endregion
|
|
506
|
+
//#region ../../packages/notifications/src/in-app/recipient.ts
|
|
507
|
+
/**
|
|
508
|
+
* The identity type of a recipient model. Auth models name it with `userType`
|
|
509
|
+
* (the same value the auth config and token payloads use); any other model
|
|
510
|
+
* falls back to its table name.
|
|
511
|
+
*/
|
|
512
|
+
function recipientTypeOf(notifiable) {
|
|
513
|
+
const userType = notifiable.userType;
|
|
514
|
+
if (typeof userType === "string" && userType) return userType;
|
|
515
|
+
return notifiable.constructor.table;
|
|
516
|
+
}
|
|
517
|
+
/** Normalize any accepted recipient form to `{ id, type? }` (`type` absent for bare ids). */
|
|
518
|
+
function toRecipientRef(recipient) {
|
|
519
|
+
if (typeof recipient !== "object") return { id: recipient };
|
|
520
|
+
if ("get" in recipient && typeof recipient.get === "function") return {
|
|
521
|
+
id: recipient.id,
|
|
522
|
+
type: recipientTypeOf(recipient)
|
|
523
|
+
};
|
|
524
|
+
return {
|
|
525
|
+
id: recipient.id,
|
|
526
|
+
type: recipient.type
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
|
|
492
530
|
//#endregion
|
|
493
531
|
//#region ../../packages/notifications/src/channels/database-channel.ts
|
|
494
532
|
function databaseChannel(repo) {
|
|
495
533
|
return defineChannel({
|
|
496
534
|
name: "database",
|
|
497
|
-
route: (notifiable) => ({
|
|
535
|
+
route: (notifiable) => ({
|
|
536
|
+
id: notifiable.id,
|
|
537
|
+
type: recipientTypeOf(notifiable)
|
|
538
|
+
}),
|
|
498
539
|
async send({ payload, route, notifiable }) {
|
|
499
540
|
const id = typeof route === "object" ? route.id : route;
|
|
541
|
+
const type = typeof route === "object" ? route.type : void 0;
|
|
500
542
|
const { tenantColumn } = repo;
|
|
501
543
|
const tenantId = tenantColumn && notifiable ? notifiable.get(tenantColumn) : void 0;
|
|
502
|
-
await repo.createFor(
|
|
544
|
+
await repo.createFor({
|
|
545
|
+
id,
|
|
546
|
+
type
|
|
547
|
+
}, payload, tenantId);
|
|
503
548
|
}
|
|
504
549
|
});
|
|
505
550
|
}
|
|
@@ -555,13 +600,16 @@ const DEFAULT_READ_AT_COLUMN = "read_at";
|
|
|
555
600
|
function resolveColumnMap(map) {
|
|
556
601
|
const recipient = map?.recipient ?? DEFAULT_RECIPIENT_COLUMN;
|
|
557
602
|
const tenant = map?.tenant;
|
|
603
|
+
const recipientType = map?.recipientType;
|
|
558
604
|
if (!map?.readAt && !map?.isRead) return {
|
|
559
605
|
recipient,
|
|
606
|
+
recipientType,
|
|
560
607
|
tenant,
|
|
561
608
|
readAt: DEFAULT_READ_AT_COLUMN
|
|
562
609
|
};
|
|
563
610
|
return {
|
|
564
611
|
recipient,
|
|
612
|
+
recipientType,
|
|
565
613
|
tenant,
|
|
566
614
|
readAt: map.readAt,
|
|
567
615
|
isRead: map.isRead
|
|
@@ -619,7 +667,7 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
619
667
|
* direct filtering only when the model declares those columns.
|
|
620
668
|
*/
|
|
621
669
|
buildFilterBy() {
|
|
622
|
-
const { recipient, tenant, readAt, isRead } = this.columns;
|
|
670
|
+
const { recipient, recipientType, tenant, readAt, isRead } = this.columns;
|
|
623
671
|
const rules = {
|
|
624
672
|
id: "=",
|
|
625
673
|
type: "=",
|
|
@@ -631,12 +679,29 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
631
679
|
else if (readAt) query.whereNull(readAt);
|
|
632
680
|
}
|
|
633
681
|
};
|
|
682
|
+
if (recipientType) rules.recipientType = ["=", recipientType];
|
|
634
683
|
if (isRead) rules.isRead = ["=", isRead];
|
|
635
684
|
if (readAt) rules.readAt = ["=", readAt];
|
|
636
685
|
if (tenant) rules.tenant = ["=", tenant];
|
|
637
686
|
return rules;
|
|
638
687
|
}
|
|
639
688
|
/**
|
|
689
|
+
* Resolve a recipient into the logical filter keys that scope a query to it.
|
|
690
|
+
* When the model stores a recipient type the scope is `(recipientType,
|
|
691
|
+
* recipientId)`; a bare id then throws, since an id alone can't say which
|
|
692
|
+
* identity type it belongs to. Without a type column the scope is the id
|
|
693
|
+
* alone and any type on the recipient is ignored.
|
|
694
|
+
*/
|
|
695
|
+
scopeOf(recipient) {
|
|
696
|
+
const { id, type } = toRecipientRef(recipient);
|
|
697
|
+
if (!this.columns.recipientType) return { recipientId: id };
|
|
698
|
+
if (!type) throw new RecipientTypeRequiredError(id);
|
|
699
|
+
return {
|
|
700
|
+
recipientId: id,
|
|
701
|
+
recipientType: type
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
640
705
|
* Translate an object keyed by LOGICAL names into one keyed by PHYSICAL
|
|
641
706
|
* columns, using `filterBy` as the lookup. Keys with no `[op, column]` tuple
|
|
642
707
|
* (e.g. `title`, `body`, `payload`, `type`, `id`) pass through unchanged —
|
|
@@ -665,10 +730,12 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
665
730
|
* the recipient column directly.
|
|
666
731
|
*/
|
|
667
732
|
stripServerOwnedKeys(input) {
|
|
668
|
-
const { recipient, tenant, readAt, isRead } = this.columns;
|
|
733
|
+
const { recipient, recipientType, tenant, readAt, isRead } = this.columns;
|
|
669
734
|
const serverOwned = /* @__PURE__ */ new Set([
|
|
670
735
|
"id",
|
|
671
736
|
"recipientId",
|
|
737
|
+
"recipientType",
|
|
738
|
+
recipientType,
|
|
672
739
|
"tenant",
|
|
673
740
|
"readAt",
|
|
674
741
|
"isRead",
|
|
@@ -692,15 +759,16 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
692
759
|
* the existing row instead of inserting a duplicate. A unique index on the
|
|
693
760
|
* key is the backstop for the rare insert race (we re-fetch on conflict).
|
|
694
761
|
*/
|
|
695
|
-
async createFor(
|
|
762
|
+
async createFor(recipient, input, tenantId) {
|
|
696
763
|
const { idempotencyKey } = input;
|
|
764
|
+
const scope = this.scopeOf(recipient);
|
|
697
765
|
if (idempotencyKey) {
|
|
698
|
-
const existing = await this.firstByIdempotencyKey(
|
|
766
|
+
const existing = await this.firstByIdempotencyKey(scope, idempotencyKey);
|
|
699
767
|
if (existing) return existing;
|
|
700
768
|
}
|
|
701
769
|
const row = {
|
|
702
770
|
...this.stripServerOwnedKeys(input),
|
|
703
|
-
|
|
771
|
+
...scope
|
|
704
772
|
};
|
|
705
773
|
if (this.columns.isRead) row.isRead = false;
|
|
706
774
|
if (this.columns.tenant && tenantId !== void 0) row.tenant = tenantId;
|
|
@@ -708,7 +776,7 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
708
776
|
return await this.create(this.toRow(row));
|
|
709
777
|
} catch (error) {
|
|
710
778
|
if (idempotencyKey) {
|
|
711
|
-
const existing = await this.firstByIdempotencyKey(
|
|
779
|
+
const existing = await this.firstByIdempotencyKey(scope, idempotencyKey);
|
|
712
780
|
if (existing) return existing;
|
|
713
781
|
}
|
|
714
782
|
throw error;
|
|
@@ -719,8 +787,8 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
719
787
|
* for the Phase-2 `Channel.sendMany` fan-out hook; not on the per-recipient
|
|
720
788
|
* send path yet.
|
|
721
789
|
*/
|
|
722
|
-
createManyFor(
|
|
723
|
-
return Promise.all(
|
|
790
|
+
createManyFor(recipients, input, tenantId) {
|
|
791
|
+
return Promise.all(recipients.map((recipient) => this.createFor(recipient, input, tenantId)));
|
|
724
792
|
}
|
|
725
793
|
/**
|
|
726
794
|
* Mark rows read — recipient-scoped. `id` omitted → all unread rows for the
|
|
@@ -728,14 +796,14 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
728
796
|
* to unread so a re-mark never overwrites an earlier `read_at` timestamp.
|
|
729
797
|
* Sets whichever read-state column(s) the model declares.
|
|
730
798
|
*/
|
|
731
|
-
markRead(
|
|
799
|
+
markRead(recipient, id) {
|
|
732
800
|
const { isRead, readAt } = this.columns;
|
|
733
801
|
const unreadScope = isRead ? { isRead: false } : { readAt: null };
|
|
734
802
|
const data = {};
|
|
735
803
|
if (isRead) data.isRead = true;
|
|
736
804
|
if (readAt) data.readAt = /* @__PURE__ */ new Date();
|
|
737
805
|
return this.updateMany(this.toRow({
|
|
738
|
-
|
|
806
|
+
...this.scopeOf(recipient),
|
|
739
807
|
...unreadScope,
|
|
740
808
|
...id !== void 0 ? { id } : {}
|
|
741
809
|
}), this.toRow(data));
|
|
@@ -744,20 +812,20 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
744
812
|
* Inverse of `markRead`, same recipient-scoping. No unread scope needed —
|
|
745
813
|
* clearing the read-state of an already-unread row is a no-op.
|
|
746
814
|
*/
|
|
747
|
-
markUnread(
|
|
815
|
+
markUnread(recipient, id) {
|
|
748
816
|
const { isRead, readAt } = this.columns;
|
|
749
817
|
const data = {};
|
|
750
818
|
if (isRead) data.isRead = false;
|
|
751
819
|
if (readAt) data.readAt = null;
|
|
752
820
|
return this.updateMany(this.toRow({
|
|
753
|
-
|
|
821
|
+
...this.scopeOf(recipient),
|
|
754
822
|
...id !== void 0 ? { id } : {}
|
|
755
823
|
}), this.toRow(data));
|
|
756
824
|
}
|
|
757
825
|
/** Find one row for a recipient (read path — `filterBy` maps the keys). */
|
|
758
|
-
findFor(
|
|
826
|
+
findFor(recipient, id) {
|
|
759
827
|
return this.first({
|
|
760
|
-
|
|
828
|
+
...this.scopeOf(recipient),
|
|
761
829
|
id
|
|
762
830
|
});
|
|
763
831
|
}
|
|
@@ -765,16 +833,16 @@ var BaseNotificationsRepository = class extends _warlock_js_core.RepositoryManag
|
|
|
765
833
|
* Delete rows — recipient-scoped. `id` omitted → clear all for the
|
|
766
834
|
* recipient; `id` given → that one row.
|
|
767
835
|
*/
|
|
768
|
-
deleteFor(
|
|
836
|
+
deleteFor(recipient, id) {
|
|
769
837
|
return this.deleteMany(this.toRow({
|
|
770
|
-
|
|
838
|
+
...this.scopeOf(recipient),
|
|
771
839
|
...id !== void 0 ? { id } : {}
|
|
772
840
|
}));
|
|
773
841
|
}
|
|
774
|
-
/** Read path — `filterBy` maps `recipientId`/`idempotencyKey` to columns. */
|
|
775
|
-
firstByIdempotencyKey(
|
|
842
|
+
/** Read path — `filterBy` maps `recipientId`/`recipientType`/`idempotencyKey` to columns. */
|
|
843
|
+
firstByIdempotencyKey(scope, idempotencyKey) {
|
|
776
844
|
return this.first({
|
|
777
|
-
|
|
845
|
+
...scope,
|
|
778
846
|
idempotencyKey
|
|
779
847
|
});
|
|
780
848
|
}
|
|
@@ -847,7 +915,6 @@ var DatabaseNotification = class extends _warlock_js_cascade.Model {
|
|
|
847
915
|
|
|
848
916
|
//#endregion
|
|
849
917
|
//#region ../../packages/notifications/src/in-app/in-app.ts
|
|
850
|
-
const idOf = (recipient) => typeof recipient === "object" ? recipient.id : recipient;
|
|
851
918
|
var InApp = class {
|
|
852
919
|
repo;
|
|
853
920
|
/**
|
|
@@ -866,14 +933,14 @@ var InApp = class {
|
|
|
866
933
|
list(recipient, options) {
|
|
867
934
|
return this.repository.list({
|
|
868
935
|
...options,
|
|
869
|
-
|
|
936
|
+
...this.repository.scopeOf(recipient)
|
|
870
937
|
});
|
|
871
938
|
}
|
|
872
939
|
/** Unread-only list — common case for badges + dashboards. */
|
|
873
940
|
listUnread(recipient, options) {
|
|
874
941
|
return this.repository.list({
|
|
875
942
|
...options,
|
|
876
|
-
|
|
943
|
+
...this.repository.scopeOf(recipient),
|
|
877
944
|
unread: true
|
|
878
945
|
});
|
|
879
946
|
}
|
|
@@ -883,25 +950,25 @@ var InApp = class {
|
|
|
883
950
|
*/
|
|
884
951
|
countUnread(recipient) {
|
|
885
952
|
return this.repository.countCached({
|
|
886
|
-
|
|
953
|
+
...this.repository.scopeOf(recipient),
|
|
887
954
|
unread: true
|
|
888
955
|
});
|
|
889
956
|
}
|
|
890
957
|
/** Find one notification for a recipient — for a detail view. */
|
|
891
958
|
find(recipient, id) {
|
|
892
|
-
return this.repository.findFor(
|
|
959
|
+
return this.repository.findFor(recipient, id);
|
|
893
960
|
}
|
|
894
961
|
/** Mark read — `id` omitted = all unread for this recipient. */
|
|
895
962
|
markAsRead(recipient, id) {
|
|
896
|
-
return this.repository.markRead(
|
|
963
|
+
return this.repository.markRead(recipient, id);
|
|
897
964
|
}
|
|
898
965
|
/** Mark unread — same recipient-scoping. */
|
|
899
966
|
markAsUnread(recipient, id) {
|
|
900
|
-
return this.repository.markUnread(
|
|
967
|
+
return this.repository.markUnread(recipient, id);
|
|
901
968
|
}
|
|
902
969
|
/** Delete/dismiss — `id` omitted = clear all for this recipient. */
|
|
903
970
|
dismiss(recipient, id) {
|
|
904
|
-
return this.repository.deleteFor(
|
|
971
|
+
return this.repository.deleteFor(recipient, id);
|
|
905
972
|
}
|
|
906
973
|
};
|
|
907
974
|
/** Single in-app facade — bound at boot via `inApp.configure(...)`. */
|
|
@@ -916,6 +983,10 @@ const inApp = new InApp();
|
|
|
916
983
|
* agree by construction. The stable lexical columns (`type`, `title`, `body`,
|
|
917
984
|
* `payload`, `idempotency_key`) keep fixed names.
|
|
918
985
|
*
|
|
986
|
+
* `columnMap.recipientType` adds the recipient-type string column (see
|
|
987
|
+
* `NotificationColumnMap`). For a table created earlier, add that column with a
|
|
988
|
+
* migration instead of re-creating the table.
|
|
989
|
+
*
|
|
919
990
|
* Read-state follows the map's presence rules (see `NotificationColumnMap`):
|
|
920
991
|
* `readAt` → a nullable timestamp, `isRead` → an indexed boolean, both → both.
|
|
921
992
|
*
|
|
@@ -936,8 +1007,9 @@ const inApp = new InApp();
|
|
|
936
1007
|
*/
|
|
937
1008
|
function notificationColumns(modelOrOptions, options) {
|
|
938
1009
|
const model = isNotificationColumnsOptions(modelOrOptions) ? void 0 : modelOrOptions;
|
|
939
|
-
const
|
|
940
|
-
const
|
|
1010
|
+
const resolvedOptions = isNotificationColumnsOptions(modelOrOptions) ? modelOrOptions : options;
|
|
1011
|
+
const idType = resolvedOptions?.idType ?? deriveIdType(resolvedOptions?.recipientModel);
|
|
1012
|
+
const { recipient, recipientType, tenant, readAt, isRead } = resolveColumnMap(model?.columnMap);
|
|
941
1013
|
const idColumn = getIdColumn(idType);
|
|
942
1014
|
const columns = {
|
|
943
1015
|
[recipient]: idColumn().index().notNullable(),
|
|
@@ -946,6 +1018,7 @@ function notificationColumns(modelOrOptions, options) {
|
|
|
946
1018
|
body: (0, _warlock_js_cascade.text)().nullable(),
|
|
947
1019
|
payload: (0, _warlock_js_cascade.json)().nullable()
|
|
948
1020
|
};
|
|
1021
|
+
if (recipientType) columns[recipientType] = (0, _warlock_js_cascade.string)().index().notNullable();
|
|
949
1022
|
if (readAt) columns[readAt] = (0, _warlock_js_cascade.timestamp)().nullable();
|
|
950
1023
|
if (isRead) columns[isRead] = (0, _warlock_js_cascade.boolCol)().default(false).index();
|
|
951
1024
|
if (tenant) columns[tenant] = idColumn().index().notNullable();
|
|
@@ -953,7 +1026,7 @@ function notificationColumns(modelOrOptions, options) {
|
|
|
953
1026
|
return columns;
|
|
954
1027
|
}
|
|
955
1028
|
function isNotificationColumnsOptions(value) {
|
|
956
|
-
return "idType" in (value ?? {});
|
|
1029
|
+
return "idType" in (value ?? {}) || "recipientModel" in (value ?? {});
|
|
957
1030
|
}
|
|
958
1031
|
function getIdColumn(idType) {
|
|
959
1032
|
switch (idType) {
|
|
@@ -963,6 +1036,10 @@ function getIdColumn(idType) {
|
|
|
963
1036
|
default: return _warlock_js_cascade.uuid;
|
|
964
1037
|
}
|
|
965
1038
|
}
|
|
1039
|
+
function deriveIdType(recipientModel) {
|
|
1040
|
+
if (!recipientModel || recipientModel.autoGenerateId === false) return "uuid";
|
|
1041
|
+
return "integer";
|
|
1042
|
+
}
|
|
966
1043
|
|
|
967
1044
|
//#endregion
|
|
968
1045
|
//#region ../../packages/notifications/src/queue/load-herald.ts
|
|
@@ -1164,6 +1241,7 @@ exports.NOTIFICATION_JOB_NAME = NOTIFICATION_JOB_NAME;
|
|
|
1164
1241
|
exports.NoQueueDispatcherError = NoQueueDispatcherError;
|
|
1165
1242
|
exports.NotificationsNotConfiguredError = NotificationsNotConfiguredError;
|
|
1166
1243
|
exports.QueuePackageNotInstalledError = QueuePackageNotInstalledError;
|
|
1244
|
+
exports.RecipientTypeRequiredError = RecipientTypeRequiredError;
|
|
1167
1245
|
exports.UnresolvableRouteError = UnresolvableRouteError;
|
|
1168
1246
|
exports.bullmqQueue = bullmqQueue;
|
|
1169
1247
|
exports.databaseChannel = databaseChannel;
|
|
@@ -1177,8 +1255,10 @@ exports.mailChannel = mailChannel;
|
|
|
1177
1255
|
exports.notificationColumns = notificationColumns;
|
|
1178
1256
|
exports.notifications = notifications;
|
|
1179
1257
|
exports.notify = notify;
|
|
1258
|
+
exports.recipientTypeOf = recipientTypeOf;
|
|
1180
1259
|
exports.resetNotificationConfig = resetNotificationConfig;
|
|
1181
1260
|
exports.resolveColumnMap = resolveColumnMap;
|
|
1182
1261
|
exports.setNotificationConfig = setNotificationConfig;
|
|
1183
1262
|
exports.startNotificationsWorker = startNotificationsWorker;
|
|
1263
|
+
exports.toRecipientRef = toRecipientRef;
|
|
1184
1264
|
//# sourceMappingURL=index.cjs.map
|