Jacob Schmidt 0d77300c22 feat: Project Journal backend monorepo
Monorepo with centralized build props, npm workspaces, LlamaSharp AI,
SQLite/SQLCipher storage, Svelte frontend, and unified smoke tests.

Co-Authored-By: Oz <oz-agent@warp.dev>
2026-03-02 20:56:26 -06:00

69 lines
2.2 KiB
C#

using System.ComponentModel.DataAnnotations;
using Journal.Core.Dtos;
using Journal.Core.Models;
using Journal.Core.Repositories;
namespace Journal.Core.Services.Conversations;
public class ConversationService(IConversationRepository repo) : IConversationService
{
private readonly IConversationRepository _repo = repo ?? throw new ArgumentNullException(nameof(repo));
private static ConversationDto MapSummary(Conversation c) => new(c.Id, c.Title, c.CreatedAt, c.UpdatedAt);
private static ConversationMessageDto MapMessage(ConversationMessage m) => new(m.Id, m.Role, m.Text, m.CreatedAt);
public List<ConversationDto> GetAll()
{
var items = _repo.GetAll();
return [.. items.Select(MapSummary)];
}
public ConversationDetailDto? GetById(Guid id)
{
var c = _repo.GetById(id);
if (c is null) return null;
var messages = _repo.GetMessages(id);
return new ConversationDetailDto(
c.Id, c.Title,
[.. messages.Select(MapMessage)],
c.CreatedAt, c.UpdatedAt);
}
public ConversationDto Create(CreateConversationDto dto)
{
ArgumentNullException.ThrowIfNull(dto);
var ctx = new ValidationContext(dto);
Validator.ValidateObject(dto, ctx, validateAllProperties: true);
var conversation = new Conversation(dto.Title);
_repo.Add(conversation);
return MapSummary(conversation);
}
public bool Update(Guid id, UpdateConversationDto dto)
{
ArgumentNullException.ThrowIfNull(dto);
if (dto.Title is not null && string.IsNullOrWhiteSpace(dto.Title))
throw new ValidationException("Title cannot be empty");
return _repo.Update(id, dto.Title?.Trim());
}
public bool Remove(Guid id) => _repo.Remove(id);
public ConversationMessageDto AddMessage(Guid conversationId, string role, string text)
{
var message = new ConversationMessage(conversationId, role, text);
_repo.AddMessage(message);
return MapMessage(message);
}
public List<ConversationMessageDto> GetMessages(Guid conversationId)
{
var messages = _repo.GetMessages(conversationId);
return [.. messages.Select(MapMessage)];
}
}