Skip to content

Commit 774705d

Browse files
xesrevinuGit Agent
andcommitted
feat(domain): add commit message and project config models
- Define interfaces for commit messages, groups, and plans - Implement parseTrailerText to parse commit trailers - Add ProjectConfig and ProjectScope to represent project settings - Provide emptyProjectConfig factory for default configuration - Create renderCommitBody to format commit message body This introduces domain entities for commit message handling and project configurations. It includes parsing logic for trailers in commit messages and utility functions for formatting. These additions serve as foundational models for managing commits and project settings. Co-Authored-By: Git Agent <noreply@git-agent.dev>
1 parent 2a93708 commit 774705d

3 files changed

Lines changed: 108 additions & 0 deletions

File tree

src/domain/commit.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
export interface Trailer {
2+
readonly key: string;
3+
readonly value: string;
4+
}
5+
6+
export const parseTrailerText = (input: string): Trailer | undefined => {
7+
const separator = ": ";
8+
const index = input.indexOf(separator);
9+
if (index <= 0) {
10+
return undefined;
11+
}
12+
13+
const key = input.slice(0, index).trim();
14+
const value = input.slice(index + separator.length).trim();
15+
if (key.length === 0 || value.length === 0) {
16+
return undefined;
17+
}
18+
19+
return {
20+
key,
21+
value,
22+
};
23+
};
24+
25+
export interface CommitMessage {
26+
readonly title: string;
27+
readonly bullets: ReadonlyArray<string>;
28+
readonly explanation: string;
29+
}
30+
31+
export interface CommitGroup {
32+
readonly files: ReadonlyArray<string>;
33+
readonly message: CommitMessage | undefined;
34+
}
35+
36+
export interface CommitPlan {
37+
readonly groups: ReadonlyArray<CommitGroup>;
38+
}
39+
40+
export interface SingleCommitResult {
41+
readonly title: string;
42+
readonly explanation: string;
43+
readonly files: ReadonlyArray<string>;
44+
readonly output: string | undefined;
45+
}
46+
47+
export const renderCommitBody = (message: CommitMessage): string => {
48+
const bulletSection = message.bullets.map((bullet) => `- ${bullet}`).join("\n");
49+
if (bulletSection.length === 0 && message.explanation.length === 0) {
50+
return "";
51+
}
52+
53+
if (bulletSection.length === 0) {
54+
return message.explanation;
55+
}
56+
57+
if (message.explanation.length === 0) {
58+
return bulletSection;
59+
}
60+
61+
return `${bulletSection}\n\n${message.explanation}`;
62+
};

src/domain/project.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export interface ProjectScope {
2+
readonly name: string;
3+
readonly description?: string;
4+
}
5+
6+
export interface ProjectConfig {
7+
readonly scopes: ReadonlyArray<ProjectScope>;
8+
readonly hooks: ReadonlyArray<string>;
9+
readonly maxDiffLines: number;
10+
readonly noGitAgentCoAuthor: boolean;
11+
readonly noModelCoAuthor: boolean;
12+
}
13+
14+
export const emptyProjectConfig = (): ProjectConfig => ({
15+
scopes: [],
16+
hooks: [],
17+
maxDiffLines: 0,
18+
noGitAgentCoAuthor: false,
19+
noModelCoAuthor: false,
20+
});

tests/commit-inputs.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { describe, expect, it } from "vitest";
2+
import { parseTrailerText } from "../src/domain/commit";
3+
import { parseCsvValues } from "../src/shared/text";
4+
5+
describe("repeatable commit inputs", () => {
6+
it("flattens repeated and comma-separated values", () => {
7+
expect(parseCsvValues(["alice", "bob, carol", "dave"])).toEqual([
8+
"alice",
9+
"bob",
10+
"carol",
11+
"dave",
12+
]);
13+
});
14+
15+
it("parses a valid trailer value", () => {
16+
expect(parseTrailerText("Reviewed-by: Ada Lovelace")).toEqual({
17+
key: "Reviewed-by",
18+
value: "Ada Lovelace",
19+
});
20+
});
21+
22+
it("rejects trailer values without the required separator", () => {
23+
expect(parseTrailerText("Reviewed-by:Ada")).toBeUndefined();
24+
expect(parseTrailerText("Reviewed-by")).toBeUndefined();
25+
});
26+
});

0 commit comments

Comments
 (0)