From 647abac4fa1323a1cfc83ed9054436357b76934c Mon Sep 17 00:00:00 2001 From: John Brunton Date: Mon, 12 Aug 2024 22:36:52 +0100 Subject: [PATCH] refactor: extract message parser --- .../api/src/app/messages/messages.service.ts | 8 +++-- .../usecases/messages/parse-message.spec.ts | 36 +++++++++++++++++++ .../usecases}/messages/parse-message.ts | 25 ++++++++----- 3 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 services/api/src/domain/usecases/messages/parse-message.spec.ts rename services/api/src/{app => domain/usecases}/messages/parse-message.ts (64%) diff --git a/services/api/src/app/messages/messages.service.ts b/services/api/src/app/messages/messages.service.ts index c29fed94..ebff4649 100644 --- a/services/api/src/app/messages/messages.service.ts +++ b/services/api/src/app/messages/messages.service.ts @@ -1,9 +1,9 @@ import { HttpException, Injectable } from '@nestjs/common'; import { CreateMessageDto } from './dto/create-message.dto'; -import { isCommand, parseMessage } from './parse-message'; import { User, systemUser } from '@entities/user.entity'; import { SendMessageUseCase } from '@usecases/messages/send'; import { CommandService } from '@app/messages/command.service'; +import { isCommand, parseMessage } from '@usecases/messages/parse-message'; @Injectable() export class MessagesService { @@ -16,7 +16,11 @@ export class MessagesService { incoming: CreateMessageDto, authenticatedUser: User, ): Promise { - const message = parseMessage(incoming, authenticatedUser); + const message = parseMessage({ + ...incoming, + authorId: authenticatedUser.id, + }); + try { if (isCommand(message)) { await this.command.exec(message, authenticatedUser); diff --git a/services/api/src/domain/usecases/messages/parse-message.spec.ts b/services/api/src/domain/usecases/messages/parse-message.spec.ts new file mode 100644 index 00000000..dcda6ea2 --- /dev/null +++ b/services/api/src/domain/usecases/messages/parse-message.spec.ts @@ -0,0 +1,36 @@ +import { parseMessage } from './parse-message'; + +describe('parseMessage', () => { + const roomId = 'room-id'; + const authorId = 'user-id'; + + it('parses commands', () => { + expect( + parseMessage({ content: '/lorem 3 words', roomId, authorId }), + ).toEqual({ + canonicalInput: '/lorem 3 words', + roomId, + tokens: ['lorem', '3', 'words'], + }); + }); + + it('ignores excess whitespace in commands', () => { + expect( + parseMessage({ content: '/lorem 3 words', roomId, authorId }), + ).toEqual({ + canonicalInput: '/lorem 3 words', + roomId, + tokens: ['lorem', '3', 'words'], + }); + }); + + it('parses normal messages', () => { + expect( + parseMessage({ content: 'Hello, World!', roomId, authorId }), + ).toEqual({ + content: 'Hello, World!', + roomId, + authorId, + }); + }); +}); diff --git a/services/api/src/app/messages/parse-message.ts b/services/api/src/domain/usecases/messages/parse-message.ts similarity index 64% rename from services/api/src/app/messages/parse-message.ts rename to services/api/src/domain/usecases/messages/parse-message.ts index 806c6b74..bc0cc7ae 100644 --- a/services/api/src/app/messages/parse-message.ts +++ b/services/api/src/domain/usecases/messages/parse-message.ts @@ -1,7 +1,5 @@ import { Command } from '@entities/command.entity'; import { DraftMessage } from '@entities/message.entity'; -import { User } from '@entities/user.entity'; -import { CreateMessageDto } from 'src/app/messages/dto/create-message.dto'; export type ParsedMessage = DraftMessage | Command; @@ -9,12 +7,23 @@ export const isCommand = (message: ParsedMessage): message is Command => { return (message as Command).tokens !== undefined; }; -export const parseMessage = ( - { content, roomId }: CreateMessageDto, - authenticatedUser: User, -): ParsedMessage => { +type ParseMessageParams = { + content: string; + roomId: string; + authorId: string; +}; + +export const parseMessage = ({ + content, + roomId, + authorId, +}: ParseMessageParams): ParsedMessage => { if (content.startsWith('/')) { - const tokens = content.slice(1).split(' '); + const tokens = content + .slice(1) + .split(' ') + .filter((token) => token.length > 0); + const canonicalInput = `/${tokens.join(' ')}`; const command: Command = { @@ -29,7 +38,7 @@ export const parseMessage = ( const message: ParsedMessage = { content, roomId, - authorId: authenticatedUser.id, + authorId, }; return message;