{"id":13392533,"url":"https://github.com/rawrmaan/restyped","last_synced_at":"2025-03-13T18:31:51.599Z","repository":{"id":65412100,"uuid":"105951089","full_name":"rawrmaan/restyped","owner":"rawrmaan","description":"End-to-end typing for REST APIs with TypeScript","archived":false,"fork":false,"pushed_at":"2018-08-02T21:30:16.000Z","size":51,"stargazers_count":312,"open_issues_count":7,"forks_count":10,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-02-16T07:03:08.930Z","etag":null,"topics":["axios","express","nodejs","rest","rest-api","typescript"],"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/rawrmaan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-05T23:40:24.000Z","updated_at":"2024-10-29T11:58:47.000Z","dependencies_parsed_at":"2023-01-23T10:55:01.453Z","dependency_job_id":null,"html_url":"https://github.com/rawrmaan/restyped","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawrmaan%2Frestyped","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawrmaan%2Frestyped/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawrmaan%2Frestyped/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawrmaan%2Frestyped/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rawrmaan","download_url":"https://codeload.github.com/rawrmaan/restyped/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243459113,"owners_count":20294341,"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":["axios","express","nodejs","rest","rest-api","typescript"],"created_at":"2024-07-30T17:00:26.908Z","updated_at":"2025-03-13T18:31:51.322Z","avatar_url":"https://github.com/rawrmaan.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Table of Contents"],"sub_categories":["HTTP"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/images/logo.png\" width=\"350\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  End-to-end typing for REST APIs with TypeScript\n\u003c/p\u003e\n\n## Motivation\n\n[Read the blog post](https://blog.falcross.com/introducing-restyped-end-to-end-typing-for-rest-apis-with-typescript/)\n\n## Benefits\n\n- **End-to-end typing.** Share request and response types between your client\n  and server for ease of use and peace of mind.\n- **Unopinionated.** Works with any new or existing REST API.\n- **Universal.** Can support any server framework or REST client.\n- **~~Lightweight~~ Weightless.** Client and server implementations add no runtime code--It's Just Types™.\n- **Use existing syntax.** Declare and call your routes the same way you always\n  have.\n- **Great for private APIs.** Keep API clients across your organization in sync\n  with the latest changes.\n- **Great for public APIs.** Create a RESTyped definition so TypeScript users\n  can consume your API fully typed.\n- **Easy to learn and use.** Start using RESTyped in less than one minute per\n  route.\n\n## How to use it\n\nRESTyped is a specification (see below). You can use these server and client\npackages along with a RESTyped defintion file to declare and consume APIs in a\ntype-safe manner:\n\n- [restyped-axios](https://github.com/rawrmaan/restyped-axios) - Client wrapper\n  for Axios to consume RESTyped APIs\n- [restyped-express-async](https://github.com/rawrmaan/restyped-express-async) -\n  Server wrapper for express to deliver RESTyped APIs using promises\n- [restyped-hapi](https://github.com/jbpionnier/restyped-hapi) - Server wrapper for Hapi.js routes to deliver RESTyped APIs\n\nYou can help make RESTyped more useful by implementing support in your favorite\nserver framework or HTTP client!\n\n**_RESTyped requires TypeScript 2.4 or higher._**\n\n## Specification\n\nIt's very easy to get started with RESTyped. Just follow a few steps to type\nyour existing API or create a new typed API:\n\n- Your API should be defined in one interface, exported as `{my_api_name}API`\n  from a file ending in `.d.ts`\n- Each route is a top level key in the interface. You should exclude any\n  prefixes like `/api/`.\n- Each route can have up to one key per valid HTTP method:\n  - `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD` or `OPTIONS`\n- Each HTTP method can have one or more of the following keys:\n  - `params`: Route params in the URL (e.g. `/users/:id` would have `id` as a\n    param)\n  - `query`: Query string params, typically used in `GET` requests (e.g.\n    `req.query` in express)\n  - `body`: JSON body object (e.g. `req.body` in express or `data` object in an\n    axios request)\n  - `response`: The route's JSON response\n\nAlso see the spec implementation [base defintions](/spec/index.d.ts).\n\nExample: `my-social-api.d.ts`\n\n```typescript\ninterface User {\n  // Model inteface--could be imported from another file\n  email: string\n  name: string\n  gender: 'Male' | 'Female' | 'Other'\n}\n\nexport interface MySocialAPI {\n  '/users': {\n    // Route name (without prefix, if you have one)\n    GET: {\n      // Any valid HTTP method\n      query: {\n        // Query string params (e.g. /me?includeProfilePics=true)\n        includeProfilePics?: boolean\n      }\n      response: User[] // JSON response\n    }\n  }\n\n  '/user/:id/send-message': {\n    POST: {\n      params: {\n        // Inline route params\n        id: string\n      }\n      body: {\n        // JSON request body\n        message: string\n      }\n      response: {\n        // JSON response\n        success: boolean\n      }\n    }\n  }\n}\n```\n\n## Full-Stack Example\n\n### 1. Define your API\n\n\u003ca href=\"/examples/food-delivery-api.d.ts\"\u003e`food-delivery-api.d.ts`\u003c/a\u003e\n\n```typescript\nexport interface FoodDeliveryAPI {\n  '/me/orders': {\n    POST: {\n      body: {\n        foodItemIds: number[]\n        address: string\n        paymentMethod: 'card' | 'cash'\n      }\n      response: {\n        success: boolean\n        eta?: string\n      }\n    }\n  }\n\n  // ...other routes...\n}\n```\n\n### 2. Declare the API via express\n\n```typescript\nimport RestypedRouter from 'restyped-express-async'\nimport { FoodDeliveryAPI } from './food-delivery-api'\nimport * as express from 'express'\n\nconst app = express()\n\nconst apiRouter = express.Router()\napp.use('/api', apiRouter)\n\nconst router = RestypedRouter\u003cFoodDeliveryAPI\u003e(apiRouter)\n\nrouter.post('/me/orders', async req =\u003e {\n  // Will not compile if you attempt to access an invalid body property\n  const {\n    foodItemIds, // number[]\n    address, // string\n    paymentMethod // 'card' | 'cash'\n  } = req.body\n\n  const success = await OrderModel.order(foodItemIds, address, paymentMethod)\n\n  // Will not compile if returned value is not of type {success: boolean}\n  return { success }\n})\n```\n\n### 3. Consume the API via axios\n\n```typescript\nimport axios from 'restyped-axios'\nimport { FoodDeliveryAPI } from './food-delivery-api'\n\nconst api = axios.create\u003cFoodDeliveryAPI\u003e({\n  baseURL: 'https://fooddelivery.com/api/'\n})\n\nasync function order() {\n  // Will not compile if you pass incorrectly typed body params\n  const res = await api.post('/me/orders', {\n    foodItemIds: [142, 788],\n    address: '1601 Market St, Phiadelphia, PA 19103',\n    paymentMethod: 'cash'\n  })\n\n  // TypeScript knows that res.data is of type {success: boolean, eta?: string}\n  const { success, eta } = res.data\n}\n```\n\n## What RESTyped isn't\n\n- **A replacement for API docs.** A RESTyped spec will help you get the\n  **routes** and **types** right, but doesn't provide any **context** or\n  explanation of your API.\n\n## Popular APIs to try out\n\n- Giphy API:\n  [`restyped-giphy-api`](https://github.com/rawrmaan/restyped-giphy-api)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawrmaan%2Frestyped","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frawrmaan%2Frestyped","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawrmaan%2Frestyped/lists"}