@dereekb/firebase 13.2.2 → 13.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/index.cjs.js +12893 -4062
- package/index.esm.js +12872 -4065
- package/package.json +5 -5
- package/src/lib/client/error/error.d.ts +18 -3
- package/src/lib/client/firestore/array.d.ts +16 -3
- package/src/lib/client/firestore/driver.accessor.batch.d.ts +35 -4
- package/src/lib/client/firestore/driver.accessor.create.d.ts +15 -0
- package/src/lib/client/firestore/driver.accessor.d.ts +15 -0
- package/src/lib/client/firestore/driver.accessor.default.d.ts +32 -0
- package/src/lib/client/firestore/driver.accessor.transaction.d.ts +35 -4
- package/src/lib/client/firestore/driver.d.ts +16 -0
- package/src/lib/client/firestore/driver.query.d.ts +36 -0
- package/src/lib/client/firestore/firestore.d.ts +11 -1
- package/src/lib/client/firestore/increment.d.ts +12 -3
- package/src/lib/client/function/development.function.factory.d.ts +27 -2
- package/src/lib/client/function/error.d.ts +27 -0
- package/src/lib/client/function/function.callable.d.ts +50 -5
- package/src/lib/client/function/function.factory.d.ts +70 -4
- package/src/lib/client/function/model.function.factory.d.ts +64 -9
- package/src/lib/client/storage/driver.accessor.d.ts +93 -0
- package/src/lib/client/storage/driver.d.ts +15 -0
- package/src/lib/client/storage/storage.d.ts +10 -1
- package/src/lib/common/auth/auth.context.d.ts +17 -2
- package/src/lib/common/auth/auth.d.ts +38 -9
- package/src/lib/common/auth/auth.error.d.ts +25 -0
- package/src/lib/common/auth/auth.server.error.d.ts +6 -2
- package/src/lib/common/development/function.d.ts +17 -6
- package/src/lib/common/development/function.schedule.d.ts +30 -1
- package/src/lib/common/firestore/accessor/accessor.wrap.modify.d.ts +36 -12
- package/src/lib/common/firestore/accessor/array.d.ts +14 -4
- package/src/lib/common/firestore/accessor/document.d.ts +77 -2
- package/src/lib/common/firestore/accessor/increment.d.ts +15 -3
- package/src/lib/common/firestore/collection/collection.d.ts +22 -4
- package/src/lib/common/firestore/collection/collection.util.d.ts +12 -2
- package/src/lib/common/firestore/driver/accessor.d.ts +28 -1
- package/src/lib/common/firestore/driver/batch.d.ts +6 -4
- package/src/lib/common/firestore/driver/driver.d.ts +18 -1
- package/src/lib/common/firestore/driver/query.d.ts +20 -1
- package/src/lib/common/firestore/driver/query.handler.d.ts +23 -0
- package/src/lib/common/firestore/driver/transaction.d.ts +18 -6
- package/src/lib/common/firestore/error.d.ts +16 -4
- package/src/lib/common/firestore/query/iterator.d.ts +11 -0
- package/src/lib/common/firestore/reference.d.ts +11 -6
- package/src/lib/common/firestore/snapshot/snapshot.d.ts +4 -0
- package/src/lib/common/firestore/snapshot/snapshot.field.d.ts +263 -63
- package/src/lib/common/firestore/types.d.ts +39 -1
- package/src/lib/common/firestore/util/id.batch.d.ts +55 -3
- package/src/lib/common/function/action.d.ts +35 -0
- package/src/lib/common/model/context.d.ts +11 -1
- package/src/lib/common/model/function.d.ts +45 -9
- package/src/lib/common/model/model/model.loader.d.ts +37 -0
- package/src/lib/common/model/model/model.param.d.ts +24 -2
- package/src/lib/common/model/model.service.d.ts +126 -4
- package/src/lib/common/model/permission/permission.context.d.ts +15 -0
- package/src/lib/common/model/permission/permission.d.ts +16 -0
- package/src/lib/common/model/permission/permission.service.d.ts +24 -1
- package/src/lib/common/model/permission/permission.service.grant.d.ts +72 -28
- package/src/lib/common/model/permission/permission.service.role.d.ts +15 -0
- package/src/lib/common/storage/accessor/path.model.d.ts +25 -8
- package/src/lib/common/storage/context.d.ts +23 -6
- package/src/lib/common/storage/driver/accessor.d.ts +15 -4
- package/src/lib/common/storage/driver/accessor.iterate.d.ts +31 -8
- package/src/lib/common/storage/driver/accessor.util.d.ts +13 -6
- package/src/lib/common/storage/driver/driver.d.ts +10 -1
- package/src/lib/common/storage/driver/error.d.ts +16 -0
- package/src/lib/common/storage/driver/list.d.ts +30 -0
- package/src/lib/common/storage/storage.d.ts +76 -19
- package/src/lib/common/storage/types.d.ts +23 -5
- package/src/lib/model/index.d.ts +1 -0
- package/src/lib/model/notification/notification.action.d.ts +8 -0
- package/src/lib/model/notification/notification.api.d.ts +26 -0
- package/src/lib/model/notification/notification.api.error.d.ts +15 -0
- package/src/lib/model/notification/notification.api.util.d.ts +27 -12
- package/src/lib/model/notification/notification.config.d.ts +193 -64
- package/src/lib/model/notification/notification.create.d.ts +62 -13
- package/src/lib/model/notification/notification.create.task.d.ts +25 -4
- package/src/lib/model/notification/notification.d.ts +258 -99
- package/src/lib/model/notification/notification.details.d.ts +66 -18
- package/src/lib/model/notification/notification.id.d.ts +90 -12
- package/src/lib/model/notification/notification.item.d.ts +57 -16
- package/src/lib/model/notification/notification.message.d.ts +84 -18
- package/src/lib/model/notification/notification.query.d.ts +21 -24
- package/src/lib/model/notification/notification.send.d.ts +38 -5
- package/src/lib/model/notification/notification.task.d.ts +87 -16
- package/src/lib/model/notification/notification.task.subtask.d.ts +42 -13
- package/src/lib/model/notification/notification.util.d.ts +68 -18
- package/src/lib/model/oidcmodel/index.d.ts +8 -0
- package/src/lib/model/oidcmodel/oidcmodel.action.d.ts +37 -0
- package/src/lib/model/oidcmodel/oidcmodel.api.d.ts +131 -0
- package/src/lib/model/oidcmodel/oidcmodel.d.ts +114 -0
- package/src/lib/model/oidcmodel/oidcmodel.data.d.ts +17 -0
- package/src/lib/model/oidcmodel/oidcmodel.id.d.ts +18 -0
- package/src/lib/model/oidcmodel/oidcmodel.interaction.d.ts +40 -0
- package/src/lib/model/oidcmodel/oidcmodel.interaction.oauth.d.ts +73 -0
- package/src/lib/model/oidcmodel/oidcmodel.query.d.ts +21 -0
- package/src/lib/model/storagefile/storagefile.action.d.ts +47 -0
- package/src/lib/model/storagefile/storagefile.api.d.ts +54 -4
- package/src/lib/model/storagefile/storagefile.create.d.ts +40 -3
- package/src/lib/model/storagefile/storagefile.d.ts +153 -16
- package/src/lib/model/storagefile/storagefile.file.d.ts +22 -7
- package/src/lib/model/storagefile/storagefile.group.d.ts +30 -1
- package/src/lib/model/storagefile/storagefile.group.processing.d.ts +20 -2
- package/src/lib/model/storagefile/storagefile.id.d.ts +44 -5
- package/src/lib/model/storagefile/storagefile.permission.d.ts +23 -4
- package/src/lib/model/storagefile/storagefile.query.d.ts +63 -11
- package/src/lib/model/storagefile/storagefile.task.d.ts +47 -4
- package/src/lib/model/storagefile/storagefile.upload.claims.d.ts +21 -4
- package/src/lib/model/storagefile/storagefile.upload.d.ts +41 -9
- package/src/lib/model/storagefile/storagefile.upload.determiner.d.ts +112 -20
- package/src/lib/model/storagefile/storagefile.util.d.ts +66 -3
- package/src/lib/model/system/system.action.d.ts +25 -0
- package/src/lib/model/system/system.d.ts +80 -4
- package/src/lib/model/user.d.ts +8 -2
- package/test/index.cjs.js +11168 -3295
- package/test/index.esm.js +11176 -3303
- package/test/package.json +6 -6
- package/test/src/lib/client/firebase.authorized.d.ts +18 -0
- package/test/src/lib/client/firebase.d.ts +60 -0
- package/test/src/lib/common/firebase.instance.d.ts +21 -0
- package/test/src/lib/common/firestore/firestore.d.ts +40 -0
- package/test/src/lib/common/firestore/firestore.instance.d.ts +16 -0
- package/test/src/lib/common/firestore/test.driver.accessor.d.ts +39 -2
- package/test/src/lib/common/firestore/test.driver.utility.d.ts +8 -2
- package/test/src/lib/common/firestore/test.iterator.d.ts +7 -2
- package/test/src/lib/common/mock/mock.item.collection.fixture.d.ts +29 -1
- package/test/src/lib/common/mock/mock.item.d.ts +219 -5
- package/test/src/lib/common/mock/mock.item.id.d.ts +6 -0
- package/test/src/lib/common/mock/mock.item.query.d.ts +12 -0
- package/test/src/lib/common/mock/mock.item.service.d.ts +60 -0
- package/test/src/lib/common/mock/mock.item.storage.fixture.d.ts +28 -1
- package/test/src/lib/common/storage/storage.d.ts +30 -0
- package/test/src/lib/common/storage/storage.instance.d.ts +22 -0
- package/test/src/lib/common/storage/test.driver.accessor.d.ts +7 -2
- package/index.cjs.js.map +0 -1
- package/index.esm.js.map +0 -1
|
@@ -1,12 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.details
|
|
3
|
+
*
|
|
4
|
+
* Template type metadata for the notification system. Each {@link NotificationTemplateType} is described by a
|
|
5
|
+
* {@link NotificationTemplateTypeInfo} entry that maps it to model identities, display info, and delivery rules.
|
|
6
|
+
*
|
|
7
|
+
* The {@link AppNotificationTemplateTypeInfoRecordService} provides runtime lookup of template types by model,
|
|
8
|
+
* enabling the server to discover which notification types apply to a given Firestore model.
|
|
9
|
+
*/
|
|
1
10
|
import { type Maybe, type ArrayOrValue } from '@dereekb/util';
|
|
2
11
|
import { type FirestoreModelIdentity, type ReadFirestoreModelKeyInput } from '../../common';
|
|
3
12
|
import { type NotificationTemplateType } from './notification.id';
|
|
4
13
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* For example, this model may be directly related to the identity in "notificationModelIdentity" but notifications are actually attached to the corresponding "altNotificationModelIdentity" or "altTargetModelIdentity".
|
|
14
|
+
* Alternative model identity pair for cases where notifications are attached to a different model
|
|
15
|
+
* than the one defined in {@link NotificationTemplateTypeInfoIdentityInfo.notificationModelIdentity}.
|
|
8
16
|
*
|
|
9
|
-
*
|
|
17
|
+
* For example, a notification may be defined for a "project" model but actually delivered via
|
|
18
|
+
* a "team" model's NotificationBox. The alternative model must always have a NotificationBox.
|
|
10
19
|
*/
|
|
11
20
|
export interface NotificationTemplateTypeInfoIdentityInfoAlternativeModelIdentityPair {
|
|
12
21
|
/**
|
|
@@ -19,7 +28,8 @@ export interface NotificationTemplateTypeInfoIdentityInfoAlternativeModelIdentit
|
|
|
19
28
|
readonly altTargetModelIdentity?: Maybe<FirestoreModelIdentity>;
|
|
20
29
|
}
|
|
21
30
|
/**
|
|
22
|
-
*
|
|
31
|
+
* Model identity mapping for a notification template type. Defines which Firestore models
|
|
32
|
+
* are associated with this notification type and which one owns the NotificationBox.
|
|
23
33
|
*/
|
|
24
34
|
export interface NotificationTemplateTypeInfoIdentityInfo {
|
|
25
35
|
/**
|
|
@@ -48,31 +58,37 @@ export interface NotificationTemplateTypeInfoIdentityInfo {
|
|
|
48
58
|
readonly sendToNotificationModelIdentity?: Maybe<boolean>;
|
|
49
59
|
}
|
|
50
60
|
/**
|
|
51
|
-
*
|
|
61
|
+
* Complete metadata for a notification template type. Defines display info, model associations,
|
|
62
|
+
* and delivery rules for a specific {@link NotificationTemplateType}.
|
|
52
63
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* Types are generally intended to be handled case-insensitively by notification services.
|
|
64
|
+
* Registered in the application's {@link NotificationTemplateTypeInfoRecord} and accessed at runtime
|
|
65
|
+
* via the {@link AppNotificationTemplateTypeInfoRecordService}.
|
|
56
66
|
*/
|
|
57
67
|
export interface NotificationTemplateTypeInfo extends NotificationTemplateTypeInfoIdentityInfo {
|
|
58
68
|
/**
|
|
59
|
-
*
|
|
69
|
+
* Template type identifier (e.g., `'comment'`, `'invite'`). Should be short to minimize Firestore storage.
|
|
60
70
|
*/
|
|
61
71
|
readonly type: NotificationTemplateType;
|
|
62
72
|
/**
|
|
63
|
-
*
|
|
73
|
+
* Human-readable name for display in notification preference UIs.
|
|
64
74
|
*/
|
|
65
75
|
readonly name: string;
|
|
66
76
|
/**
|
|
67
|
-
* Description of
|
|
77
|
+
* Description of what this notification type conveys, shown in preference management UIs.
|
|
68
78
|
*/
|
|
69
79
|
readonly description: string;
|
|
70
80
|
/**
|
|
71
|
-
*
|
|
81
|
+
* When true, only sends to recipients who have explicitly enabled this template type in their
|
|
82
|
+
* {@link NotificationBoxRecipientTemplateConfig}. Recipients without an explicit opt-in are skipped.
|
|
83
|
+
*
|
|
84
|
+
* Overridable per-notification via {@link Notification.ois}.
|
|
72
85
|
*/
|
|
73
86
|
readonly onlySendToExplicitlyEnabledRecipients?: boolean;
|
|
74
87
|
/**
|
|
75
|
-
*
|
|
88
|
+
* When false, sends text/SMS to all recipients regardless of explicit opt-in status
|
|
89
|
+
* (still respects explicit opt-outs).
|
|
90
|
+
*
|
|
91
|
+
* Overridable per-notification via {@link Notification.ots}.
|
|
76
92
|
*/
|
|
77
93
|
readonly onlyTextExplicitlyEnabledRecipients?: boolean;
|
|
78
94
|
}
|
|
@@ -81,18 +97,34 @@ export interface NotificationTemplateTypeInfo extends NotificationTemplateTypeIn
|
|
|
81
97
|
*/
|
|
82
98
|
export type NotificationTemplateTypeInfoRecord = Record<NotificationTemplateType, NotificationTemplateTypeInfo>;
|
|
83
99
|
/**
|
|
84
|
-
* Creates a NotificationTemplateTypeInfoRecord from
|
|
100
|
+
* Creates a {@link NotificationTemplateTypeInfoRecord} from an array of template type info entries.
|
|
101
|
+
*
|
|
102
|
+
* @throws {Error} When duplicate template types are found in the input array.
|
|
85
103
|
*
|
|
86
|
-
* @
|
|
87
|
-
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* const record = notificationTemplateTypeInfoRecord([
|
|
107
|
+
* { type: 'comment', name: 'Comment', description: 'New comment notifications', notificationModelIdentity: projectIdentity },
|
|
108
|
+
* { type: 'invite', name: 'Invite', description: 'Team invite notifications', notificationModelIdentity: teamIdentity }
|
|
109
|
+
* ]);
|
|
110
|
+
* ```
|
|
88
111
|
*/
|
|
89
112
|
export declare function notificationTemplateTypeInfoRecord(infoArray: NotificationTemplateTypeInfo[]): NotificationTemplateTypeInfoRecord;
|
|
90
113
|
/**
|
|
91
|
-
* Reference to
|
|
114
|
+
* Reference to an {@link AppNotificationTemplateTypeInfoRecordService} instance.
|
|
115
|
+
*
|
|
116
|
+
* Used for dependency injection in modules that need access to the template type registry.
|
|
92
117
|
*/
|
|
93
118
|
export interface AppNotificationTemplateTypeInfoRecordServiceRef {
|
|
94
119
|
readonly appNotificationTemplateTypeInfoRecordService: AppNotificationTemplateTypeInfoRecordService;
|
|
95
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Runtime service for looking up {@link NotificationTemplateTypeInfo} by model identity or template type.
|
|
123
|
+
*
|
|
124
|
+
* Built from a {@link NotificationTemplateTypeInfoRecord} via {@link appNotificationTemplateTypeInfoRecordService}.
|
|
125
|
+
* Provides indexed lookups for the server-side notification pipeline to discover which template types
|
|
126
|
+
* apply to a given model.
|
|
127
|
+
*/
|
|
96
128
|
export declare abstract class AppNotificationTemplateTypeInfoRecordService {
|
|
97
129
|
/**
|
|
98
130
|
* All records for this app.
|
|
@@ -147,4 +179,20 @@ export declare abstract class AppNotificationTemplateTypeInfoRecordService {
|
|
|
147
179
|
*/
|
|
148
180
|
abstract getTemplateTypeInfosForTargetModelIdentity(identity: FirestoreModelIdentity): NotificationTemplateTypeInfo[];
|
|
149
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Creates an {@link AppNotificationTemplateTypeInfoRecordService} from the given template type record.
|
|
184
|
+
*
|
|
185
|
+
* Builds internal indexes for fast lookup by notification model identity and target model identity.
|
|
186
|
+
* Handles alternative model identities defined in {@link NotificationTemplateTypeInfoIdentityInfoAlternativeModelIdentityPair}.
|
|
187
|
+
*
|
|
188
|
+
* @param appNotificationTemplateTypeInfoRecord - the complete template type registry for the application
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* const service = appNotificationTemplateTypeInfoRecordService(
|
|
193
|
+
* notificationTemplateTypeInfoRecord([commentInfo, inviteInfo])
|
|
194
|
+
* );
|
|
195
|
+
* const types = service.getTemplateTypesForNotificationModel('project/abc123');
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
150
198
|
export declare function appNotificationTemplateTypeInfoRecordService(appNotificationTemplateTypeInfoRecord: NotificationTemplateTypeInfoRecord): AppNotificationTemplateTypeInfoRecordService;
|
|
@@ -1,49 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.id
|
|
3
|
+
*
|
|
4
|
+
* ID types and generation functions for notification model documents.
|
|
5
|
+
*
|
|
6
|
+
* Notification documents use "two-way flat keys" as their document IDs. A two-way flat key
|
|
7
|
+
* encodes a hierarchical Firestore model key (e.g., `'collection/id'`) into a flat string
|
|
8
|
+
* (e.g., `'collection_id'`) that can be used as a document ID while remaining reversible
|
|
9
|
+
* back to the original key via {@link inferNotificationBoxRelatedModelKey}.
|
|
10
|
+
*
|
|
11
|
+
* This pattern allows {@link NotificationBox} and {@link NotificationSummary} documents
|
|
12
|
+
* to be stored in top-level collections while maintaining a bidirectional link to the
|
|
13
|
+
* model they represent.
|
|
14
|
+
*/
|
|
1
15
|
import { type FactoryWithRequiredInput } from '@dereekb/util';
|
|
2
16
|
import { type FirestoreModelId, type FirestoreModelKey, type FlatFirestoreModelKey, twoWayFlatFirestoreModelKey, inferKeyFromTwoWayFlatFirestoreModelKey, type FirebaseAuthUserId, type RootFirestoreModelIdentity, type FirestoreModelIdInput, type FirestoreCollectionName } from '../../common';
|
|
3
17
|
/**
|
|
4
|
-
*
|
|
18
|
+
* Document ID for a {@link NotificationBox}. Encoded as a two-way flat key of the model it represents.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const boxId: NotificationBoxId = notificationBoxIdForModel('project/abc123');
|
|
23
|
+
* // boxId === 'project_abc123'
|
|
24
|
+
* ```
|
|
5
25
|
*/
|
|
6
26
|
export type NotificationBoxId = FlatFirestoreModelKey;
|
|
27
|
+
/**
|
|
28
|
+
* Full Firestore model key path for a {@link NotificationBox} document (e.g., `'notificationBox/project_abc123'`).
|
|
29
|
+
*/
|
|
7
30
|
export type NotificationBoxKey = FirestoreModelKey;
|
|
8
31
|
/**
|
|
9
|
-
* A
|
|
32
|
+
* A box ID or collection name prefix used to exclude a user from receiving notifications.
|
|
10
33
|
*
|
|
11
|
-
*
|
|
34
|
+
* Supports prefix matching: excluding `'ab_123'` also excludes child boxes like `'ab_123_cd_456'`.
|
|
35
|
+
* Used when a user temporarily loses access to a resource and should stop receiving its notifications.
|
|
12
36
|
*
|
|
13
|
-
*
|
|
37
|
+
* @see {@link NotificationUser.x} where exclusions are stored
|
|
14
38
|
*/
|
|
15
39
|
export type NotificationBoxSendExclusion = FirestoreCollectionName | NotificationBoxId;
|
|
16
40
|
/**
|
|
17
|
-
* List of
|
|
41
|
+
* List of {@link NotificationBoxSendExclusion} entries for a user.
|
|
18
42
|
*/
|
|
19
43
|
export type NotificationBoxSendExclusionList = NotificationBoxSendExclusion[];
|
|
20
44
|
/**
|
|
21
|
-
*
|
|
45
|
+
* Converts a Firestore model key to a {@link NotificationBoxId} using two-way flat key encoding.
|
|
22
46
|
*
|
|
23
|
-
* @
|
|
24
|
-
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const boxId = notificationBoxIdForModel('project/abc123');
|
|
50
|
+
* // boxId === 'project_abc123'
|
|
51
|
+
* ```
|
|
25
52
|
*/
|
|
26
53
|
export declare const notificationBoxIdForModel: typeof twoWayFlatFirestoreModelKey;
|
|
54
|
+
/**
|
|
55
|
+
* Reverses a {@link NotificationBoxId} back to the original Firestore model key.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* const modelKey = inferNotificationBoxRelatedModelKey('project_abc123');
|
|
60
|
+
* // modelKey === 'project/abc123'
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
27
63
|
export declare const inferNotificationBoxRelatedModelKey: typeof inferKeyFromTwoWayFlatFirestoreModelKey;
|
|
64
|
+
/**
|
|
65
|
+
* Document ID for a {@link NotificationUser}. Encoded as a flat key derived from the user's auth identity.
|
|
66
|
+
*/
|
|
28
67
|
export type NotificationUserId = FlatFirestoreModelKey;
|
|
68
|
+
/**
|
|
69
|
+
* Full Firestore model key path for a {@link NotificationUser} document.
|
|
70
|
+
*/
|
|
29
71
|
export type NotificationUserKey = FirestoreModelKey;
|
|
72
|
+
/**
|
|
73
|
+
* Document ID for a {@link NotificationSummary}. Encoded as a two-way flat key of the model it represents.
|
|
74
|
+
*/
|
|
30
75
|
export type NotificationSummaryId = FlatFirestoreModelKey;
|
|
76
|
+
/**
|
|
77
|
+
* Full Firestore model key path for a {@link NotificationSummary} document.
|
|
78
|
+
*/
|
|
31
79
|
export type NotificationSummaryKey = FirestoreModelKey;
|
|
32
80
|
/**
|
|
33
|
-
*
|
|
81
|
+
* Converts a Firestore model key to a {@link NotificationSummaryId} using two-way flat key encoding.
|
|
34
82
|
*
|
|
35
|
-
* @
|
|
36
|
-
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* const summaryId = notificationSummaryIdForModel('project/abc123');
|
|
86
|
+
* // summaryId === 'project_abc123'
|
|
87
|
+
* ```
|
|
37
88
|
*/
|
|
38
89
|
export declare const notificationSummaryIdForModel: typeof twoWayFlatFirestoreModelKey;
|
|
39
90
|
/**
|
|
40
|
-
*
|
|
91
|
+
* Factory function that produces a {@link NotificationSummaryId} from a user's auth UID.
|
|
92
|
+
*
|
|
93
|
+
* Used to find the notification summary for a specific user's model identity.
|
|
41
94
|
*/
|
|
42
95
|
export type NotificationSummaryIdForUidFunction = FactoryWithRequiredInput<NotificationSummaryId, FirebaseAuthUserId>;
|
|
96
|
+
/**
|
|
97
|
+
* Creates a {@link NotificationSummaryIdForUidFunction} that generates summary IDs
|
|
98
|
+
* by combining the given user model identity with the provided UID.
|
|
99
|
+
*
|
|
100
|
+
* @param userModelIdentity - the root identity for user models (e.g., `profileIdentity`)
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const summaryIdForUid = notificationSummaryIdForUidFunctionForRootFirestoreModelIdentity(profileIdentity);
|
|
105
|
+
* const summaryId = summaryIdForUid('user-uid-123');
|
|
106
|
+
* // summaryId === 'profile_user-uid-123'
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
43
109
|
export declare function notificationSummaryIdForUidFunctionForRootFirestoreModelIdentity(userModelIdentity: RootFirestoreModelIdentity): NotificationSummaryIdForUidFunction;
|
|
110
|
+
/**
|
|
111
|
+
* Document ID for a {@link NotificationWeek} (a {@link YearWeekCode} string).
|
|
112
|
+
*/
|
|
44
113
|
export type NotificationWeekId = FirestoreModelId;
|
|
114
|
+
/**
|
|
115
|
+
* Full Firestore model key path for a {@link NotificationWeek} document.
|
|
116
|
+
*/
|
|
45
117
|
export type NotificationWeekKey = FirestoreModelKey;
|
|
118
|
+
/**
|
|
119
|
+
* Document ID for a {@link Notification}.
|
|
120
|
+
*/
|
|
46
121
|
export type NotificationId = FirestoreModelId;
|
|
122
|
+
/**
|
|
123
|
+
* Full Firestore model key path for a {@link Notification} document.
|
|
124
|
+
*/
|
|
47
125
|
export type NotificationKey = FirestoreModelKey;
|
|
48
126
|
/**
|
|
49
127
|
* Equivalent to NotificationId, but can be used to more specifically refer to a Notification with a task type.
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.item
|
|
3
|
+
*
|
|
4
|
+
* Defines the {@link NotificationItem} embedded data structure that carries notification content
|
|
5
|
+
* across multiple document types ({@link Notification}, {@link NotificationWeek}, {@link NotificationSummary}).
|
|
6
|
+
*/
|
|
1
7
|
import { type Maybe } from '@dereekb/util';
|
|
2
8
|
import { type FirebaseAuthUserId, type FirestoreModelKey, type SavedToFirestoreIfTrue } from '../../common';
|
|
3
9
|
import { type NotificationTaskType, type NotificationId, type NotificationTemplateType } from './notification.id';
|
|
4
10
|
/**
|
|
5
|
-
* Arbitrary metadata
|
|
11
|
+
* Arbitrary metadata attached to a {@link NotificationItem}. Content is defined by the concrete notification/task type.
|
|
12
|
+
*
|
|
13
|
+
* Stored directly in Firestore, so values must be Firestore-compatible (no class instances, functions, etc.).
|
|
6
14
|
*/
|
|
7
15
|
export type NotificationItemMetadata = Readonly<Record<string, any>>;
|
|
16
|
+
/**
|
|
17
|
+
* Pairs a {@link NotificationItem} with its resolved subject and message strings for display.
|
|
18
|
+
*/
|
|
8
19
|
export interface NotificationItemSubjectMessagePair<D extends NotificationItemMetadata = {}> {
|
|
9
20
|
readonly item: NotificationItem<D>;
|
|
10
21
|
readonly subject: string;
|
|
@@ -12,51 +23,67 @@ export interface NotificationItemSubjectMessagePair<D extends NotificationItemMe
|
|
|
12
23
|
readonly date: Date;
|
|
13
24
|
}
|
|
14
25
|
/**
|
|
15
|
-
*
|
|
26
|
+
* Embeddable notification content carried inside {@link Notification}, {@link NotificationWeek}, and {@link NotificationSummary} documents.
|
|
16
27
|
*
|
|
17
|
-
*
|
|
28
|
+
* Each item has a template/task type (`t`) that determines how the notification is rendered and delivered.
|
|
29
|
+
* The optional `s` (subject) and `g` (message) fields can override the template's defaults.
|
|
30
|
+
*
|
|
31
|
+
* Field abbreviations:
|
|
32
|
+
* - `cat` — created-at timestamp
|
|
33
|
+
* - `t` — template or task type identifier
|
|
34
|
+
* - `cb` — created-by user UID
|
|
35
|
+
* - `m` — target model key
|
|
36
|
+
* - `s` — subject override
|
|
37
|
+
* - `g` — message override
|
|
38
|
+
* - `d` — metadata payload
|
|
39
|
+
* - `v` — viewed/read flag
|
|
18
40
|
*/
|
|
19
41
|
export interface NotificationItem<D extends NotificationItemMetadata = {}> {
|
|
20
42
|
/**
|
|
21
|
-
* Unique identifier
|
|
43
|
+
* Unique notification item identifier.
|
|
22
44
|
*/
|
|
23
45
|
id: NotificationId;
|
|
24
46
|
/**
|
|
25
|
-
*
|
|
47
|
+
* Creation timestamp of this notification item.
|
|
26
48
|
*/
|
|
27
49
|
cat: Date;
|
|
28
50
|
/**
|
|
29
|
-
*
|
|
51
|
+
* Template type (for standard notifications) or task type (for task notifications).
|
|
52
|
+
* Determines how the notification is rendered and which handler processes it.
|
|
30
53
|
*/
|
|
31
54
|
t: NotificationTemplateType | NotificationTaskType;
|
|
32
55
|
/**
|
|
33
|
-
*
|
|
56
|
+
* UID of the user who triggered this notification, if applicable.
|
|
34
57
|
*/
|
|
35
58
|
cb?: Maybe<FirebaseAuthUserId>;
|
|
36
59
|
/**
|
|
37
|
-
* Model
|
|
60
|
+
* Model key of the target object this notification relates to.
|
|
38
61
|
*/
|
|
39
62
|
m?: Maybe<FirestoreModelKey>;
|
|
40
63
|
/**
|
|
41
|
-
* Subject
|
|
64
|
+
* Subject text override. Replaces the template's default subject when present.
|
|
42
65
|
*/
|
|
43
66
|
s?: Maybe<string>;
|
|
44
67
|
/**
|
|
45
|
-
* Message
|
|
68
|
+
* Message text override. Replaces the template's default message when present.
|
|
46
69
|
*/
|
|
47
70
|
g?: Maybe<string>;
|
|
48
71
|
/**
|
|
49
|
-
* Arbitrary metadata
|
|
50
|
-
*
|
|
51
|
-
* This is stored directly into Firestore, so be cautious about what is stored.
|
|
72
|
+
* Arbitrary metadata payload. Stored directly in Firestore — keep values serializable and small.
|
|
52
73
|
*/
|
|
53
74
|
d?: Maybe<D>;
|
|
54
75
|
/**
|
|
55
|
-
* True if
|
|
76
|
+
* Read/viewed flag. True if the recipient has seen this notification item.
|
|
56
77
|
*/
|
|
57
78
|
v?: Maybe<SavedToFirestoreIfTrue>;
|
|
58
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Firestore sub-object converter for embedding {@link NotificationItem} within parent documents.
|
|
82
|
+
*/
|
|
59
83
|
export declare const firestoreNotificationItem: import("../..").FirestoreSubObjectFieldMapFunctionsConfig<NotificationItem<{}>, Partial<import("@dereekb/util").ReplaceType<NotificationItem<{}>, import("@dereekb/util").MaybeMap<object>, any>>>;
|
|
84
|
+
/**
|
|
85
|
+
* Result of splitting {@link NotificationItem} entries into read and unread groups.
|
|
86
|
+
*/
|
|
60
87
|
export interface UnreadNotificationItemsResult<D extends NotificationItemMetadata = {}> {
|
|
61
88
|
readonly items: NotificationItem<D>[];
|
|
62
89
|
readonly considerReadIfCreatedBefore?: Maybe<Date>;
|
|
@@ -64,9 +91,23 @@ export interface UnreadNotificationItemsResult<D extends NotificationItemMetadat
|
|
|
64
91
|
readonly unread: NotificationItem<D>[];
|
|
65
92
|
}
|
|
66
93
|
/**
|
|
67
|
-
*
|
|
94
|
+
* Separates notification items into read and unread groups based on the `v` (viewed) flag
|
|
95
|
+
* and an optional cutoff date.
|
|
96
|
+
*
|
|
97
|
+
* Items are considered read if their `v` flag is true OR if they were created before the `considerReadIfCreatedBefore` date.
|
|
98
|
+
* This is used with {@link NotificationSummary.rat} to mark all older items as read.
|
|
68
99
|
*
|
|
69
|
-
* @param items
|
|
100
|
+
* @param items - notification items to classify
|
|
101
|
+
* @param considerReadIfCreatedBefore - optional cutoff date; items created at or before this date are treated as read
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* const result = unreadNotificationItems(summary.n, summary.rat);
|
|
106
|
+
* console.log(result.unread.length); // number of unread items
|
|
107
|
+
* ```
|
|
70
108
|
*/
|
|
71
109
|
export declare function unreadNotificationItems<D extends NotificationItemMetadata = {}>(items: NotificationItem<D>[], considerReadIfCreatedBefore?: Maybe<Date>): UnreadNotificationItemsResult<D>;
|
|
110
|
+
/**
|
|
111
|
+
* Sort comparator for {@link NotificationItem} arrays. Sorts ascending by creation date (`cat`).
|
|
112
|
+
*/
|
|
72
113
|
export declare const sortNotificationItemsFunction: import("@dereekb/date").SortByDateFunction<NotificationItem<any>>;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module notification.message
|
|
3
|
+
*
|
|
4
|
+
* Defines the message factory pattern for the notification system. A {@link NotificationMessageFunctionFactory}
|
|
5
|
+
* creates per-recipient {@link NotificationMessageFunction} instances that produce channel-specific content
|
|
6
|
+
* (email, text, push, summary) from a {@link NotificationItem}.
|
|
7
|
+
*
|
|
8
|
+
* The server's notification send pipeline calls these factories to expand each notification into concrete messages
|
|
9
|
+
* before dispatching them through the configured delivery channels.
|
|
10
|
+
*/
|
|
1
11
|
import { type PromiseOrValue, type Maybe, type WebsiteUrl, type NameEmailPair, type ArrayOrValue } from '@dereekb/util';
|
|
2
12
|
import { type NotificationRecipient, type NotificationRecipientWithConfig } from './notification.config';
|
|
3
13
|
import { type NotificationSendFlags, type Notification, type NotificationBox } from './notification';
|
|
@@ -5,7 +15,7 @@ import { type NotificationItem, type NotificationItemMetadata } from './notifica
|
|
|
5
15
|
import { type DocumentDataWithIdAndKey } from '../../common';
|
|
6
16
|
import { type NotificationSendEmailMessagesResult, type NotificationSendTextMessagesResult, type NotificationSendNotificationSummaryMessagesResult } from './notification.send';
|
|
7
17
|
/**
|
|
8
|
-
*
|
|
18
|
+
* Per-recipient context passed to a {@link NotificationMessageFunction} when generating message content.
|
|
9
19
|
*/
|
|
10
20
|
export interface NotificationMessageInputContext {
|
|
11
21
|
/**
|
|
@@ -116,26 +126,32 @@ export interface NotificationMessageEmailContent extends NotificationMessageCont
|
|
|
116
126
|
}
|
|
117
127
|
export interface NotificationMessageNotificationSummaryContent {
|
|
118
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Flags controlling whether a generated {@link NotificationMessage} should be delivered.
|
|
131
|
+
*/
|
|
119
132
|
export declare enum NotificationMessageFlag {
|
|
120
133
|
/**
|
|
121
|
-
*
|
|
134
|
+
* Normal delivery — message has content and should be sent.
|
|
122
135
|
*/
|
|
123
136
|
NONE = 0,
|
|
124
137
|
/**
|
|
125
|
-
*
|
|
138
|
+
* Message factory produced no content for this recipient. Delivery is skipped.
|
|
126
139
|
*/
|
|
127
140
|
NO_CONTENT = 1,
|
|
128
141
|
/**
|
|
129
|
-
*
|
|
142
|
+
* Explicitly suppress delivery. Used when the factory determines the notification should not be sent.
|
|
130
143
|
*/
|
|
131
144
|
DO_NOT_SEND = 2
|
|
132
145
|
}
|
|
133
146
|
/**
|
|
134
|
-
*
|
|
147
|
+
* Expanded notification content for a single recipient, produced by a {@link NotificationMessageFunction}.
|
|
148
|
+
*
|
|
149
|
+
* Contains the base content plus optional channel-specific overrides for email, text, and notification summary.
|
|
150
|
+
* The `flag` field can suppress delivery if the factory determined no content or opted out.
|
|
135
151
|
*/
|
|
136
152
|
export interface NotificationMessage<D extends NotificationItemMetadata = {}> {
|
|
137
153
|
/**
|
|
138
|
-
*
|
|
154
|
+
* Delivery control flag. When set to `NO_CONTENT` or `DO_NOT_SEND`, this message is skipped.
|
|
139
155
|
*/
|
|
140
156
|
readonly flag?: NotificationMessageFlag;
|
|
141
157
|
/**
|
|
@@ -165,24 +181,34 @@ export interface NotificationMessage<D extends NotificationItemMetadata = {}> {
|
|
|
165
181
|
*/
|
|
166
182
|
readonly notificationSummaryContent?: NotificationMessageNotificationSummaryContent;
|
|
167
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Configuration input for a {@link NotificationMessageFunctionFactory}, providing the notification context
|
|
186
|
+
* needed to create a per-recipient message function.
|
|
187
|
+
*/
|
|
168
188
|
export interface NotificationMessageFunctionFactoryConfig<D extends NotificationItemMetadata = {}> {
|
|
169
189
|
/**
|
|
170
|
-
*
|
|
190
|
+
* The notification item containing content and metadata.
|
|
171
191
|
*/
|
|
172
192
|
readonly item: NotificationItem<D>;
|
|
173
193
|
/**
|
|
174
|
-
* NotificationBox
|
|
194
|
+
* Parent NotificationBox context (model key for the box's associated model).
|
|
175
195
|
*/
|
|
176
196
|
readonly notificationBox: Pick<NotificationBox, 'm'>;
|
|
177
197
|
/**
|
|
178
|
-
* Full Notification
|
|
198
|
+
* Full Notification document data with its Firestore ID and key.
|
|
179
199
|
*/
|
|
180
200
|
readonly notification: DocumentDataWithIdAndKey<Notification>;
|
|
181
201
|
}
|
|
182
202
|
/**
|
|
183
|
-
*
|
|
203
|
+
* Async factory that creates a {@link NotificationMessageFunction} for a specific notification.
|
|
204
|
+
*
|
|
205
|
+
* Registered per-template-type in the application's notification configuration. The server calls this
|
|
206
|
+
* factory once per notification, then invokes the returned function once per recipient.
|
|
184
207
|
*/
|
|
185
208
|
export type NotificationMessageFunctionFactory<D extends NotificationItemMetadata = {}> = (config: NotificationMessageFunctionFactoryConfig<D>) => Promise<NotificationMessageFunction>;
|
|
209
|
+
/**
|
|
210
|
+
* Details passed to {@link NotificationMessageFunctionExtras} lifecycle callbacks after a send attempt.
|
|
211
|
+
*/
|
|
186
212
|
export interface NotificationMessageFunctionExtrasCallbackDetails {
|
|
187
213
|
readonly success: boolean;
|
|
188
214
|
readonly updatedSendFlags: NotificationSendFlags;
|
|
@@ -190,32 +216,72 @@ export interface NotificationMessageFunctionExtrasCallbackDetails {
|
|
|
190
216
|
readonly sendTextsResult?: Maybe<NotificationSendTextMessagesResult>;
|
|
191
217
|
readonly sendNotificationSummaryResult?: Maybe<NotificationSendNotificationSummaryMessagesResult>;
|
|
192
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Callback function invoked by the send pipeline with delivery results.
|
|
221
|
+
*/
|
|
193
222
|
export type NotificationMessageFunctionExtrasCallbackFunction = (callbackDetails: NotificationMessageFunctionExtrasCallbackDetails) => PromiseOrValue<unknown>;
|
|
223
|
+
/**
|
|
224
|
+
* Optional extensions attached to a {@link NotificationMessageFunction} to customize delivery behavior.
|
|
225
|
+
*
|
|
226
|
+
* Allows message factories to inject additional recipients and hook into the send lifecycle
|
|
227
|
+
* for side effects like logging, analytics, or cascading updates.
|
|
228
|
+
*/
|
|
194
229
|
export interface NotificationMessageFunctionExtras {
|
|
195
230
|
/**
|
|
196
|
-
*
|
|
231
|
+
* Additional recipients appended to every notification using this message function.
|
|
232
|
+
* Useful for always-CC recipients like admin accounts or audit logs.
|
|
197
233
|
*/
|
|
198
234
|
readonly globalRecipients?: Maybe<NotificationRecipientWithConfig[]>;
|
|
199
235
|
/**
|
|
200
|
-
* Called each
|
|
236
|
+
* Called after each send attempt (whether successful or not) with the delivery results.
|
|
201
237
|
*/
|
|
202
238
|
readonly onSendAttempted?: NotificationMessageFunctionExtrasCallbackFunction;
|
|
203
239
|
/**
|
|
204
|
-
* Called when
|
|
240
|
+
* Called when all channels have completed delivery and the notification is marked done.
|
|
205
241
|
*/
|
|
206
242
|
readonly onSendSuccess?: NotificationMessageFunctionExtrasCallbackFunction;
|
|
207
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Core message generation function that produces a {@link NotificationMessage} for a single recipient.
|
|
246
|
+
*/
|
|
208
247
|
export type NotificationMessageFunctionWithoutExtras = (inputContext: NotificationMessageInputContext) => Promise<NotificationMessage>;
|
|
209
248
|
/**
|
|
210
|
-
*
|
|
249
|
+
* Combined message function type: a callable that generates per-recipient content,
|
|
250
|
+
* plus optional {@link NotificationMessageFunctionExtras} for delivery customization.
|
|
251
|
+
*
|
|
252
|
+
* Created by {@link notificationMessageFunction} or returned from a {@link NotificationMessageFunctionFactory}.
|
|
211
253
|
*/
|
|
212
254
|
export type NotificationMessageFunction = NotificationMessageFunctionWithoutExtras & NotificationMessageFunctionExtras;
|
|
213
255
|
/**
|
|
214
|
-
* Creates a NotificationMessageFunction
|
|
256
|
+
* Creates a {@link NotificationMessageFunction} by attaching optional {@link NotificationMessageFunctionExtras}
|
|
257
|
+
* (global recipients, lifecycle callbacks) to a base message generation function.
|
|
258
|
+
*
|
|
259
|
+
* @param fn - base function that generates message content per recipient
|
|
260
|
+
* @param extras - optional delivery customization (global recipients, send callbacks)
|
|
215
261
|
*
|
|
216
|
-
* @
|
|
217
|
-
*
|
|
218
|
-
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* const msgFn = notificationMessageFunction(
|
|
265
|
+
* async (ctx) => ({
|
|
266
|
+
* inputContext: ctx,
|
|
267
|
+
* content: { title: 'New comment', openingMessage: 'Someone commented on your post' }
|
|
268
|
+
* }),
|
|
269
|
+
* { globalRecipients: [adminRecipient] }
|
|
270
|
+
* );
|
|
271
|
+
* ```
|
|
219
272
|
*/
|
|
220
273
|
export declare function notificationMessageFunction(fn: NotificationMessageFunctionWithoutExtras, extras?: NotificationMessageFunctionExtras): NotificationMessageFunction;
|
|
274
|
+
/**
|
|
275
|
+
* Creates a {@link NotificationMessageFunctionFactory} that always returns `NO_CONTENT` messages.
|
|
276
|
+
*
|
|
277
|
+
* Useful as a placeholder factory for template types that should not produce deliverable content.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```ts
|
|
281
|
+
* const factory = noContentNotificationMessageFunctionFactory();
|
|
282
|
+
* const msgFn = await factory(config);
|
|
283
|
+
* const msg = await msgFn(inputContext);
|
|
284
|
+
* // msg.flag === NotificationMessageFlag.NO_CONTENT
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
221
287
|
export declare function noContentNotificationMessageFunctionFactory<D extends NotificationItemMetadata = any>(): NotificationMessageFunctionFactory<D>;
|