feat(data): add ClaudeDoDbContext with Fluent API configurations
This commit is contained in:
22
src/ClaudeDo.Data/ClaudeDoDbContext.cs
Normal file
22
src/ClaudeDo.Data/ClaudeDoDbContext.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ClaudeDo.Data;
|
||||
|
||||
public class ClaudeDoDbContext : DbContext
|
||||
{
|
||||
public ClaudeDoDbContext(DbContextOptions<ClaudeDoDbContext> options) : base(options) { }
|
||||
|
||||
public DbSet<TaskEntity> Tasks => Set<TaskEntity>();
|
||||
public DbSet<ListEntity> Lists => Set<ListEntity>();
|
||||
public DbSet<TagEntity> Tags => Set<TagEntity>();
|
||||
public DbSet<ListConfigEntity> ListConfigs => Set<ListConfigEntity>();
|
||||
public DbSet<WorktreeEntity> Worktrees => Set<WorktreeEntity>();
|
||||
public DbSet<TaskRunEntity> TaskRuns => Set<TaskRunEntity>();
|
||||
public DbSet<SubtaskEntity> Subtasks => Set<SubtaskEntity>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ClaudeDoDbContext).Assembly);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class ListConfigEntityConfiguration : IEntityTypeConfiguration<ListConfigEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ListConfigEntity> builder)
|
||||
{
|
||||
builder.ToTable("list_config");
|
||||
|
||||
builder.HasKey(c => c.ListId);
|
||||
builder.Property(c => c.ListId).HasColumnName("list_id");
|
||||
builder.Property(c => c.Model).HasColumnName("model");
|
||||
builder.Property(c => c.SystemPrompt).HasColumnName("system_prompt");
|
||||
builder.Property(c => c.AgentPath).HasColumnName("agent_path");
|
||||
}
|
||||
}
|
||||
36
src/ClaudeDo.Data/Configuration/ListEntityConfiguration.cs
Normal file
36
src/ClaudeDo.Data/Configuration/ListEntityConfiguration.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class ListEntityConfiguration : IEntityTypeConfiguration<ListEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ListEntity> builder)
|
||||
{
|
||||
builder.ToTable("lists");
|
||||
|
||||
builder.HasKey(l => l.Id);
|
||||
builder.Property(l => l.Id).HasColumnName("id");
|
||||
builder.Property(l => l.Name).HasColumnName("name").IsRequired();
|
||||
builder.Property(l => l.CreatedAt).HasColumnName("created_at").IsRequired();
|
||||
builder.Property(l => l.WorkingDir).HasColumnName("working_dir");
|
||||
builder.Property(l => l.DefaultCommitType).HasColumnName("default_commit_type").IsRequired().HasDefaultValue("chore");
|
||||
|
||||
builder.HasOne(l => l.Config)
|
||||
.WithOne(c => c.List)
|
||||
.HasForeignKey<ListConfigEntity>(c => c.ListId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasMany(l => l.Tags)
|
||||
.WithMany(tag => tag.Lists)
|
||||
.UsingEntity("list_tags",
|
||||
l => l.HasOne(typeof(TagEntity)).WithMany().HasForeignKey("tag_id").OnDelete(DeleteBehavior.Cascade),
|
||||
r => r.HasOne(typeof(ListEntity)).WithMany().HasForeignKey("list_id").OnDelete(DeleteBehavior.Cascade),
|
||||
j =>
|
||||
{
|
||||
j.HasKey("list_id", "tag_id");
|
||||
j.ToTable("list_tags");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class SubtaskEntityConfiguration : IEntityTypeConfiguration<SubtaskEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SubtaskEntity> builder)
|
||||
{
|
||||
builder.ToTable("subtasks");
|
||||
|
||||
builder.HasKey(s => s.Id);
|
||||
builder.Property(s => s.Id).HasColumnName("id");
|
||||
builder.Property(s => s.TaskId).HasColumnName("task_id").IsRequired();
|
||||
builder.Property(s => s.Title).HasColumnName("title").IsRequired();
|
||||
builder.Property(s => s.Completed).HasColumnName("completed").IsRequired().HasDefaultValue(false);
|
||||
builder.Property(s => s.OrderNum).HasColumnName("order_num").IsRequired();
|
||||
builder.Property(s => s.CreatedAt).HasColumnName("created_at").IsRequired();
|
||||
|
||||
builder.HasOne(s => s.Task)
|
||||
.WithMany(t => t.Subtasks)
|
||||
.HasForeignKey(s => s.TaskId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasIndex(s => s.TaskId).HasDatabaseName("idx_subtasks_task_id");
|
||||
}
|
||||
}
|
||||
22
src/ClaudeDo.Data/Configuration/TagEntityConfiguration.cs
Normal file
22
src/ClaudeDo.Data/Configuration/TagEntityConfiguration.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class TagEntityConfiguration : IEntityTypeConfiguration<TagEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<TagEntity> builder)
|
||||
{
|
||||
builder.ToTable("tags");
|
||||
|
||||
builder.HasKey(t => t.Id);
|
||||
builder.Property(t => t.Id).HasColumnName("id").ValueGeneratedOnAdd();
|
||||
builder.Property(t => t.Name).HasColumnName("name").IsRequired();
|
||||
builder.HasIndex(t => t.Name).IsUnique();
|
||||
|
||||
builder.HasData(
|
||||
new TagEntity { Id = 1, Name = "agent" },
|
||||
new TagEntity { Id = 2, Name = "manual" });
|
||||
}
|
||||
}
|
||||
73
src/ClaudeDo.Data/Configuration/TaskEntityConfiguration.cs
Normal file
73
src/ClaudeDo.Data/Configuration/TaskEntityConfiguration.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class TaskEntityConfiguration : IEntityTypeConfiguration<TaskEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<TaskEntity> builder)
|
||||
{
|
||||
builder.ToTable("tasks");
|
||||
|
||||
builder.HasKey(t => t.Id);
|
||||
builder.Property(t => t.Id).HasColumnName("id");
|
||||
builder.Property(t => t.ListId).HasColumnName("list_id").IsRequired();
|
||||
builder.Property(t => t.Title).HasColumnName("title").IsRequired();
|
||||
builder.Property(t => t.Description).HasColumnName("description");
|
||||
builder.Property(t => t.Status).HasColumnName("status").IsRequired()
|
||||
.HasConversion(
|
||||
v => v switch
|
||||
{
|
||||
TaskStatus.Manual => "manual",
|
||||
TaskStatus.Queued => "queued",
|
||||
TaskStatus.Running => "running",
|
||||
TaskStatus.Done => "done",
|
||||
TaskStatus.Failed => "failed",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
v => v switch
|
||||
{
|
||||
"manual" => TaskStatus.Manual,
|
||||
"queued" => TaskStatus.Queued,
|
||||
"running" => TaskStatus.Running,
|
||||
"done" => TaskStatus.Done,
|
||||
"failed" => TaskStatus.Failed,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
builder.Property(t => t.ScheduledFor).HasColumnName("scheduled_for");
|
||||
builder.Property(t => t.Result).HasColumnName("result");
|
||||
builder.Property(t => t.LogPath).HasColumnName("log_path");
|
||||
builder.Property(t => t.CreatedAt).HasColumnName("created_at").IsRequired();
|
||||
builder.Property(t => t.StartedAt).HasColumnName("started_at");
|
||||
builder.Property(t => t.FinishedAt).HasColumnName("finished_at");
|
||||
builder.Property(t => t.CommitType).HasColumnName("commit_type").IsRequired().HasDefaultValue("chore");
|
||||
builder.Property(t => t.Model).HasColumnName("model");
|
||||
builder.Property(t => t.SystemPrompt).HasColumnName("system_prompt");
|
||||
builder.Property(t => t.AgentPath).HasColumnName("agent_path");
|
||||
|
||||
builder.HasOne(t => t.List)
|
||||
.WithMany(l => l.Tasks)
|
||||
.HasForeignKey(t => t.ListId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasOne(t => t.Worktree)
|
||||
.WithOne(w => w.Task)
|
||||
.HasForeignKey<WorktreeEntity>(w => w.TaskId);
|
||||
|
||||
builder.HasMany(t => t.Tags)
|
||||
.WithMany(tag => tag.Tasks)
|
||||
.UsingEntity("task_tags",
|
||||
l => l.HasOne(typeof(TagEntity)).WithMany().HasForeignKey("tag_id").OnDelete(DeleteBehavior.Cascade),
|
||||
r => r.HasOne(typeof(TaskEntity)).WithMany().HasForeignKey("task_id").OnDelete(DeleteBehavior.Cascade),
|
||||
j =>
|
||||
{
|
||||
j.HasKey("task_id", "tag_id");
|
||||
j.ToTable("task_tags");
|
||||
});
|
||||
|
||||
builder.HasIndex(t => t.ListId).HasDatabaseName("idx_tasks_list_id");
|
||||
builder.HasIndex(t => t.Status).HasDatabaseName("idx_tasks_status");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class TaskRunEntityConfiguration : IEntityTypeConfiguration<TaskRunEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<TaskRunEntity> builder)
|
||||
{
|
||||
builder.ToTable("task_runs");
|
||||
|
||||
builder.HasKey(r => r.Id);
|
||||
builder.Property(r => r.Id).HasColumnName("id");
|
||||
builder.Property(r => r.TaskId).HasColumnName("task_id").IsRequired();
|
||||
builder.Property(r => r.RunNumber).HasColumnName("run_number").IsRequired();
|
||||
builder.Property(r => r.SessionId).HasColumnName("session_id");
|
||||
builder.Property(r => r.IsRetry).HasColumnName("is_retry").IsRequired().HasDefaultValue(false);
|
||||
builder.Property(r => r.Prompt).HasColumnName("prompt").IsRequired();
|
||||
builder.Property(r => r.ResultMarkdown).HasColumnName("result_markdown");
|
||||
builder.Property(r => r.StructuredOutputJson).HasColumnName("structured_output");
|
||||
builder.Property(r => r.ErrorMarkdown).HasColumnName("error_markdown");
|
||||
builder.Property(r => r.ExitCode).HasColumnName("exit_code");
|
||||
builder.Property(r => r.TurnCount).HasColumnName("turn_count");
|
||||
builder.Property(r => r.TokensIn).HasColumnName("tokens_in");
|
||||
builder.Property(r => r.TokensOut).HasColumnName("tokens_out");
|
||||
builder.Property(r => r.LogPath).HasColumnName("log_path");
|
||||
builder.Property(r => r.StartedAt).HasColumnName("started_at");
|
||||
builder.Property(r => r.FinishedAt).HasColumnName("finished_at");
|
||||
|
||||
builder.HasOne(r => r.Task)
|
||||
.WithMany(t => t.Runs)
|
||||
.HasForeignKey(r => r.TaskId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasIndex(r => r.TaskId).HasDatabaseName("idx_task_runs_task_id");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using ClaudeDo.Data.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace ClaudeDo.Data.Configuration;
|
||||
|
||||
public class WorktreeEntityConfiguration : IEntityTypeConfiguration<WorktreeEntity>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<WorktreeEntity> builder)
|
||||
{
|
||||
builder.ToTable("worktrees");
|
||||
|
||||
builder.HasKey(w => w.TaskId);
|
||||
builder.Property(w => w.TaskId).HasColumnName("task_id");
|
||||
builder.Property(w => w.Path).HasColumnName("path").IsRequired();
|
||||
builder.Property(w => w.BranchName).HasColumnName("branch_name").IsRequired();
|
||||
builder.Property(w => w.BaseCommit).HasColumnName("base_commit").IsRequired();
|
||||
builder.Property(w => w.HeadCommit).HasColumnName("head_commit");
|
||||
builder.Property(w => w.DiffStat).HasColumnName("diff_stat");
|
||||
builder.Property(w => w.State).HasColumnName("state").IsRequired()
|
||||
.HasDefaultValue(WorktreeState.Active)
|
||||
.HasConversion(
|
||||
v => v switch
|
||||
{
|
||||
WorktreeState.Active => "active",
|
||||
WorktreeState.Merged => "merged",
|
||||
WorktreeState.Discarded => "discarded",
|
||||
WorktreeState.Kept => "kept",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
},
|
||||
v => v switch
|
||||
{
|
||||
"active" => WorktreeState.Active,
|
||||
"merged" => WorktreeState.Merged,
|
||||
"discarded" => WorktreeState.Discarded,
|
||||
"kept" => WorktreeState.Kept,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
});
|
||||
builder.Property(w => w.CreatedAt).HasColumnName("created_at").IsRequired();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user