Files
ClaudeDo/src/ClaudeDo.Data/Repositories/ListRepository.cs
2026-04-14 11:34:16 +02:00

158 lines
6.7 KiB
C#

using ClaudeDo.Data.Models;
using Microsoft.Data.Sqlite;
namespace ClaudeDo.Data.Repositories;
public sealed class ListRepository
{
private readonly SqliteConnectionFactory _factory;
public ListRepository(SqliteConnectionFactory factory) => _factory = factory;
public async Task AddAsync(ListEntity entity, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = """
INSERT INTO lists (id, name, created_at, working_dir, default_commit_type)
VALUES (@id, @name, @created_at, @working_dir, @default_commit_type)
""";
cmd.Parameters.AddWithValue("@id", entity.Id);
cmd.Parameters.AddWithValue("@name", entity.Name);
cmd.Parameters.AddWithValue("@created_at", entity.CreatedAt.ToString("o"));
cmd.Parameters.AddWithValue("@working_dir", (object?)entity.WorkingDir ?? DBNull.Value);
cmd.Parameters.AddWithValue("@default_commit_type", entity.DefaultCommitType);
await cmd.ExecuteNonQueryAsync(ct);
}
public async Task UpdateAsync(ListEntity entity, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = """
UPDATE lists SET name = @name, working_dir = @working_dir,
default_commit_type = @default_commit_type
WHERE id = @id
""";
cmd.Parameters.AddWithValue("@id", entity.Id);
cmd.Parameters.AddWithValue("@name", entity.Name);
cmd.Parameters.AddWithValue("@working_dir", (object?)entity.WorkingDir ?? DBNull.Value);
cmd.Parameters.AddWithValue("@default_commit_type", entity.DefaultCommitType);
await cmd.ExecuteNonQueryAsync(ct);
}
public async Task DeleteAsync(string listId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "DELETE FROM lists WHERE id = @id";
cmd.Parameters.AddWithValue("@id", listId);
await cmd.ExecuteNonQueryAsync(ct);
}
public async Task<ListEntity?> GetByIdAsync(string listId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT id, name, created_at, working_dir, default_commit_type FROM lists WHERE id = @id";
cmd.Parameters.AddWithValue("@id", listId);
await using var reader = await cmd.ExecuteReaderAsync(ct);
if (!await reader.ReadAsync(ct)) return null;
return ReadList(reader);
}
public async Task<List<ListEntity>> GetAllAsync(CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT id, name, created_at, working_dir, default_commit_type FROM lists ORDER BY created_at";
await using var reader = await cmd.ExecuteReaderAsync(ct);
var result = new List<ListEntity>();
while (await reader.ReadAsync(ct))
result.Add(ReadList(reader));
return result;
}
public async Task<List<TagEntity>> GetTagsAsync(string listId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = """
SELECT t.id, t.name FROM tags t
JOIN list_tags lt ON lt.tag_id = t.id
WHERE lt.list_id = @list_id
""";
cmd.Parameters.AddWithValue("@list_id", listId);
await using var reader = await cmd.ExecuteReaderAsync(ct);
var result = new List<TagEntity>();
while (await reader.ReadAsync(ct))
result.Add(new TagEntity { Id = reader.GetInt64(0), Name = reader.GetString(1) });
return result;
}
public async Task AddTagAsync(string listId, long tagId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "INSERT OR IGNORE INTO list_tags (list_id, tag_id) VALUES (@list_id, @tag_id)";
cmd.Parameters.AddWithValue("@list_id", listId);
cmd.Parameters.AddWithValue("@tag_id", tagId);
await cmd.ExecuteNonQueryAsync(ct);
}
public async Task RemoveTagAsync(string listId, long tagId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "DELETE FROM list_tags WHERE list_id = @list_id AND tag_id = @tag_id";
cmd.Parameters.AddWithValue("@list_id", listId);
cmd.Parameters.AddWithValue("@tag_id", tagId);
await cmd.ExecuteNonQueryAsync(ct);
}
public async Task<ListConfigEntity?> GetConfigAsync(string listId, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT list_id, model, system_prompt, agent_path FROM list_config WHERE list_id = @list_id";
cmd.Parameters.AddWithValue("@list_id", listId);
await using var reader = await cmd.ExecuteReaderAsync(ct);
if (!await reader.ReadAsync(ct)) return null;
return new ListConfigEntity
{
ListId = reader.GetString(0),
Model = reader.IsDBNull(1) ? null : reader.GetString(1),
SystemPrompt = reader.IsDBNull(2) ? null : reader.GetString(2),
AgentPath = reader.IsDBNull(3) ? null : reader.GetString(3),
};
}
public async Task SetConfigAsync(ListConfigEntity entity, CancellationToken ct = default)
{
await using var conn = _factory.Open();
await using var cmd = conn.CreateCommand();
cmd.CommandText = """
INSERT OR REPLACE INTO list_config (list_id, model, system_prompt, agent_path)
VALUES (@list_id, @model, @system_prompt, @agent_path)
""";
cmd.Parameters.AddWithValue("@list_id", entity.ListId);
cmd.Parameters.AddWithValue("@model", (object?)entity.Model ?? DBNull.Value);
cmd.Parameters.AddWithValue("@system_prompt", (object?)entity.SystemPrompt ?? DBNull.Value);
cmd.Parameters.AddWithValue("@agent_path", (object?)entity.AgentPath ?? DBNull.Value);
await cmd.ExecuteNonQueryAsync(ct);
}
private static ListEntity ReadList(SqliteDataReader reader) => new()
{
Id = reader.GetString(0),
Name = reader.GetString(1),
CreatedAt = DateTime.Parse(reader.GetString(2)),
WorkingDir = reader.IsDBNull(3) ? null : reader.GetString(3),
DefaultCommitType = reader.GetString(4),
};
}