feat: user to user message model. (#649)

Co-authored-by: Mo <[email protected]>
This commit is contained in:
Karol Sójko
2023-07-10 12:10:25 +02:00
committed by GitHub
co-authored by Mo
parent 2606f6d929
commit f759261919
6 changed files with 181 additions and 0 deletions
@@ -0,0 +1,17 @@
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { MessageProps } from './MessageProps'
export class Message extends Entity<MessageProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: MessageProps, id?: UniqueEntityId) {
super(props, id)
}
static create(props: MessageProps, id?: UniqueEntityId): Result<Message> {
return Result.ok<Message>(new Message(props, id))
}
}
@@ -0,0 +1,9 @@
import { Timestamps, Uuid } from '@standardnotes/domain-core'
export interface MessageProps {
recipientUuid: Uuid
senderUuid: Uuid
encryptedMessage: string
replaceabilityIdentifier: string | null
timestamps: Timestamps
}
@@ -0,0 +1,9 @@
import { Uuid } from '@standardnotes/domain-core'
import { Message } from './Message'
export interface MessageRepositoryInterface {
findByUuid: (uuid: Uuid) => Promise<Message | null>
save(message: Message): Promise<void>
remove(message: Message): Promise<void>
}
@@ -0,0 +1,45 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
@Entity({ name: 'messages' })
export class TypeORMMessage {
@PrimaryGeneratedColumn('uuid')
declare uuid: string
@Column({
name: 'recipient_uuid',
length: 36,
})
declare recipientUuid: string
@Column({
name: 'sender_uuid',
length: 36,
})
declare senderUuid: string
@Column({
name: 'encrypted_message',
type: 'text',
})
declare encryptedMessage: string
@Column({
name: 'replaceability_identifier',
type: 'varchar',
length: 255,
nullable: true,
})
declare replaceabilityIdentifier: string | null
@Column({
name: 'created_at_timestamp',
type: 'bigint',
})
declare createdAtTimestamp: number
@Column({
name: 'updated_at_timestamp',
type: 'bigint',
})
declare updatedAtTimestamp: number
}
@@ -0,0 +1,38 @@
import { Repository } from 'typeorm'
import { MapperInterface, Uuid } from '@standardnotes/domain-core'
import { MessageRepositoryInterface } from '../../Domain/Message/MessageRepositoryInterface'
import { TypeORMMessage } from './TypeORMMessage'
import { Message } from '../../Domain/Message/Message'
export class TypeORMMessageRepository implements MessageRepositoryInterface {
constructor(
private ormRepository: Repository<TypeORMMessage>,
private mapper: MapperInterface<Message, TypeORMMessage>,
) {}
async findByUuid(uuid: Uuid): Promise<Message | null> {
const persistence = await this.ormRepository
.createQueryBuilder('message')
.where('message.uuid = :uuid', {
uuid: uuid.value,
})
.getOne()
if (persistence === null) {
return null
}
return this.mapper.toDomain(persistence)
}
async remove(message: Message): Promise<void> {
await this.ormRepository.remove(this.mapper.toProjection(message))
}
async save(message: Message): Promise<void> {
const persistence = this.mapper.toProjection(message)
await this.ormRepository.save(persistence)
}
}
@@ -0,0 +1,63 @@
import { Timestamps, MapperInterface, UniqueEntityId, Uuid, Validator } from '@standardnotes/domain-core'
import { Message } from '../../Domain/Message/Message'
import { TypeORMMessage } from '../../Infra/TypeORM/TypeORMMessage'
export class MessagePersistenceMapper implements MapperInterface<Message, TypeORMMessage> {
toDomain(projection: TypeORMMessage): Message {
const recipientUuidOrError = Uuid.create(projection.recipientUuid)
if (recipientUuidOrError.isFailed()) {
throw new Error(`Failed to create message from projection: ${recipientUuidOrError.getError()}`)
}
const recipientUuid = recipientUuidOrError.getValue()
const senderUuidOrError = Uuid.create(projection.senderUuid)
if (senderUuidOrError.isFailed()) {
throw new Error(`Failed to create message from projection: ${senderUuidOrError.getError()}`)
}
const senderUuid = senderUuidOrError.getValue()
const timestampsOrError = Timestamps.create(projection.createdAtTimestamp, projection.updatedAtTimestamp)
if (timestampsOrError.isFailed()) {
throw new Error(`Failed to create notification from projection: ${timestampsOrError.getError()}`)
}
const timestamps = timestampsOrError.getValue()
const validateNotEmptyMessage = Validator.isNotEmpty(projection.encryptedMessage)
if (validateNotEmptyMessage.isFailed()) {
throw new Error(`Failed to create message from projection: ${validateNotEmptyMessage.getError()}`)
}
const messageOrError = Message.create(
{
recipientUuid,
senderUuid,
encryptedMessage: projection.encryptedMessage,
replaceabilityIdentifier: projection.replaceabilityIdentifier,
timestamps,
},
new UniqueEntityId(projection.uuid),
)
if (messageOrError.isFailed()) {
throw new Error(`Failed to create message from projection: ${messageOrError.getError()}`)
}
const message = messageOrError.getValue()
return message
}
toProjection(domain: Message): TypeORMMessage {
const typeorm = new TypeORMMessage()
typeorm.uuid = domain.id.toString()
typeorm.encryptedMessage = domain.props.encryptedMessage
typeorm.recipientUuid = domain.props.recipientUuid.value
typeorm.senderUuid = domain.props.senderUuid.value
typeorm.replaceabilityIdentifier = domain.props.replaceabilityIdentifier
typeorm.createdAtTimestamp = domain.props.timestamps.createdAt
typeorm.updatedAtTimestamp = domain.props.timestamps.updatedAt
return typeorm
}
}