/** * @module notification.create * * Factory functions and template types for creating {@link Notification} documents. * * Provides a fluent input pattern ({@link CreateNotificationTemplateInput}) that maps friendly field names * to the abbreviated Firestore fields, plus throttling support to avoid duplicate sends. */ import { type Maybe, type Milliseconds, type ModelKey } from '@dereekb/util'; import { type Notification, type NotificationDocument, type NotificationFirestoreCollections, NotificationSendType } from './notification'; import { type NotificationRecipientWithConfig } from './notification.config'; import { type NotificationTaskType, type NotificationTaskUniqueId, type NotificationTemplateType } from './notification.id'; import { type FirebaseAuthUserId, type FirestoreDocumentAccessor, type ReadFirestoreModelKeyInput, type Transaction } from '../../common'; import { type NotificationItem } from './notification.item'; /** * Template for the embedded {@link NotificationItem} within a new notification. * Omits auto-generated fields (`id`, `cat`) that are set during document creation. */ export interface CreateNotificationTemplateItem extends Omit { /** * Custom created at date for the item. */ readonly cat?: Maybe; } /** * Low-level template for creating a new {@link Notification} document. Uses Firestore field abbreviations directly. * * Prefer using {@link CreateNotificationTemplateInput} with {@link createNotificationTemplate} for a friendlier API. */ export interface CreateNotificationTemplate extends Partial> { /** * Model key of the NotificationBox's target model (not the NotificationBox's key) */ readonly notificationModel: ModelKey; /** * Item template */ readonly n: CreateNotificationTemplateItem; /** * Whether or not this notification task is "unique". * * If true, the notification task will be created using a unique key based on the target model's id and the task type. * * If a string, the notification task will be created with the provided unique key. * * Only used for Notification Tasks. */ readonly unique?: Maybe; /** * Whether or not to override an existing task with the same unique key when creating. * * Defaults to false. * * Only used for Notification Tasks. */ readonly overrideExistingTask?: Maybe; } /** * Friendly input type for creating notification templates. Maps readable field names to the abbreviated Firestore fields. * * Processed by {@link createNotificationTemplate} into a {@link CreateNotificationTemplate}. * * @example * ```ts * const template = createNotificationTemplate({ * notificationModel: 'project/abc123', * type: 'comment', * subject: 'New comment', * message: 'Someone commented on your project', * createdBy: 'user-uid-123' * }); * ``` */ export interface CreateNotificationTemplateInput extends Partial>, Partial> { /** * Model key input of the NotificationBox's target model (not the NotificationBox/key) */ readonly notificationModel: ReadFirestoreModelKeyInput; /** * Template type */ readonly type: NotificationTemplateType | NotificationTaskType; /** * Overrides st */ readonly sendType?: NotificationSendType; /** * Overrides r */ readonly recipients?: NotificationRecipientWithConfig[]; /** * Overrides cb */ readonly createdBy?: Maybe; /** * Overrides m */ readonly targetModel?: Maybe; /** * Overrides s */ readonly subject?: Maybe; /** * Overrides g */ readonly message?: Maybe; /** * Overrides d */ readonly data?: Maybe; /** * Overrides ois */ readonly explicitOptInSendOnly?: Maybe; /** * Overrides ots */ readonly explicitOptInTextSmsSendOnly?: Maybe; } /** * Converts a {@link CreateNotificationTemplateInput} into a {@link CreateNotificationTemplate} * ready for document creation. * * Maps friendly field names (`subject`, `message`, `createdBy`, etc.) to their Firestore abbreviations * and filters out null/undefined metadata values. * * @param input - friendly input with readable field names * @returns the low-level template using Firestore field abbreviations */ export declare function createNotificationTemplate(input: CreateNotificationTemplateInput): CreateNotificationTemplate; /** * Input parameters controlling whether a notification should actually be created and sent. * * Supports both an explicit toggle (`sendNotification`) and time-based throttling * to prevent duplicate sends within a configurable window. */ export interface ShouldSendCreatedNotificationInput { /** * Whether or not to actually create/save the notification. Defaults to true. */ readonly sendNotification?: Maybe; /** * Date that can be provided to throttle sending notifications. If the throttle time has not elapsed since the last send then the notification will not be sent. */ readonly sendNotificationThrottleDate?: Maybe; /** * Amount of time to throttle notifications. Only used if sendNotificationThrottleDate is provided. Defaults to 1 hour. */ readonly sendNotificationThrottleTime?: Maybe; } /** * Determines whether a notification should be created based on the explicit toggle and throttle settings. * * Returns false if `sendNotification` is explicitly false, or if the throttle window hasn't elapsed. * * @param input - the send control parameters including the toggle and throttle configuration * @returns true if the notification should be created and sent */ export declare function shouldSendCreatedNotificationInput(input: ShouldSendCreatedNotificationInput): boolean; /** * Full input for creating a {@link Notification} document, including the template, transaction context, * and collection accessors. */ export interface CreateNotificationDocumentPairInput extends ShouldSendCreatedNotificationInput { /** * Now to use when creating the notification. * * Default is the current time. */ readonly now?: Maybe; /** * Additional flag controlling whether or not to create the notification. */ readonly shouldCreateNotification?: Maybe; /** * Template */ readonly template: CreateNotificationTemplate; /** * Transaction, if available. */ readonly transaction?: Maybe; /** * Context to create the accessor from. */ readonly context?: Pick; /** * Accessor to use directly. */ readonly accessor?: FirestoreDocumentAccessor; } /** * Result of creating a notification document pair (document reference + data), before or after saving. */ export interface CreateNotificationDocumentPairResult extends Pick { /** * The notification document. */ readonly notificationDocument: NotificationDocument; /** * The notification data. */ readonly notification: Notification; /** * Whether or not the notification was created. */ readonly notificationCreated: boolean; /** * Whether or not the notification is considered a task notification. */ readonly isNotificationTask: boolean; } /** * Creates a notification document reference and builds the {@link Notification} data, but does NOT save to Firestore. * * Use {@link createNotificationDocument} to both create and save in one step. * * For unique task notifications, generates a deterministic document ID from the target model and task type. * * @param input - the creation parameters including template, context, and accessor * @returns the document reference and notification data pair, with `notificationCreated` set to false * @throws {Error} When neither an accessor nor sufficient context is provided * @throws {Error} When `unique=true` but no target model is specified */ export declare function createNotificationDocumentPair(input: CreateNotificationDocumentPairInput): CreateNotificationDocumentPairResult; /** * Internal function used by createNotificationDocument(). * * @param input - send control parameters (throttle settings, shouldCreateNotification flag) * @param pair - the document pair created by {@link createNotificationDocumentPair} * @returns the pair with `notificationCreated` updated to reflect whether the document was saved */ export declare function _createNotificationDocumentFromPair(input: Pick, pair: CreateNotificationDocumentPairResult): Promise; /** * Creates a new {@link Notification} document and saves it to Firestore. * * For unique tasks with `overrideExistingTask`, uses `set()` to replace existing documents. * Otherwise uses `create()` which fails if the document already exists. * * @param input - the creation parameters including template, context, send control settings * @returns the document pair with `notificationCreated` reflecting whether the document was saved */ export declare function createNotificationDocument(input: CreateNotificationDocumentPairInput): Promise; /** * Creates and saves a notification only if sending conditions are met (not throttled, not explicitly disabled). * * Returns `undefined` if the notification was not created. * * @param input - the creation parameters including template, context, and send control settings * @returns the document pair if the notification was created, or undefined if it was skipped */ export declare function createNotificationDocumentIfSending(input: CreateNotificationDocumentPairInput): Promise>;