Refactor type gen

This commit is contained in:
Louis Knight-Webb
2025-06-20 19:49:15 +01:00
parent b15f1a5977
commit 53d0328c0d
4 changed files with 66 additions and 109 deletions

View File

@@ -1,80 +1,18 @@
use std::env;
use std::path::Path;
use ts_rs::TS;
// Import all the types we want to export using the library crate
use std::{env, fs, path::Path};
use ts_rs::TS; // make sure this is in [build-dependencies]
fn main() {
// Where the combined types.ts will live
let shared_path = Path::new("../shared");
fs::create_dir_all(shared_path).expect("cannot create ../shared");
// Create the shared directory if it doesn't exist
std::fs::create_dir_all(shared_path).unwrap();
println!("Generating TypeScript types…");
println!("Generating TypeScript types...");
// Set environment variable to configure ts-rs output directory
// Tell ts-rs where to drop its per-type files (well still roll our own big one)
env::set_var("TS_RS_EXPORT_DIR", shared_path.to_str().unwrap());
// Generate consolidated types.ts file
let consolidated_content = format!(
r#"// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
// Auto-generated from Rust backend types using ts-rs
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}
{}"#,
// Collect every declaration at *runtime* (so no const-eval issues)
let decls = [
vibe_kanban::models::ApiResponse::<()>::decl(),
vibe_kanban::models::config::Config::decl(),
vibe_kanban::models::config::ThemeMode::decl(),
@@ -103,9 +41,18 @@ fn main() {
vibe_kanban::models::task_attempt::FileDiff::decl(),
vibe_kanban::models::task_attempt::WorktreeDiff::decl(),
vibe_kanban::models::task_attempt::BranchStatus::decl(),
);
];
std::fs::write(shared_path.join("types.ts"), consolidated_content).unwrap();
// Header banner
const HEADER: &str =
"// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs).\n\
// Do not edit this file manually.\n\
// Auto-generated from Rust backend types using ts-rs\n\n";
println!("TypeScript types generated successfully in ../shared/");
// Smash it all together
let consolidated = format!("{HEADER}{}", decls.join("\n\n"));
fs::write(shared_path.join("types.ts"), consolidated).expect("unable to write types.ts");
println!("✅ TypeScript types generated in ../shared/");
}

View File

@@ -369,8 +369,7 @@ impl TaskAttempt {
let main_commit = main_repo.find_commit(main_branch_commit.id())?;
let worktree_commit = main_repo.find_commit(worktree_branch_commit.id())?;
let merge_commit_message =
format!("Merge task: {} into {}", task_title, main_branch);
let merge_commit_message = format!("Merge task: {} into {}", task_title, main_branch);
let merge_commit_id = main_repo.commit(
Some(&main_branch_ref),
&signature,
@@ -784,15 +783,20 @@ impl TaskAttempt {
// Look for the next sequence of matching lines (at least 2 consecutive matches)
for search_old in (old_idx + 1)..old_lines.len() {
for search_new in (new_idx + 1)..new_lines.len() {
if search_old < old_lines.len() - 1 && search_new < new_lines.len() - 1 {
if search_old < old_lines.len() - 1
&& search_new < new_lines.len() - 1
{
// Check for at least 2 consecutive matching lines to confirm this is not a coincidental match
if old_lines[search_old] == new_lines[search_new]
&& old_lines[search_old + 1] == new_lines[search_new + 1] {
if old_lines[search_old] == new_lines[search_new]
&& old_lines[search_old + 1] == new_lines[search_new + 1]
{
next_match_old = search_old;
next_match_new = search_new;
break;
}
} else if search_old == old_lines.len() - 1 && search_new == new_lines.len() - 1 {
} else if search_old == old_lines.len() - 1
&& search_new == new_lines.len() - 1
{
// Last lines match
if old_lines[search_old] == new_lines[search_new] {
next_match_old = search_old;

View File

@@ -600,7 +600,12 @@ pub async fn delete_task_attempt_file(
message: Some(format!("File '{}' deleted successfully", query.file_path)),
})),
Err(e) => {
tracing::error!("Failed to delete file '{}' from task attempt {}: {}", query.file_path, attempt_id, e);
tracing::error!(
"Failed to delete file '{}' from task attempt {}: {}",
query.file_path,
attempt_id,
e
);
Ok(ResponseJson(ApiResponse {
success: false,
data: None,

View File

@@ -1,58 +1,59 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs).
// Do not edit this file manually.
// Auto-generated from Rust backend types using ts-rs
export type ApiResponse<T> = { success: boolean, data: T | null, message: string | null, };
type ApiResponse<T> = { success: boolean, data: T | null, message: string | null, };
export type Config = { theme: ThemeMode, executor: ExecutorConfig, disclaimer_acknowledged: boolean, sound_alerts: boolean, editor: EditorConfig, };
type Config = { theme: ThemeMode, executor: ExecutorConfig, disclaimer_acknowledged: boolean, sound_alerts: boolean, editor: EditorConfig, };
export type ThemeMode = "light" | "dark" | "system";
type ThemeMode = "light" | "dark" | "system";
export type EditorConfig = { editor_type: EditorType, custom_command: string | null, };
type EditorConfig = { editor_type: EditorType, custom_command: string | null, };
export type EditorType = "vscode" | "cursor" | "windsurf" | "intellij" | "zed" | "custom";
type EditorType = "vscode" | "cursor" | "windsurf" | "intellij" | "zed" | "custom";
export type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" };
type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" };
export type CreateProject = { name: string, git_repo_path: string, use_existing_repo: boolean, setup_script: string | null, };
type CreateProject = { name: string, git_repo_path: string, use_existing_repo: boolean, setup_script: string | null, };
export type Project = { id: string, name: string, git_repo_path: string, setup_script: string | null, created_at: Date, updated_at: Date, };
type Project = { id: string, name: string, git_repo_path: string, setup_script: string | null, created_at: Date, updated_at: Date, };
export type UpdateProject = { name: string | null, git_repo_path: string | null, setup_script: string | null, };
type UpdateProject = { name: string | null, git_repo_path: string | null, setup_script: string | null, };
export type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType, };
type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType, };
export type SearchMatchType = "FileName" | "DirectoryName" | "FullPath";
type SearchMatchType = "FileName" | "DirectoryName" | "FullPath";
export type CreateTask = { project_id: string, title: string, description: string | null, };
type CreateTask = { project_id: string, title: string, description: string | null, };
export type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
export type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, };
type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, };
export type TaskWithAttemptStatus = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, has_in_progress_attempt: boolean, has_merged_attempt: boolean, };
type TaskWithAttemptStatus = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, has_in_progress_attempt: boolean, has_merged_attempt: boolean, };
export type UpdateTask = { title: string | null, description: string | null, status: TaskStatus | null, };
type UpdateTask = { title: string | null, description: string | null, status: TaskStatus | null, };
export type TaskAttemptStatus = "init" | "setuprunning" | "setupcomplete" | "setupfailed" | "executorrunning" | "executorcomplete" | "executorfailed" | "paused";
type TaskAttemptStatus = "init" | "setuprunning" | "setupcomplete" | "setupfailed" | "executorrunning" | "executorcomplete" | "executorfailed" | "paused";
export type TaskAttempt = { id: string, task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, stdout: string | null, stderr: string | null, created_at: string, updated_at: string, };
type TaskAttempt = { id: string, task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, stdout: string | null, stderr: string | null, created_at: string, updated_at: string, };
export type CreateTaskAttempt = { task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, };
type CreateTaskAttempt = { task_id: string, worktree_path: string, merge_commit: string | null, executor: string | null, };
export type UpdateTaskAttempt = { worktree_path: string | null, merge_commit: string | null, };
type UpdateTaskAttempt = { worktree_path: string | null, merge_commit: string | null, };
export type TaskAttemptActivity = { id: string, task_attempt_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, };
type TaskAttemptActivity = { id: string, task_attempt_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, };
export type CreateTaskAttemptActivity = { task_attempt_id: string, status: TaskAttemptStatus | null, note: string | null, };
type CreateTaskAttemptActivity = { task_attempt_id: string, status: TaskAttemptStatus | null, note: string | null, };
export type DirectoryEntry = { name: string, path: string, is_directory: boolean, is_git_repo: boolean, };
type DirectoryEntry = { name: string, path: string, is_directory: boolean, is_git_repo: boolean, };
export type DiffChunkType = "Equal" | "Insert" | "Delete";
type DiffChunkType = "Equal" | "Insert" | "Delete";
export type DiffChunk = { chunk_type: DiffChunkType, content: string, };
type DiffChunk = { chunk_type: DiffChunkType, content: string, };
export type FileDiff = { path: string, chunks: Array<DiffChunk>, };
type FileDiff = { path: string, chunks: Array<DiffChunk>, };
export type WorktreeDiff = { files: Array<FileDiff>, };
type WorktreeDiff = { files: Array<FileDiff>, };
export type BranchStatus = { is_behind: boolean, commits_behind: number, commits_ahead: number, up_to_date: boolean, merged: boolean, };
type BranchStatus = { is_behind: boolean, commits_behind: number, commits_ahead: number, up_to_date: boolean, merged: boolean, };