cloudaxe-opencode/packages/opencode/src/server/instance/project.ts

119 lines
3.7 KiB
TypeScript
Raw Normal View History

import { Hono } from "hono"
2025-12-09 18:55:39 +00:00
import { describeRoute, validator } from "hono-openapi"
import { resolver } from "hono-openapi"
import { Instance } from "../../project/instance"
import { Project } from "../../project/project"
2025-12-09 18:55:39 +00:00
import z from "zod"
import { ProjectID } from "../../project/schema"
import { errors } from "../error"
import { lazy } from "../../util/lazy"
import { InstanceBootstrap } from "../../project/bootstrap"
import { AppRuntime } from "@/effect/app-runtime"
2026-01-16 21:21:54 +00:00
export const ProjectRoutes = lazy(() =>
new Hono()
.get(
"/",
describeRoute({
summary: "List all projects",
description: "Get a list of projects that have been opened with OpenCode.",
operationId: "project.list",
responses: {
200: {
description: "List of projects",
content: {
"application/json": {
schema: resolver(z.array(Project.Info.zod)),
2026-01-16 21:21:54 +00:00
},
},
},
},
2026-01-16 21:21:54 +00:00
}),
async (c) => {
const projects = Project.list()
2026-01-16 21:21:54 +00:00
return c.json(projects)
},
2026-01-16 21:21:54 +00:00
)
.get(
"/current",
describeRoute({
summary: "Get current project",
description: "Retrieve the currently active project that OpenCode is working with.",
operationId: "project.current",
responses: {
200: {
description: "Current project information",
content: {
"application/json": {
schema: resolver(Project.Info.zod),
2026-01-16 21:21:54 +00:00
},
},
},
},
2026-01-16 21:21:54 +00:00
}),
async (c) => {
return c.json(Instance.project)
},
2026-01-16 21:21:54 +00:00
)
.post(
"/git/init",
describeRoute({
summary: "Initialize git repository",
description: "Create a git repository for the current project and return the refreshed project info.",
operationId: "project.initGit",
responses: {
200: {
description: "Project information after git initialization",
content: {
"application/json": {
schema: resolver(Project.Info.zod),
},
},
},
},
}),
async (c) => {
const dir = Instance.directory
const prev = Instance.project
const next = await AppRuntime.runPromise(
Project.Service.use((svc) => svc.initGit({ directory: dir, project: prev })),
)
if (next.id === prev.id && next.vcs === prev.vcs && next.worktree === prev.worktree) return c.json(next)
await Instance.reload({
directory: dir,
worktree: dir,
project: next,
init: () => AppRuntime.runPromise(InstanceBootstrap),
})
return c.json(next)
},
)
2026-01-16 21:21:54 +00:00
.patch(
"/:projectID",
describeRoute({
summary: "Update project",
description: "Update project properties such as name, icon, and commands.",
2026-01-16 21:21:54 +00:00
operationId: "project.update",
responses: {
200: {
description: "Updated project information",
content: {
"application/json": {
schema: resolver(Project.Info.zod),
2026-01-16 21:21:54 +00:00
},
2025-12-09 18:55:39 +00:00
},
},
2026-01-16 21:21:54 +00:00
...errors(400, 404),
2025-12-09 18:55:39 +00:00
},
2026-01-16 21:21:54 +00:00
}),
validator("param", z.object({ projectID: ProjectID.zod })),
2026-03-24 18:04:22 +00:00
validator("json", Project.UpdateInput.omit({ projectID: true })),
2026-01-16 21:21:54 +00:00
async (c) => {
const projectID = c.req.valid("param").projectID
const body = c.req.valid("json")
const project = await AppRuntime.runPromise(Project.Service.use((svc) => svc.update({ ...body, projectID })))
2026-01-16 21:21:54 +00:00
return c.json(project)
2025-12-09 18:55:39 +00:00
},
2026-01-16 21:21:54 +00:00
),
)