Skip to content

Commit e1f9757

Browse files
committed
Update task creation to new saga, service and thin hook
1 parent 4fb9c86 commit e1f9757

File tree

22 files changed

+710
-236
lines changed

22 files changed

+710
-236
lines changed

apps/array/src/main/di/container.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import "reflect-metadata";
22
import { Container } from "inversify";
3-
import { TaskService } from "../services/task.service.js";
4-
import { TOKENS } from "./tokens.js";
3+
import { GitService } from "../services/git/service.js";
4+
import { MAIN_TOKENS } from "./tokens.js";
55

66
/**
77
* Main process dependency injection container
@@ -11,7 +11,7 @@ export const container = new Container({
1111
});
1212

1313
// Bind services
14-
container.bind<TaskService>(TOKENS.TaskService).to(TaskService);
14+
container.bind<GitService>(MAIN_TOKENS.GitService).to(GitService);
1515

1616
export function get<T>(token: symbol): T {
1717
return container.get<T>(token);

apps/array/src/main/di/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { container, get } from "./container.js";
2-
export { TOKENS } from "./tokens.js";
2+
export { MAIN_TOKENS } from "./tokens.js";

apps/array/src/main/di/tokens.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
export const TOKENS = {
1+
/**
2+
* Main process DI tokens.
3+
*
4+
* IMPORTANT: These tokens are for main process only.
5+
* Never import this file from renderer code.
6+
*/
7+
export const MAIN_TOKENS = Object.freeze({
28
// Services
3-
TaskService: Symbol.for("TaskService"),
4-
} as const;
9+
GitService: Symbol.for("Main.GitService"),
10+
});

apps/array/src/main/preload.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,6 @@ contextBridge.exposeInMainWorld("electronAPI", {
7676
// Repo API
7777
validateRepo: (directoryPath: string): Promise<boolean> =>
7878
ipcRenderer.invoke("validate-repo", directoryPath),
79-
detectRepo: (
80-
directoryPath: string,
81-
): Promise<{
82-
organization: string;
83-
repository: string;
84-
branch?: string;
85-
remote?: string;
86-
} | null> => ipcRenderer.invoke("detect-repo", directoryPath),
8779
cloneRepository: (
8880
repoUrl: string,
8981
targetPath: string,

apps/array/src/main/services/git.ts

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { promisify } from "node:util";
66
import type { ChangedFile, GitFileStatus } from "@shared/types";
77
import { type IpcMainInvokeEvent, ipcMain } from "electron";
88
import { logger } from "../lib/logger";
9+
import { parseGitHubUrl } from "./git/utils";
910

1011
const log = logger.scope("git");
1112

@@ -51,24 +52,6 @@ const getAllFilesInDirectory = async (
5152
return files;
5253
};
5354

54-
export interface GitHubRepo {
55-
organization: string;
56-
repository: string;
57-
}
58-
59-
export const parseGitHubUrl = (url: string): GitHubRepo | null => {
60-
const match =
61-
url.match(/github\.com[:/](.+?)\/(.+?)(\.git)?$/) ||
62-
url.match(/git@github\.com:(.+?)\/(.+?)(\.git)?$/);
63-
64-
if (!match) return null;
65-
66-
return {
67-
organization: match[1],
68-
repository: match[2].replace(/\.git$/, ""),
69-
};
70-
};
71-
7255
export const isGitRepository = async (
7356
directoryPath: string,
7457
): Promise<boolean> => {
@@ -690,31 +673,6 @@ export function registerGitIpc(): void {
690673
},
691674
);
692675

693-
ipcMain.handle(
694-
"detect-repo",
695-
async (
696-
_event: IpcMainInvokeEvent,
697-
directoryPath: string,
698-
): Promise<{
699-
organization: string;
700-
repository: string;
701-
branch?: string;
702-
remote?: string;
703-
} | null> => {
704-
if (!directoryPath) return null;
705-
706-
const remoteUrl = await getRemoteUrl(directoryPath);
707-
if (!remoteUrl) return null;
708-
709-
const repo = parseGitHubUrl(remoteUrl);
710-
if (!repo) return null;
711-
712-
const branch = await getCurrentBranch(directoryPath);
713-
714-
return { ...repo, branch, remote: remoteUrl };
715-
},
716-
);
717-
718676
ipcMain.handle(
719677
"get-changed-files-head",
720678
async (
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { execFile } from "node:child_process";
2+
import { promisify } from "node:util";
3+
import { injectable } from "inversify";
4+
import type { DetectRepoResult } from "./types";
5+
import { parseGitHubUrl } from "./utils";
6+
7+
const execFileAsync = promisify(execFile);
8+
9+
@injectable()
10+
export class GitService {
11+
public async detectRepo(
12+
directoryPath: string,
13+
): Promise<DetectRepoResult | null> {
14+
if (!directoryPath) return null;
15+
16+
const remoteUrl = await this.getRemoteUrl(directoryPath);
17+
if (!remoteUrl) return null;
18+
19+
const repo = await parseGitHubUrl(remoteUrl);
20+
if (!repo) return null;
21+
22+
const branch = await this.getCurrentBranch(directoryPath);
23+
if (!branch) return null;
24+
25+
return {
26+
organization: repo.organization,
27+
repository: repo.repository,
28+
remote: remoteUrl,
29+
branch,
30+
};
31+
}
32+
33+
public async getRemoteUrl(directoryPath: string): Promise<string | null> {
34+
try {
35+
const { stdout } = await execFileAsync("git remote get-url origin", {
36+
cwd: directoryPath,
37+
});
38+
return stdout.trim();
39+
} catch {
40+
return null;
41+
}
42+
}
43+
44+
public async getCurrentBranch(directoryPath: string): Promise<string | null> {
45+
try {
46+
const { stdout } = await execFileAsync("git branch --show-current", {
47+
cwd: directoryPath,
48+
});
49+
return stdout.trim();
50+
} catch {
51+
return null;
52+
}
53+
}
54+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface GitHubRepo {
2+
organization: string;
3+
repository: string;
4+
}
5+
6+
export interface DetectRepoResult {
7+
organization: string;
8+
repository: string;
9+
remote?: string;
10+
branch?: string;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { GitHubRepo } from "./types";
2+
3+
export function parseGitHubUrl(url: string): GitHubRepo | null {
4+
const match =
5+
url.match(/github\.com[:/](.+?)\/(.+?)(\.git)?$/) ||
6+
url.match(/git@github\.com:(.+?)\/(.+?)(\.git)?$/);
7+
8+
if (!match) return null;
9+
10+
return { organization: match[1], repository: match[2].replace(/\.git$/, "") };
11+
}

apps/array/src/main/services/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import "./posthog-analytics.js";
1515
import "./session-manager.js";
1616
import "./settingsStore.js";
1717
import "./shell.js";
18-
import "./task.service.js";
1918
import "./transcription-prompts.js";
2019
import "./updates.js";
2120
import "./worktree.js";

apps/array/src/main/trpc/router.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { encryptionRouter } from "./routers/encryption.js";
2+
import { gitRouter } from "./routers/git.js";
23
import { logsRouter } from "./routers/logs.js";
34
import { osRouter } from "./routers/os.js";
45
import { secureStoreRouter } from "./routers/secure-store.js";
@@ -9,6 +10,7 @@ export const trpcRouter = router({
910
logs: logsRouter,
1011
secureStore: secureStoreRouter,
1112
encryption: encryptionRouter,
13+
git: gitRouter,
1214
});
1315

1416
export type TrpcRouter = typeof trpcRouter;

0 commit comments

Comments
 (0)