Browse Source

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

Co-authored-by: Mo <mo@standardnotes.com>
Karol Sójko 1 year ago
parent
commit
f759261919

+ 17 - 0
packages/syncing-server/src/Domain/Message/Message.ts

@@ -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))
+  }
+}

+ 9 - 0
packages/syncing-server/src/Domain/Message/MessageProps.ts

@@ -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
+}

+ 9 - 0
packages/syncing-server/src/Domain/Message/MessageRepositoryInterface.ts

@@ -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>
+}

+ 45 - 0
packages/syncing-server/src/Infra/TypeORM/TypeORMMessage.ts

@@ -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
+}

+ 38 - 0
packages/syncing-server/src/Infra/TypeORM/TypeORMMessageRepository.ts

@@ -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)
+  }
+}

+ 63 - 0
packages/syncing-server/src/Mapping/Persistence/MessagePersistenceMapper.ts

@@ -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
+  }
+}