{"id":18160731,"url":"https://github.com/blankeos/tsrest-hono","last_synced_at":"2025-04-07T03:54:41.843Z","repository":{"id":190658169,"uuid":"683032477","full_name":"Blankeos/tsrest-hono","owner":"Blankeos","description":"🔥 hono + typesafety with tsrest example","archived":false,"fork":false,"pushed_at":"2023-08-25T18:54:37.000Z","size":28,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-13T08:41:26.518Z","etag":null,"topics":["example","example-project","hono","ts-rest"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Blankeos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-25T12:42:25.000Z","updated_at":"2023-08-25T17:56:01.000Z","dependencies_parsed_at":"2023-08-25T20:38:50.642Z","dependency_job_id":null,"html_url":"https://github.com/Blankeos/tsrest-hono","commit_stats":null,"previous_names":["blankeos/tsrest-hono"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Ftsrest-hono","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Ftsrest-hono/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Ftsrest-hono/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Blankeos%2Ftsrest-hono/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Blankeos","download_url":"https://codeload.github.com/Blankeos/tsrest-hono/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247589831,"owners_count":20963022,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["example","example-project","hono","ts-rest"],"created_at":"2024-11-02T08:09:11.916Z","updated_at":"2025-04-07T03:54:41.822Z","avatar_url":"https://github.com/Blankeos.png","language":"TypeScript","readme":"# ts-rest and hono example\n\nI'm using the ts-rest-hono library for this. This is how I summarize the process of creating APIs with ts-rest.\n\nIt's built on these concepts:\n\n1. 📜 **Contract**\n2. 🤝 **Server**\n3. 🔌 **Endpoint Creation**\n\n### 📜 1. Contract (`@ts-rest/core`)\n\nIf you used GraphQL before, think of this as your \"Schema\". This is where you define what **methods**, **paths**, and **responses** your API endpoints use. It's a very small file that only defines what your API does. The magic is that your Server(Backend) and your Client(Frontend) agrees on this.\n\n```ts\nimport { initContract } from \"@ts-rest/core\";\nimport { z } from \"zod\";\n\nconst c = initContract();\n\nexport const TodoSchema = z.object({\n  id: z.string(),\n  title: z.string(),\n  completed: z.boolean(),\n});\n\nexport const contract = c.router({\n  getTodos: {\n    method: \"GET\",\n    path: \"/todos\",\n    responses: {\n      201: TodoSchema.array(),\n    },\n    summary: \"Create \",\n  },\n  createTodo: {\n    method: \"POST\",\n    path: \"/todo\",\n    responses: {\n      201: TodoSchema,\n    },\n    body: z.object({\n      title: z.string(),\n      completed: z.boolean(),\n    }),\n    summary: \"Creates a todo.\",\n  },\n});\n```\n\n### 🤝 2. Server (`ts-rest-hono`)\n\nThis is kind of like your \"resolver\" (in GraphQL) for the contract. In TS-REST, you need a package that plays well with the server you choose. The officially supported ones are Nest, Next, and Express. For Hono, we use `ts-rest-hono`. The function we use to make the **server** is `initServer`.\n\n**Server** is also called your \"router\". 💡\n\n```ts\nimport { initServer } from \"ts-rest-hono\";\nimport { contract } from \"./contract\";\nimport { nanoid } from \"nanoid\"; // optional\n\nconst s = initServer();\n\ntype Todo = {\n  id: string;\n  title: string;\n  completed: boolean;\n};\n\nconst todos: Todo[] = [];\n\nconst router = s.router(contract, {\n  getTodos: async () =\u003e {\n    return {\n      status: 201,\n      body: todos,\n    };\n  },\n  createTodo: async ({ body: { completed, title } }) =\u003e {\n    const newTodo = {\n      id: nanoid(),\n      title,\n      completed,\n    };\n\n    todos.push(newTodo);\n\n    return {\n      status: 201,\n      body: newTodo,\n    };\n  },\n});\n\nexport default router;\n```\n\n### 🔌 3. Endpoint Creation (`ts-rest-hono`)\n\nIn Hono, you need an creation package that plays well with the server you choose. Again, we use `ts-rest-hono`. The function we use for **endpoint creation** is `createHonoEndpoints`.\n\nEndpoint creation hooks up your **contract**, **server(router)**, and **app(the actual backend server framework)**. (very confusing I know, it's hard to be consistent with the terminology here)\n\n```ts\nimport { serve } from \"@hono/node-server\";\nimport { Hono } from \"hono\";\nimport { createHonoEndpoints } from \"ts-rest-hono\";\nimport { contract } from \"./contract\";\nimport router from \"./honoRouter\";\n\nconst app = new Hono();\n\napp.get(\"/\", (c) =\u003e {\n  return c.text(\"🔥 Hello Hono!\");\n});\n\ncreateHonoEndpoints(contract, router, app);\n\nserve(app, (info) =\u003e {\n  console.log(`Listening on http://localhost:${info.port}`);\n});\n```\n\n### Conclusions\n\nSo TS-REST isn't really \"backend agnostic\" in the sense that it can work with any backend. It's a yes and no answer:\n\n- \"yes\" - it can run on any backend. You only need to define a **contract**.\n- \"no\" - BUT you need to have a package to handle the **server (router)** and **endpoint creation** parts. The officially supported ones are Nest, Next, and Express. For Hono, we use `ts-rest-hono`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblankeos%2Ftsrest-hono","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblankeos%2Ftsrest-hono","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblankeos%2Ftsrest-hono/lists"}