- Fragment model with validation, DTOs (immutable records), repository, service - Sidecar stdin/stdout JSON protocol for Tauri integration - DI wiring via ServiceCollectionExtensions - Scaffolded Journal.Api (not yet wired) Co-Authored-By: Warp <agent@warp.dev>
127 lines
4.2 KiB
C#
127 lines
4.2 KiB
C#
using Journal.Core.Models;
|
|
|
|
namespace Journal.Core.Repositories;
|
|
|
|
public class InMemoryFragmentRepository : IFragmentRepository
|
|
{
|
|
private readonly List<Fragment> _store = [];
|
|
private readonly Lock _lock = new();
|
|
|
|
public Task<List<Fragment>> GetAllAsync()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return Task.FromResult(_store.ToList());
|
|
}
|
|
}
|
|
|
|
public Task<Fragment?> GetByIdAsync(Guid id)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return Task.FromResult(_store.FirstOrDefault(f => f.Id == id));
|
|
}
|
|
}
|
|
|
|
public Task AddAsync(Fragment fragment)
|
|
{
|
|
if (fragment is null) throw new ArgumentNullException(nameof(fragment));
|
|
lock (_lock)
|
|
{
|
|
if (fragment.Tags != null)
|
|
{
|
|
fragment.Tags = [.. fragment.Tags
|
|
.Where(t => !string.IsNullOrWhiteSpace(t))
|
|
.Select(t => t!.Trim())];
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(fragment.Type)) fragment.Type = fragment.Type.Trim();
|
|
if (!string.IsNullOrWhiteSpace(fragment.Description)) fragment.Description = fragment.Description.Trim();
|
|
|
|
_store.Add(fragment);
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<bool> RemoveAsync(Guid id)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
var item = _store.FirstOrDefault(f => f.Id == id);
|
|
if (item is null) return Task.FromResult(false);
|
|
return Task.FromResult(_store.Remove(item));
|
|
}
|
|
}
|
|
|
|
public Task<bool> UpdateAsync(Guid id, string? type = null, string? description = null, IEnumerable<string>? tags = null, DateTimeOffset? time = null)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
var item = _store.FirstOrDefault(f => f.Id == id);
|
|
if (item is null) return Task.FromResult(false);
|
|
|
|
if (type != null)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Type cannot be empty", nameof(type));
|
|
item.Type = type.Trim();
|
|
}
|
|
|
|
if (description != null)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(description)) throw new ArgumentException("Description cannot be empty", nameof(description));
|
|
item.Description = description.Trim();
|
|
}
|
|
|
|
if (tags != null)
|
|
{
|
|
item.Tags = [.. tags
|
|
.Where(t => !string.IsNullOrWhiteSpace(t))
|
|
.Select(t => t!.Trim())];
|
|
}
|
|
|
|
if (time.HasValue)
|
|
item.Time = time.Value;
|
|
|
|
return Task.FromResult(true);
|
|
}
|
|
}
|
|
|
|
public Task<List<Fragment>> GetByTagAsync(string tag)
|
|
{
|
|
var q = tag?.Trim();
|
|
if (string.IsNullOrWhiteSpace(q)) return Task.FromResult(new List<Fragment>());
|
|
lock (_lock)
|
|
{
|
|
return Task.FromResult(_store.Where(f => f.Tags?.Any(t => !string.IsNullOrWhiteSpace(t) && t.Contains(q, StringComparison.OrdinalIgnoreCase)) == true).ToList());
|
|
}
|
|
}
|
|
|
|
public Task<List<Fragment>> GetByTypeAsync(string type)
|
|
{
|
|
var q = type?.Trim();
|
|
if (string.IsNullOrWhiteSpace(q)) return Task.FromResult(new List<Fragment>());
|
|
lock (_lock)
|
|
{
|
|
return Task.FromResult(_store.Where(f => !string.IsNullOrWhiteSpace(f.Type) && f.Type.Trim().Contains(q, StringComparison.OrdinalIgnoreCase)).ToList());
|
|
}
|
|
}
|
|
|
|
public Task<List<Fragment>> SearchAsync(string? type = null, string? tag = null, DateTimeOffset? timeAfter = null)
|
|
{
|
|
var results = _store.AsEnumerable();
|
|
var qType = type?.Trim();
|
|
var qTag = tag?.Trim();
|
|
|
|
lock (_lock)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(qType))
|
|
results = results.Where(f => !string.IsNullOrWhiteSpace(f.Type) && f.Type.Trim().Contains(qType, StringComparison.OrdinalIgnoreCase));
|
|
if (!string.IsNullOrWhiteSpace(qTag))
|
|
results = results.Where(f => f.Tags?.Any(t => !string.IsNullOrWhiteSpace(t) && t.Contains(qTag, StringComparison.OrdinalIgnoreCase)) == true);
|
|
if (timeAfter.HasValue)
|
|
results = results.Where(f => f.Time > timeAfter.Value);
|
|
|
|
return Task.FromResult(results.ToList());
|
|
}
|
|
}
|
|
}
|