07.Continue Employee Controller
เราจะมาทำ Employee Controller ที่เหลือให้ครบ
Get Routes
import { Effect } from "effect"import * as S from "effect/Schema"import { Hono } from "hono"import { describeRoute } from "hono-openapi"import { resolver, validator } from "hono-openapi/effect"import { ServicesRuntime } from "../../runtimes/index.js"import { Branded, EmployeeWithRelationsSchema, Helpers } from "../../schema/index.js"import { EmployeeServiceContext } from "../../services/employee/index.js"
const getByIdResponseSchema = EmployeeWithRelationsSchema.Schema.omit("deletedAt")
const getByIdDocs = describeRoute({ responses: { 200: { content: { "application/json": { schema: resolver(getByIdResponseSchema), }, }, description: "Get Employee by EmployeeId", }, 404: { content: { "application/json": { schema: resolver(S.Struct({ message: S.String, })), }, }, description: "Get Employee by EmployeeId not found", }, }, tags: ["Employee"],})
const validateGetByIdRequest = validator("param", S.Struct({ employeeId: Branded.EmployeeIdFromString,}))
const getManyResponseSchema = S.Array(EmployeeWithRelationsSchema.Schema.omit("deletedAt"))
const getManyDocs = describeRoute({ responses: { 200: { content: { "application/json": { schema: resolver(getManyResponseSchema), }, }, description: "Get Employees", }, 500: { content: { "application/json": { schema: resolver(S.Struct({ message: S.String, })), }, }, description: "Get Employees Error", }, }, tags: ["Employee"],})
export function setupEmployeeGetRoutes() { const app = new Hono()
app.get("/:employeeId", getByIdDocs, validateGetByIdRequest, async (c) => { const { employeeId } = c.req.valid("param")
const parseResponse = Helpers.fromObjectToSchemaEffect(getByIdResponseSchema)
const program = EmployeeServiceContext.pipe( Effect.andThen(svc => svc.findOneById(employeeId)), Effect.andThen(parseResponse), Effect.andThen(data => c.json(data, 200)), Effect.catchTags({ FindEmployeeByIdError: () => Effect.succeed(c.json({ message: "findOneById error" }, 500)), NoSuchElementException: () => Effect.succeed(c.json({ message: "not found employee for id" }, 404)), ParseError: () => Effect.succeed(c.json({ message: "findOneById error" }, 500)), }), Effect.withSpan("GET /:employeeId.employee.controller"), )
const result = await ServicesRuntime.runPromise(program) return result })
app.get("/", getManyDocs, async (c) => { const parseResponse = Helpers.fromObjectToSchemaEffect(getManyResponseSchema)
const program = EmployeeServiceContext.pipe( // ^? Effect.Effect<..., never, EmployeeServiceContext> Effect.tap(() => Effect.log("start finding many employees")), Effect.andThen(svc => svc.findMany()), Effect.andThen(parseResponse), Effect.andThen(data => c.json(data, 200)), Effect.tap(() => Effect.log("test")), Effect.catchTags({ FindManyEmployeeError: () => Effect.succeed(c.json({ message: "find many error" }, 500)), ParseError: () => Effect.succeed(c.json({ message: "parse error" }, 500)), }), Effect.annotateLogs({ key: "annotate" }), Effect.withLogSpan("test"), Effect.withSpan("GET /.employee.controller /"), )
const result = await ServicesRuntime.runPromise(program) return result })
return app}
Post Routes
import { Effect } from "effect"import * as S from "effect/Schema"import { Hono } from "hono"import { describeRoute } from "hono-openapi"import { resolver, validator } from "hono-openapi/effect"import { ServicesRuntime } from "../../runtimes/index.js"import { EmployeeSchema, Helpers } from "../../schema/index.js"import { EmployeeServiceContext } from "../../services/employee/index.js"
const responseSchema = EmployeeSchema.Schema.omit("deletedAt")
const docs = describeRoute({ responses: { 201: { content: { "application/json": { schema: resolver(responseSchema), }, }, description: "Created Employee", }, 500: { content: { "application/json": { schema: resolver(S.Struct({ message: S.String, })), }, }, description: "Created Employee", }, }, tags: ["Employee"], validateResponse: true,})
const validateRequestBody = validator("json", EmployeeSchema.CreateSchema)
export function setupEmployeePostRoutes() { const app = new Hono()
app.post("/", docs, validateRequestBody, async (c) => { const body = c.req.valid("json")
const parseResponse = Helpers.fromObjectToSchemaEffect(responseSchema)
const program = EmployeeServiceContext.pipe( Effect.andThen(svc => svc.create(body).pipe( Effect.retry( pipe( Schedule.recurs(3), Schedule.addDelay(() => Duration.seconds(10)), ), ), )), Effect.andThen(parseResponse), Effect.andThen(data => c.json(data, 201)), Effect.orElseSucceed(() => c.json({ message: "create failed" }, 500)), Effect.withSpan("POST /.employee.controller"), )
const result = await ServicesRuntime.runPromise(program) return result })
return app}
Update Routes
import { Effect } from "effect"import * as S from "effect/Schema"import { Hono } from "hono"import { describeRoute } from "hono-openapi"import { resolver, validator } from "hono-openapi/effect"import { ServicesRuntime } from "../../runtimes/index.js"import { Branded, EmployeeSchema, Helpers } from "../../schema/index.js"import { EmployeeServiceContext } from "../../services/employee/index.js"
const updateEmployeeResponseSchema = EmployeeSchema.Schema.omit("deletedAt")
const updateEmployeeDocs = describeRoute({ responses: { 200: { content: { "application/json": { schema: resolver(updateEmployeeResponseSchema), }, }, description: "Update Employees", }, 500: { content: { "application/json": { schema: resolver(updateEmployeeResponseSchema), }, }, description: "Update Employees Error", }, }, tags: ["Employee"],})
const validateUpdateEmployeeRequestBody = validator("json", EmployeeSchema.UpdateSchema)const validateUpdateEmployeeRequestParam = validator("param", S.Struct({ employeeId: Branded.EmployeeIdFromString,}))
export function setupEmployeePutRoutes() { const app = new Hono()
app.put("/:employeeId", updateEmployeeDocs, validateUpdateEmployeeRequestBody, validateUpdateEmployeeRequestParam, async (c) => { const data = c.req.valid("json") const { employeeId } = c.req.valid("param")
const parseResponse = Helpers.fromSchemaToObjectEffect(updateEmployeeResponseSchema)
const program = EmployeeServiceContext.pipe( Effect.andThen(svc => svc.update(employeeId, data)), Effect.andThen(parseResponse), Effect.andThen(data => c.json(data, 200)), Effect.orElseSucceed(() => c.json({ message: "update failed" }, 500)), Effect.withSpan("PUT /.employee.controller"), )
const result = await ServicesRuntime.runPromise(program)
return result })
return app}
Delete Routes
import { Effect } from "effect"import * as S from "effect/Schema"import { Hono } from "hono"import { describeRoute } from "hono-openapi"import { resolver, validator } from "hono-openapi/effect"import { ServicesRuntime } from "../../runtimes/index.js"import { Branded, EmployeeSchema, Helpers } from "../../schema/index.js"import { EmployeeServiceContext } from "../../services/employee/index.js"
const deleteEmployeResponseSchema = EmployeeSchema.Schema.omit("deletedAt")
const deleteEmployeeDocs = describeRoute({ responses: { 200: { content: { "application/json": { schema: resolver(deleteEmployeResponseSchema), }, }, description: "Get Employee by EmployeeId", }, }, tags: ["Employee"],})
const validateDeleteEmployeeRequest = validator("param", S.Struct({ employeeId: Branded.EmployeeIdFromString,}))
export function setupRoutes() { const app = new Hono()
app.delete("/:employeeId", deleteEmployeeDocs, validateDeleteEmployeeRequest, async (c) => { const { employeeId } = c.req.valid("param")
const parseResponse = Helpers.fromObjectToSchemaEffect(deleteEmployeResponseSchema)
const program = EmployeeServiceContext.pipe( Effect.andThen(svc => svc.removeById(employeeId)), Effect.andThen(parseResponse), Effect.andThen(data => c.json(data, 200)), Effect.orElseSucceed(() => c.json({ message: "delete failed" }, 500)), Effect.withSpan("DELETE /:employeeId.employee.controller"), )
const result = await ServicesRuntime.runPromise(program)
return result })
return app}