เราจะมาทำ Employee Controller ที่เหลือให้ครบ
1import { Effect } from "effect"2import * as S from "effect/Schema"3import { Hono } from "hono"4import { describeRoute } from "hono-openapi"5import { resolver, validator } from "hono-openapi/effect"6import { ServicesRuntime } from "../../runtimes/index.js"7import { Branded, EmployeeWithRelationsSchema, Helpers } from "../../schema/index.js"8import { EmployeeServiceContext } from "../../services/employee/index.js"9 10const getByIdResponseSchema = EmployeeWithRelationsSchema.Schema.omit("deletedAt")11 12const getByIdDocs = describeRoute({13 responses: {14 200: {15 content: {16 "application/json": {17 schema: resolver(getByIdResponseSchema),18 },19 },20 description: "Get Employee by EmployeeId",21 },22 404: {23 content: {24 "application/json": {25 schema: resolver(S.Struct({26 message: S.String,27 })),28 },29 },30 description: "Get Employee by EmployeeId not found",31 },32 },33 tags: ["Employee"],34})35 36const validateGetByIdRequest = validator("param", S.Struct({37 employeeId: Branded.EmployeeIdFromString,38}))39 40const getManyResponseSchema = S.Array(EmployeeWithRelationsSchema.Schema.omit("deletedAt"))41 42const getManyDocs = describeRoute({43 responses: {44 200: {45 content: {46 "application/json": {47 schema: resolver(getManyResponseSchema),48 },49 },50 description: "Get Employees",51 },52 500: {53 content: {54 "application/json": {55 schema: resolver(S.Struct({56 message: S.String,57 })),58 },59 },60 description: "Get Employees Error",61 },62 },63 tags: ["Employee"],64})65 66export function setupEmployeeGetRoutes() {67 const app = new Hono()68 69 app.get("/:employeeId", getByIdDocs, validateGetByIdRequest, async (c) => {70 const { employeeId } = c.req.valid("param")71 72 const parseResponse = Helpers.fromObjectToSchemaEffect(getByIdResponseSchema)73 74 const program = EmployeeServiceContext.pipe(75 Effect.andThen(svc => svc.findOneById(employeeId)),76 Effect.andThen(parseResponse),77 Effect.andThen(data => c.json(data, 200)),78 Effect.catchTags({79 FindEmployeeByIdError: () => Effect.succeed(c.json({ message: "findOneById error" }, 500)),80 NoSuchElementException: () => Effect.succeed(c.json({ message: "not found employee for id" }, 404)),81 ParseError: () => Effect.succeed(c.json({ message: "findOneById error" }, 500)),82 }),83 Effect.withSpan("GET /:employeeId.employee.controller"),84 )85 86 const result = await ServicesRuntime.runPromise(program)87 return result88 })89 90 app.get("/", getManyDocs, async (c) => {91 const parseResponse = Helpers.fromObjectToSchemaEffect(getManyResponseSchema)92 93 const program = EmployeeServiceContext.pipe(94 // ^? Effect.Effect<..., never, EmployeeServiceContext>95 Effect.tap(() => Effect.log("start finding many employees")),96 Effect.andThen(svc => svc.findMany()),97 Effect.andThen(parseResponse),98 Effect.andThen(data => c.json(data, 200)),99 Effect.tap(() => Effect.log("test")),100 Effect.catchTags({101 FindManyEmployeeError: () => Effect.succeed(c.json({ message: "find many error" }, 500)),102 ParseError: () => Effect.succeed(c.json({ message: "parse error" }, 500)),103 }),104 Effect.annotateLogs({ key: "annotate" }),105 Effect.withLogSpan("test"),106 Effect.withSpan("GET /.employee.controller /"),107 )108 109 const result = await ServicesRuntime.runPromise(program)110 return result111 })112 113 return app114}
1import { Effect } from "effect"2import * as S from "effect/Schema"3import { Hono } from "hono"4import { describeRoute } from "hono-openapi"5import { resolver, validator } from "hono-openapi/effect"6import { ServicesRuntime } from "../../runtimes/index.js"7import { EmployeeSchema, Helpers } from "../../schema/index.js"8import { EmployeeServiceContext } from "../../services/employee/index.js"9 10const responseSchema = EmployeeSchema.Schema.omit("deletedAt")11 12const docs = describeRoute({13 responses: {14 201: {15 content: {16 "application/json": {17 schema: resolver(responseSchema),18 },19 },20 description: "Created Employee",21 },22 500: {23 content: {24 "application/json": {25 schema: resolver(S.Struct({26 message: S.String,27 })),28 },29 },30 description: "Created Employee",31 },32 },33 tags: ["Employee"],34 validateResponse: true,35})36 37const validateRequestBody = validator("json", EmployeeSchema.CreateSchema)38 39export function setupEmployeePostRoutes() {40 const app = new Hono()41 42 app.post("/", docs, validateRequestBody, async (c) => {43 const body = c.req.valid("json")44 45 const parseResponse = Helpers.fromObjectToSchemaEffect(responseSchema)46 47 const program = EmployeeServiceContext.pipe(48 Effect.andThen(svc => svc.create(body).pipe(49 Effect.retry(50 pipe(51 Schedule.recurs(3),52 Schedule.addDelay(() => Duration.seconds(10)),53 ),54 ),55 )),56 Effect.andThen(parseResponse),57 Effect.andThen(data => c.json(data, 201)),58 Effect.orElseSucceed(() => c.json({ message: "create failed" }, 500)),59 Effect.withSpan("POST /.employee.controller"),60 )61 62 const result = await ServicesRuntime.runPromise(program)63 return result64 })65 66 return app67}
1import { Effect } from "effect"2import * as S from "effect/Schema"3import { Hono } from "hono"4import { describeRoute } from "hono-openapi"5import { resolver, validator } from "hono-openapi/effect"6import { ServicesRuntime } from "../../runtimes/index.js"7import { Branded, EmployeeSchema, Helpers } from "../../schema/index.js"8import { EmployeeServiceContext } from "../../services/employee/index.js"9 10const updateEmployeeResponseSchema = EmployeeSchema.Schema.omit("deletedAt")11 12const updateEmployeeDocs = describeRoute({13 responses: {14 200: {15 content: {16 "application/json": {17 schema: resolver(updateEmployeeResponseSchema),18 },19 },20 description: "Update Employees",21 },22 500: {23 content: {24 "application/json": {25 schema: resolver(updateEmployeeResponseSchema),26 },27 },28 description: "Update Employees Error",29 },30 },31 tags: ["Employee"],32})33 34const validateUpdateEmployeeRequestBody = validator("json", EmployeeSchema.UpdateSchema)35const validateUpdateEmployeeRequestParam = validator("param", S.Struct({36 employeeId: Branded.EmployeeIdFromString,37}))38 39export function setupEmployeePutRoutes() {40 const app = new Hono()41 42 app.put("/:employeeId", updateEmployeeDocs, validateUpdateEmployeeRequestBody, validateUpdateEmployeeRequestParam, async (c) => {43 const data = c.req.valid("json")44 const { employeeId } = c.req.valid("param")45 46 const parseResponse = Helpers.fromSchemaToObjectEffect(updateEmployeeResponseSchema)47 48 const program = EmployeeServiceContext.pipe(49 Effect.andThen(svc => svc.update(employeeId, data)),50 Effect.andThen(parseResponse),51 Effect.andThen(data => c.json(data, 200)),52 Effect.orElseSucceed(() => c.json({ message: "update failed" }, 500)),53 Effect.withSpan("PUT /.employee.controller"),54 )55 56 const result = await ServicesRuntime.runPromise(program)57 58 return result59 })60 61 return app62}
1import { Effect } from "effect"2import * as S from "effect/Schema"3import { Hono } from "hono"4import { describeRoute } from "hono-openapi"5import { resolver, validator } from "hono-openapi/effect"6import { ServicesRuntime } from "../../runtimes/index.js"7import { Branded, EmployeeSchema, Helpers } from "../../schema/index.js"8import { EmployeeServiceContext } from "../../services/employee/index.js"9 10const deleteEmployeResponseSchema = EmployeeSchema.Schema.omit("deletedAt")11 12const deleteEmployeeDocs = describeRoute({13 responses: {14 200: {15 content: {16 "application/json": {17 schema: resolver(deleteEmployeResponseSchema),18 },19 },20 description: "Get Employee by EmployeeId",21 },22 },23 tags: ["Employee"],24})25 26const validateDeleteEmployeeRequest = validator("param", S.Struct({27 employeeId: Branded.EmployeeIdFromString,28}))29 30export function setupRoutes() {31 const app = new Hono()32 33 app.delete("/:employeeId", deleteEmployeeDocs, validateDeleteEmployeeRequest, async (c) => {34 const { employeeId } = c.req.valid("param")35 36 const parseResponse = Helpers.fromObjectToSchemaEffect(deleteEmployeResponseSchema)37 38 const program = EmployeeServiceContext.pipe(39 Effect.andThen(svc => svc.removeById(employeeId)),40 Effect.andThen(parseResponse),41 Effect.andThen(data => c.json(data, 200)),42 Effect.orElseSucceed(() => c.json({ message: "delete failed" }, 500)),43 Effect.withSpan("DELETE /:employeeId.employee.controller"),44 )45 46 const result = await ServicesRuntime.runPromise(program)47 48 return result49 })50 51 return app52}