Skip to content

Commit bee094f

Browse files
authored
feat(server): extract question handler factory into packages/server (#22503)
1 parent 678d8f6 commit bee094f

5 files changed

Lines changed: 55 additions & 26 deletions

File tree

packages/opencode/src/server/instance/httpapi/question.ts

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,27 @@ import { memoMap } from "@/effect/run-service"
33
import { Question } from "@/question"
44
import { QuestionID } from "@/question/schema"
55
import { lazy } from "@/util/lazy"
6-
import { QuestionReply, QuestionRequest, questionApi } from "@opencode-ai/server"
7-
import { Effect, Layer, Schema } from "effect"
6+
import { makeQuestionHandler, questionApi } from "@opencode-ai/server"
7+
import { Effect, Layer } from "effect"
88
import { HttpRouter, HttpServer } from "effect/unstable/http"
99
import { HttpApiBuilder } from "effect/unstable/httpapi"
1010
import type { Handler } from "hono"
1111

1212
const root = "/experimental/httpapi/question"
1313

14-
const QuestionLive = HttpApiBuilder.group(
15-
questionApi,
16-
"question",
17-
Effect.fn("QuestionHttpApi.handlers")(function* (handlers) {
14+
const QuestionLive = makeQuestionHandler({
15+
list: Effect.fn("QuestionHttpApi.host.list")(function* () {
1816
const svc = yield* Question.Service
19-
const decode = Schema.decodeUnknownSync(Schema.Array(QuestionRequest))
20-
21-
const list = Effect.fn("QuestionHttpApi.list")(function* () {
22-
return decode(yield* svc.list())
23-
})
24-
25-
const reply = Effect.fn("QuestionHttpApi.reply")(function* (ctx: {
26-
params: { requestID: string }
27-
payload: Schema.Schema.Type<typeof QuestionReply>
28-
}) {
29-
yield* svc.reply({
30-
requestID: QuestionID.make(ctx.params.requestID),
31-
answers: ctx.payload.answers,
32-
})
33-
return true
17+
return yield* svc.list()
18+
}),
19+
reply: Effect.fn("QuestionHttpApi.host.reply")(function* (input) {
20+
const svc = yield* Question.Service
21+
yield* svc.reply({
22+
requestID: QuestionID.make(input.requestID),
23+
answers: input.answers,
3424
})
35-
36-
return handlers.handle("list", list).handle("reply", reply)
3725
}),
38-
).pipe(Layer.provide(Question.defaultLayer))
26+
}).pipe(Layer.provide(Question.defaultLayer))
3927

4028
const web = lazy(() =>
4129
HttpRouter.toWebHandler(

packages/server/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"./definition": "./src/definition/index.ts",
1111
"./definition/api": "./src/definition/api.ts",
1212
"./definition/question": "./src/definition/question.ts",
13-
"./api": "./src/api/index.ts"
13+
"./api": "./src/api/index.ts",
14+
"./api/question": "./src/api/question.ts"
1415
},
1516
"files": [
1617
"dist"

packages/server/src/api/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export {}
1+
export { makeQuestionHandler } from "./question.js"
2+
export type { QuestionOps } from "./question.js"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Effect, Schema } from "effect"
2+
import { HttpApiBuilder } from "effect/unstable/httpapi"
3+
import { QuestionReply, QuestionRequest, questionApi } from "../definition/question.js"
4+
5+
export interface QuestionOps<R = never> {
6+
readonly list: () => Effect.Effect<ReadonlyArray<unknown>, never, R>
7+
readonly reply: (input: {
8+
requestID: string
9+
answers: Schema.Schema.Type<typeof QuestionReply>["answers"]
10+
}) => Effect.Effect<void, never, R>
11+
}
12+
13+
export const makeQuestionHandler = <R>(ops: QuestionOps<R>) =>
14+
HttpApiBuilder.group(
15+
questionApi,
16+
"question",
17+
Effect.fn("QuestionHttpApi.handlers")(function* (handlers) {
18+
const decode = Schema.decodeUnknownSync(Schema.Array(QuestionRequest))
19+
20+
const list = Effect.fn("QuestionHttpApi.list")(function* () {
21+
return decode(yield* ops.list())
22+
})
23+
24+
const reply = Effect.fn("QuestionHttpApi.reply")(function* (ctx: {
25+
params: { requestID: string }
26+
payload: Schema.Schema.Type<typeof QuestionReply>
27+
}) {
28+
yield* ops.reply({
29+
requestID: ctx.params.requestID,
30+
answers: ctx.payload.answers,
31+
})
32+
return true
33+
})
34+
35+
return handlers.handle("list", list).handle("reply", reply)
36+
}),
37+
)

packages/server/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
export { openapi } from "./openapi.js"
2+
export { makeQuestionHandler } from "./api/question.js"
23
export { api } from "./definition/api.js"
34
export { questionApi, QuestionReply, QuestionRequest } from "./definition/question.js"
45
export type { OpenApiSpec, ServerApi } from "./types.js"
6+
export type { QuestionOps } from "./api/question.js"

0 commit comments

Comments
 (0)