This commit is contained in:
2025-12-11 11:25:22 +01:00
parent 6a427eab57
commit e4c1be628d
86 changed files with 1222 additions and 736 deletions

View File

@@ -5,6 +5,8 @@
* Immutable entity with factory methods and domain validation.
*/
import { NotificationDomainError } from '../errors/NotificationDomainError';
import type { NotificationType } from '../value-objects/NotificationType';
import type { NotificationChannel } from '../value-objects/NotificationChannel';
@@ -91,12 +93,12 @@ export class Notification {
createdAt?: Date;
urgency?: NotificationUrgency;
}): Notification {
if (!props.id) throw new Error('Notification ID is required');
if (!props.recipientId) throw new Error('Recipient ID is required');
if (!props.type) throw new Error('Notification type is required');
if (!props.title?.trim()) throw new Error('Notification title is required');
if (!props.body?.trim()) throw new Error('Notification body is required');
if (!props.channel) throw new Error('Notification channel is required');
if (!props.id) throw new NotificationDomainError('Notification ID is required');
if (!props.recipientId) throw new NotificationDomainError('Recipient ID is required');
if (!props.type) throw new NotificationDomainError('Notification type is required');
if (!props.title?.trim()) throw new NotificationDomainError('Notification title is required');
if (!props.body?.trim()) throw new NotificationDomainError('Notification body is required');
if (!props.channel) throw new NotificationDomainError('Notification channel is required');
// Modal notifications that require response start with action_required status
const defaultStatus = props.requiresResponse ? 'action_required' : 'unread';
@@ -196,7 +198,7 @@ export class Notification {
}
// Cannot dismiss action_required notifications without responding
if (this.props.requiresResponse && this.props.status === 'action_required') {
throw new Error('Cannot dismiss notification that requires response');
throw new NotificationDomainError('Cannot dismiss notification that requires response');
}
return new Notification({
...this.props,

View File

@@ -6,6 +6,7 @@
import type { NotificationType } from '../value-objects/NotificationType';
import type { NotificationChannel } from '../value-objects/NotificationChannel';
import { NotificationDomainError } from '../errors/NotificationDomainError';
import { DEFAULT_ENABLED_CHANNELS } from '../value-objects/NotificationChannel';
export interface ChannelPreference {
@@ -45,8 +46,8 @@ export class NotificationPreference {
private constructor(private readonly props: NotificationPreferenceProps) {}
static create(props: Omit<NotificationPreferenceProps, 'updatedAt'> & { updatedAt?: Date }): NotificationPreference {
if (!props.driverId) throw new Error('Driver ID is required');
if (!props.channels) throw new Error('Channel preferences are required');
if (!props.driverId) throw new NotificationDomainError('Driver ID is required');
if (!props.channels) throw new NotificationDomainError('Channel preferences are required');
return new NotificationPreference({
...props,

View File

@@ -0,0 +1,8 @@
export class NotificationDomainError extends Error {
readonly name: string = 'NotificationDomainError';
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, new.target.prototype);
}
}