{"id":13767656,"url":"https://github.com/danprince/zhttp","last_synced_at":"2026-04-17T10:03:39.426Z","repository":{"id":46073103,"uuid":"427429384","full_name":"danprince/zhttp","owner":"danprince","description":"🛡️ Typesafe HTTP endpoints with Express, Zod, and Static Path","archived":false,"fork":false,"pushed_at":"2021-11-16T12:44:54.000Z","size":90,"stargazers_count":3,"open_issues_count":9,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-26T11:02:22.737Z","etag":null,"topics":["express","http","typescript","zod"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danprince.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-12T16:40:20.000Z","updated_at":"2024-03-23T22:52:31.000Z","dependencies_parsed_at":"2022-09-26T18:30:41.398Z","dependency_job_id":null,"html_url":"https://github.com/danprince/zhttp","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danprince%2Fzhttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danprince%2Fzhttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danprince%2Fzhttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danprince%2Fzhttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danprince","download_url":"https://codeload.github.com/danprince/zhttp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245791966,"owners_count":20672671,"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":["express","http","typescript","zod"],"created_at":"2024-08-03T16:01:10.684Z","updated_at":"2025-10-20T10:43:22.792Z","avatar_url":"https://github.com/danprince.png","language":"TypeScript","funding_links":[],"categories":["Projects Using Zod"],"sub_categories":[],"readme":"# zhttp\nA small library that brings [`zod`][zod], [`express`][express], and [`static-path`][static-path] together to create type safe HTTP endpoints for clients and servers.\n\n- [Reference](./docs)\n  - [`endpoint`](./docs/modules/index.md#endpoint)\n  - [`createRouter`](./docs/modules/express.md#createRouter)\n  - [`fetchJson`](./docs/modules/fetch.md#fetchJson)\n  - [`createClient`](./docs/modules/fetch.md#createClient)\n\n## Getting Started\nInstall `zhttp` and its peer dependencies.\n\n```sh\nnpm i @danprince/zhttp express @types/express zod static-path\n```\n\n- `static-path` requires `typescript@^4.1` (for [template literal types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html))\n- `zod` requires you to run TypeScript in [strict mode](https://www.typescriptlang.org/tsconfig#strict).\n\n## Example\nDefine your endpoints somewhere that both your client and server can import from.\n\n```ts\n// shared/endpoints.ts\nimport { endpoint } from \"@danprince/zhttp\";\nimport { z } from \"zod\";\nimport { path } from \"path\";\n\nexport let sendMessage = endpoint({\n  // static-path definition\n  path: path(\"/message/:to\"),\n\n  // \"post\" | \"get\" | \"patch\" | \"put\" | \"delete\" | \"head\"\n  method: \"post\",\n\n  // zod request body schema\n  request: z.object({\n    subject: z.string(),\n    text: z.string(),\n  }),\n\n  // zod response body schema\n  response: z.object({\n    status: z.union([\n      z.literal(\"success\"),\n      z.literal(\"pending\"),\n      z.literal(\"failure\"),\n    ]),\n  }),\n});\n```\n\nThen create corresponding server side route handlers.\n\n```ts\n// server/routes.ts\nimport { createRouter } from \"@danprince/zhttp/express\";\nimport { sendMessage } from \"../shared/endpoints\";\n\nlet router = createRouter();\n\nrouter.use(sendMessage, async (req, res) =\u003e {\n  // Type safe access from req.body\n  let { subject, text } = req.body;\n\n  // ...\n\n  // Type safe res.body methods\n  res.json({ status: \"success\" });\n});\n\n// router.routes() is an Express.Router\n```\n\nAnd finally, the client side.\n\n```ts\n// client/index.ts\nimport { fetchJson } from \"@danprince/zhttp/fetch\";\nimport { sendMessage } from \"../shared/endpoints\";\n\nlet res = await fetchJson(sendMessage, {\n  params: { to: \"howard\" },\n  body: {\n    subject: \"Hello!\",\n    text: \"This is a message\",\n  },\n});\n\n// Type safe response\nres.status\n```\n\n[express]: https://github.com/expressjs/express\n[zod]: https://github.com/colinhacks/zod\n[static-path]: https://github.com/garybernhardt/static-path\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanprince%2Fzhttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanprince%2Fzhttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanprince%2Fzhttp/lists"}