{"_id":"@dwidge/zodios-express","_rev":"1-e1a5b28b8ed4de523e57d02b94675f37","name":"@dwidge/zodios-express","dist-tags":{"latest":"10.5.1"},"versions":{"10.5.1":{"name":"@dwidge/zodios-express","version":"10.5.1","keywords":["express","zod","rpc","validation"],"author":{"name":"ecyrbe","email":"ecyrbe@gmail.com"},"license":"MIT","_id":"@dwidge/zodios-express@10.5.1","maintainers":[{"name":"dwidge","email":"dwidge+npm@gmail.com"}],"homepage":"https://github.com/ecyrbe/zodios-express","bugs":{"url":"https://github.com/ecyrbe/zodios-express/issues"},"dist":{"shasum":"bb37472a3ada930b55e122b6c8ecf58d980aad81","tarball":"https://registry.npmjs.org/@dwidge/zodios-express/-/zodios-express-10.5.1.tgz","fileCount":6,"integrity":"sha512-w5664a/xg8vI2OUgVCMSh6VUdGQDOCRQ6jlDeYTSooIEJxMQ+a+3kyT/OURwnandtQ/XRjvlBRXzURfwH4THTA==","signatures":[{"sig":"MEUCIGqK6rc+IlxzcB+ZyYl4K8liV9r4phflKucUu7/cGO8ZAiEAysQRWG3f8Hj+f0GWXT+SewiqmLUvT7gz0LFSnN3onew=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":21721,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkK0iWACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoYuw//aBw2t4xxX8q9FLDINe1ZdiIQ5npVCOgOHYEr1ldV3kBHPdSm\r\nbfSET3s5Y82Wt3Wci22+CQyVH9BcW5zHHtioirPP68NgxwHMjMe5B+TOAGwW\r\nbmwPnhuCRtIKI89fO5c1Vvm+EgEZAT3cWdpcT9PCHGPIhQX0vaDAwtWJeZWj\r\nm1Ti5eIcVjn73uankqU4NjaEFFn/PLp3foxbrpx7IpU9mpI/G6KagxLxQuKN\r\nkn3VpSKPonmUGYigrVnIVfZea4Q9jOOGCrUhWyJzLko0jb+7bveXyvTQMi86\r\nkpVZE+HzHKSgErutVryXAax7YXBaqMPxjc9rX64aSNTU5SzflynONP349oeq\r\n/A2gG3EISnp2/CAJqmiMdJqCyYx4CQlGL9cOS3cygyhjdUjro/twrrdK8Wz3\r\npwSw66ueKwO8m6Tc0vL4FCAMQeTF3kYJahVVNlSmajkVjmvEL1BQEifCSgfs\r\nEmalJArLlzMQWwvY7etay/RutJivhbdI78FV8QVh4QgILMVXyy4tVMjCPYP+\r\nPDgLH9xuQribSDvRi4YLGmdCunByGoMtf83LjVB5+wc7JIwJ4GpF/BQZg2Bd\r\nlf1Bw0QZ89MMEmjs+CYsDPINv1GwOTbrX0U0bXcVj2FmicEk8C9ll3hRxIyz\r\ntT9U2Tk1kzDNel/jQmBc01xyPhyi5js0Y4o=\r\n=s4Qt\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","module":"lib/index.mjs","exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.mjs","require":"./lib/index.js"},"./package.json":"./package.json"},"gitHead":"b465e14fe2c02bab196ddf1673576bf85189ca7e","scripts":{"rc":"npm version prerelease --preid=rc","test":"jest --coverage","build":"tsup","example":"ts-node examples/jsonplaceholder.ts","major-rc":"npm version premajor --preid=rc","minor-rc":"npm version preminor --preid=rc","patch-rc":"npm version prepatch --preid=rc","prebuild":"rimraf lib"},"typings":"lib/index.d.ts","_npmUser":{"name":"dwidge","email":"dwidge+npm@gmail.com"},"repository":{"url":"git+https://github.com/ecyrbe/zodios-express.git","type":"git"},"_npmVersion":"9.5.1","description":"Typescript express server","directories":{},"_nodeVersion":"19.8.1","_hasShrinkwrap":false,"devDependencies":{"zod":"3.21.4","jest":"29.5.0","tsup":"6.3.0","axios":"1.3.4","rimraf":"4.4.1","express":"4.18.2","ts-jest":"29.1.0","ts-node":"10.9.1","supertest":"6.3.3","typescript":"5.0.3","@jest/types":"^29.5.0","@types/jest":"29.5.0","@types/node":"18.15.11","@zodios/core":"10.8.1","@types/express":"4.17.17","@types/supertest":"2.0.12"},"peerDependencies":{"zod":"^3.x","express":"4.x","@zodios/core":">=10.4.4 <11.0.0"},"_npmOperationalInternal":{"tmp":"tmp/zodios-express_10.5.1_1680558230022_0.6331355578838131","host":"s3://npm-registry-packages"}}},"time":{"created":"2023-04-03T21:43:49.939Z","modified":"2024-10-13T05:48:47.256Z","10.5.1":"2023-04-03T21:43:50.188Z"},"bugs":{"url":"https://github.com/ecyrbe/zodios-express/issues"},"author":{"name":"ecyrbe","email":"ecyrbe@gmail.com"},"license":"MIT","homepage":"https://github.com/ecyrbe/zodios-express","keywords":["express","zod","rpc","validation"],"repository":{"url":"git+https://github.com/ecyrbe/zodios-express.git","type":"git"},"description":"Typescript express server","maintainers":[{"email":"dwidge+npm@gmail.com","name":"dwidgedev"}],"readme":" <h1 align=\"center\">Zodios Express</h1>\n <p align=\"center\">\n   <a href=\"https://github.com/ecyrbe/zodios-express\">\n     <img align=\"center\" src=\"https://raw.githubusercontent.com/ecyrbe/zodios/main/docs/logo.svg\" width=\"128px\" alt=\"Zodios logo\">\n   </a>\n </p>\n <p align=\"center\">\n    Zodios express is a typescript end to end typesafe adapter for express using <a href=\"https://github.com/colinhacks/zod\">zod</a>\n    <br/>\n </p>\n \n <p align=\"center\">\n   <a href=\"https://www.npmjs.com/package/@zodios/express\">\n   <img src=\"https://img.shields.io/npm/v/@zodios/express.svg\" alt=\"langue typescript\">\n   </a>\n   <a href=\"https://www.npmjs.com/package/@zodios/express\">\n   <img alt=\"npm\" src=\"https://img.shields.io/npm/dw/@zodios/express\">\n   </a>\n   <a href=\"https://github.com/ecyrbe/zodios/blob/main/LICENSE\">\n    <img alt=\"GitHub\" src=\"https://img.shields.io/github/license/ecyrbe/zodios-express\">   \n   </a>\n   <img alt=\"GitHub Workflow Status\" src=\"https://img.shields.io/github/workflow/status/ecyrbe/zodios-express/CI\">\n </p>\n\nhttps://user-images.githubusercontent.com/633115/185851987-554f5686-cb78-4096-8ff5-c8d61b645608.mp4\n\n# What is it ?\n\nIt's an express adapter for zodios that helps you type your express routes.\n  \n- really simple centralized API declaration\n- router endpoints autocompletion\n- typescript autocompletion for query, path, header and body input parameters (`req` is fully typed)\n- typescript autocompletion for response body (`res.json()`)\n- input validation thanks to zod\n- openapi specification generation out of the box (using swagger)\n- end to end typesafe APIs (a la tRPC when using both @zodios/express and @zodios/core)\n  \n**Table of contents:**\n\n- [What is it ?](#what-is-it-)\n- [Install](#install)\n- [How to use it ?](#how-to-use-it-)\n  - [`zodiosApp` : Declare your API for fullstack end to end type safety](#zodiosapp--declare-your-api-for-fullstack-end-to-end-type-safety)\n  - [`zodiosRouter` : Split your application with multiple routers](#zodiosrouter--split-your-application-with-multiple-routers)\n  - [Error Handling](#error-handling)\n- [Roadmap](#roadmap)\n\n# Install\n\n```bash\n> npm install @zodios/express\n```\n\nor\n\n```bash\n> yarn add @zodios/express\n```\n\n# How to use it ?\n\nFor an almost complete example on how to use zodios and how to split your APIs declarations, take a look at [dev.to](examples/dev.to/) example.\n\n## `zodiosApp` : Declare your API for fullstack end to end type safety\n\nHere is an example of API declaration with Zodios.\n  \nin a common directory (ex: `src/common/api.ts`) :\n\n```typescript\nimport { makeApi } from \"@zodios/core\";\nimport { z } from \"zod\";\n\nconst userApi = makeApi([\n  {\n    method: \"get\",\n    path: \"/users/:id\", // auto detect :id and ask for it in apiClient get params\n    alias: \"getUser\", // optionnal alias to call this endpoint with it\n    description: \"Get a user\",\n    response: z.object({\n      id: z.number(),\n      name: z.string(),\n    }),\n  },\n]);\n```\n\nin your frontend (ex: `src/client/api.ts`) :\n\n```typescript\nimport { Zodios } from \"@zodios/core\";\nimport { userApi } from \"../../common/api\";\n\nconst apiClient = new Zodios(\n  \"https://jsonplaceholder.typicode.com\",\n  userApi\n);\n\n//   typed                     alias   auto-complete params\n//     ▼                        ▼                   ▼\nconst user = await apiClient.getUser({ params: { id: 1 } });\n```\n\nin your backend (ex: `src/server/router.ts`) :\n```typescript\nimport { zodiosApp } from \"@zodios/express\";\nimport { userApi } from \"../../common/api\";\n\n// just an express adapter that is aware of  your api, app is just an express app with type annotations and validation middlewares\nconst app = zodiosApp(userApi);\n\n//  auto-complete path  fully typed and validated input params (body, query, path, header)\n//          ▼           ▼    ▼\napp.get(\"/users/:id\", (req, res) => {\n  // res.json is typed thanks to zod\n  res.json({\n    //   auto-complete req.params.id\n    //              ▼\n    id: req.params.id,\n    name: \"John Doe\",\n  });\n})\n\napp.listen(3000);\n```\n\n## `zodiosRouter` : Split your application with multiple routers\n\nWhen organizing your express application, you usually want to split your API declarations into separate Routers.\nYou can use the `zodiosRouter` to do that with a `zodiosApp` without APIs attached.\n\n```typescript\nimport { zodiosApp, zodiosRouter } from \"@zodios/express\";\n\nconst app = zodiosApp(); // just an axpess app with type annotations\nconst userRouter = zodiosRouter(userApi); // just an express router with type annotations and validation middlewares\nconst adminRouter = zodiosRouter(adminApi); // just an express router with type annotations and validation middlewares\n\nconst app.use(userRouter,adminRouter);\n\napp.listen(3000);\n```\n## Error Handling\n\nZodios express can infer the status code to match your API error response and also have your errors correctly typed.\n\n```typescript\nimport { makeApi } from \"@zodios/core\";\nimport { zodiosApp } from \"@zodios/express\";\nimport { z } from \"zod\";\n\nconst userApi = makeApi([\n  {\n    method: \"get\",\n    path: \"/users/:id\", // auto detect :id and ask for it in apiClient get params\n    alias: \"getUser\", // optionnal alias to call this endpoint with it\n    description: \"Get a user\",\n    response: z.object({\n      id: z.number(),\n      name: z.string(),\n    }),\n    errors: [\n      {\n        status: 404,\n        response: z.object({\n          code: z.string(),\n          message: z.string(),\n          id: z.number(),\n        }),\n      }, {\n        status: 'default', // default status code will be used if error is not 404\n        response: z.object({\n          code: z.string(),\n          message: z.string(),\n        }),\n      },\n    ],\n  },\n]);\n\nconst app = zodiosApp(userApi);\napp.get(\"/users/:id\", (req, res) => {\n  try {\n    const id = +req.params.id;\n    const user = service.findUser(id);\n    if(!user) {\n      // match error 404 schema with auto-completion\n      res.status(404).json({\n        code: \"USER_NOT_FOUND\",\n        message: \"User not found\",\n        id, // compile time error if you forget to add id\n      });\n    } else {\n      // match response schema with auto-completion\n      res.json(user);\n    }\n  } catch(err) {\n    // match default error schema with auto-completion\n    res.status(500).json({\n      code: \"INTERNAL_ERROR\",\n      message: \"Internal error\",\n    });\n  }\n})\n\napp.listen(3000);\n```\n\n# Roadmap\n\n- [] add support for swagger/openapi generation\n- [] add utilities to combine api declarations to match the express router api\n- [] add autocompletion for express `app.name()`\n","readmeFilename":"README.md"}