{"id":15416297,"url":"https://github.com/herber/warp","last_synced_at":"2025-10-17T05:56:02.364Z","repository":{"id":40765195,"uuid":"269468149","full_name":"herber/warp","owner":"herber","description":"🦄🚀  Minimalist framework for building APIs in TypeScript.","archived":false,"fork":false,"pushed_at":"2023-03-04T23:10:41.000Z","size":1559,"stargazers_count":9,"open_issues_count":20,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-20T02:50:39.985Z","etag":null,"topics":["api","authentication","decorators","dependency-injection","express","hacktoberfest","middleware","nestjs","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/herber.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-04T21:21:30.000Z","updated_at":"2024-04-02T07:54:16.000Z","dependencies_parsed_at":"2024-10-21T15:59:40.872Z","dependency_job_id":null,"html_url":"https://github.com/herber/warp","commit_stats":{"total_commits":103,"total_committers":3,"mean_commits":"34.333333333333336","dds":"0.23300970873786409","last_synced_commit":"15981ec5d202ea38cd01818bf596cb66b3fb0b19"},"previous_names":["varld/warp"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herber%2Fwarp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herber%2Fwarp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herber%2Fwarp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/herber%2Fwarp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/herber","download_url":"https://codeload.github.com/herber/warp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248863110,"owners_count":21173935,"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":["api","authentication","decorators","dependency-injection","express","hacktoberfest","middleware","nestjs","typescript"],"created_at":"2024-10-01T17:11:33.282Z","updated_at":"2025-10-17T05:55:57.330Z","avatar_url":"https://github.com/herber.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://i.imgur.com/OLt55Xe.png\" width=\"100%\" alt=\"Warp logo\"\u003e\n\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003e\n  \u003cb\u003eMinimalist framework for building APIs in TypeScript.\u003c/b\u003e \n\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#getting-started\"\u003eGetting Started\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#examples\"\u003eExamples\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#authentication\"\u003eAuthentication\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#accessing-the-request-body\"\u003eValidation\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#dependency-injection\"\u003eDependency Injection\u003c/a\u003e\n  \u003cspan\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e\n  \u003ca href=\"https://github.com/varld/warp/blob/master/readme.md#testing\"\u003eTesting\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n## Features\n\n- 🔋 **Batteries includes:** Cors, dependency injection and body parsing are already set up.\n- 🚀 **Written in Typescript:** No need to worry about inconsistent types.\n- 🤷‍♂️ **Unopinionated:** We don't force you to do anything.\n- 🏭 **Built on Express:** Warp is compatible with all existing Express packages.\n- ✨ **Support for `async`/`await`:** Warp helps you escape the callback hell.\n- 🔥 **Easy to get started with:** One file with a few lines of code is all you need.\n- 👋 **Built in authentication:** Warp has build in support for token authentication.\n\n## Why\n\nAbout a year ago I fell in love with Nest.js, however after building a couple of bigger projects with it I noticed, that it forces me to do things in counterintuitive ways while offering features that I hardly ever used. On the other hand, Express is great but really barebones. You have to set up body parsing, authentication and routing for every project.\n\n**Warp** aims to be a combination of the great API that Nest.js offers while maintaining the simplicity of Express. Warp is a clever combination of a few standard packages, which together offer controller based routing, authentication, dependency injection, validation and reduce code duplication.\n\n## Getting Started\n\n### Using Warp CLI\n\nWarp CLI creates a simple TypeScript project with a very basic Warp API and test.\n\n```bash\n# Create warp project in current directory\nnpx create-warp-app\n\n# Create warp project in (./my-api)\nnpx create-warp-app ./my-api\n```\n\n### Custom Setup\n\nYou can easily set up your own warp project. This guide assumes that you already have a Node.js project with TypeScript set up.\n\n#### Install Warp\n\n```bash\n# Using npm\nnpm install @varld/warp\n\n# Using yarn\nyarn add @varld/warp\n```\n\n#### Setting up TypeScript\n\nWarp uses decorators and reflection, those two features have to be enabled in the `tsconfig.json` file.\n\n```json\n{\n  \"compilerOptions\": {\n    ...\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```\n\n#### Creating a Simple API\n\n```typescript\nimport warp, { Controller, Get, Param } from '@varld/warp';\n\n@Controller('/')\nclass GreetingController {\n  @Get('/:name')\n  greet(@Param('name') name: string) {\n    return `Hello ${name}`;\n  }\n}\n\nlet app = warp({\n  controllers: [GreetingController]\n});\n\napp.listen(3000);\n```\n\nThat's it! 🎉 Go ahead and visit [`http://localhost:3000/your-name`](http://localhost:3000/your-name) in a browser.\n\nNow let's take a look at what the code above does exactly.\n\n1. On the first line, we import `warp` and a few decorators, which we are using later.\n2. Nest, we create a controller-class. All controllers must have the `@Controller('/...')` decorator, with the base-path of the controller as the first argument.\n3. Within the controller class we create an HTTP-Handler (called greet) using the `@Get('/...')` decorator. This decorator indicates, that the handler listens to `GET` request under the path supplied in the first argument. Of course there are decorators for all other HTTP-Methods as well.\n4. The `greet` has a single argument decorated with `@Param('name')`. This indicates, that we want to extract a `path-param` called `name` from the url.\n5. Withing the `greet` method we return a string containing the supplied name.\n6. Now we set up a warp-instance and tell it about our controller. The `warp` function returns a _standard Express app_.\n7. Finally we tell the warp-instance to listen to port 3000.\n\nPretty simple, right. ✌️\n\n## Usage\n\n### File Structure\n\nWhile Warp does not force you do adhere to a specific file structure, there is one that we think works very well.\n\n```\n/src\n  package.json\n  index.ts\n  /controllers\n    controllerName.ts\n  /services\n    serviceName.ts\n/tests\n  testName.spec.ts\n```\n\nIn the root of the project, there is an `index.ts`-file, which create a Warp instance and sets everything up.\nThe `controllers` directory houses all controllers. Each controller should have its own file named accordingly.\nThe `services` directory contains all services. Each file should contain just one service.\n\nIf you are using authentication, you could extract the authenticator into its own file.\n\n### Handler Methods\n\nWarp has decorators for all popular HTTP-Methods. They all basically work the same.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/') // Listens to GET requests\n  getSomething() {\n    /*...*/\n  }\n\n  @Post('/') // Listens to POST requests\n  createSomething() {\n    /*...*/\n  }\n\n  @Put('/') // Listens to PUT requests\n  overrideSomething() {\n    /*...*/\n  }\n\n  @Patch('/') // Listens to PATCH requests\n  updateSomething() {\n    /*...*/\n  }\n\n  @Delete('/') // Listens to DELETE requests\n  deleteSomething() {\n    /*...*/\n  }\n\n  @Head('/') // Listens to HEAD requests\n  headRequest() {\n    /*...*/\n  }\n\n  @Options('/') // Listens to OPTIONS requests\n  optionsRequest() {\n    /*...*/\n  }\n}\n```\n\n### Middleware\n\nWarp is compatible with all existing Express middleware, however installing it is a bit different.\n\n#### Global Middleware\n\nGlobal middleware is executed on every request. You can optionally specify if it should be executed before or after the request handler methods.\n\n```typescript\n// Default behavior\nlet app = warp({\n  controllers: [\n    /*...*/\n  ],\n  middleware: [\n    aMiddlewareFunction,\n    anotherOne\n    // ...\n  ]\n});\n\n// Specify when the middleware should be executed\nlet app = warp({\n  controllers: [\n    /*...*/\n  ],\n  middleware: [\n    {\n      // Will be executed before request handlers\n      execution: 'before',\n      middleware: setupMiddleware\n    },\n    {\n      // Will be executed after request handlers\n      execution: 'after',\n      middleware: cleanupMiddleware\n    }\n    // ...\n  ]\n});\n```\n\n#### Controller-based middleware\n\nController-based middleware will be executed before every handler method within a controller. This is useful if you want to perform an action for every handler of a controller.\n\n```typescript\n@Controller('/', [\n  aMiddlewareFunction,\n  anotherOne\n  // ...\n])\nclass MyController {\n  // ...\n}\n```\n\n#### Handler-based middleware\n\nHandler-based middleware is specific to selected request handlers. Handler-based middleware can be specified using the second parameter of `@Get` or any other method decorator or using the `@Middleware()` decorator. You can also use bot variant together.\n\n```typescript\n@Get('/:name', [\n  aMiddlewareFunction,\n  // ...\n])\n@Middleware(anotherMiddlewareFunction)\n@Middleware([\n  aMiddlewareFunctionInAnArray,\n  oneMore,\n  // ...\n])\nhandler() {\n  // ...\n}\n```\n\n### Guards\n\nAs the name suggests, guards are used to protect handlers. Guards are decorators, which receive a function that returns either `true` or `false`. If `true` is returned, the handler will be executed normally. If `false` is returned, the handler will not be executed and a `Forbidden`-Error will sent to the client instead. The function in the guard receives the `request` object as its first argument.\n\nGuards are especially useful if you want to make a handler only accessible to users with special permissions.\n\n```typescript\n@Get('/')\n@Guard((req) =\u003e false)\nhandler() {\n  return `This will not be executed`;\n}\n```\n\n### Responses\n\nBy default, everything you return in a handler function will be sent to client with the `200` status code. If you return a string, that string will sent to the client as is. If you return an object, that object will be converted to JSON. Depending on the return type a matching `Content-Type`-header will be chosen. You can use responses to manipulate this behavior.\n\n#### JSON Response\n\nEverything you provide to the JSON-Response will be converted to JSON. In addition to the response data you can also specify a custom status code and additional http-headers.\n\n```typescript\n@Get('/')\nhandler() {\n  return new JSONResponse({\n    /* some data */\n  });\n}\n\n// With a statuscode and custom headers\n@Get('/')\nhandler() {\n  return new JSONResponse({\n    /* some data */\n  }, 202, {\n    'Custom': 'Header'\n  });\n}\n```\n\n#### File Response\n\nFile responses can be used to serve local files.\n\n`new FileResponse(filePath, [expressSendFileOptions, status, headers])`\n\n#### Next Response\n\nThe next response can be used to call Express's `next()` function. Which tells Express to continue to the next middleware.\n\n`new NextResponse()`\n\n#### Redirect Response\n\nUsing the redirect response, you can redirect the client to a different url.\n\n`new RedirectResponse(location, [status, headers])`\n\n#### Render Response\n\nThe render response can be used to access Express's internal template rendering. For this to work you must configure a view engine first.\n\n```typescript\nimport warp, { Controller, Get, Param } from '@varld/warp';\n\n@Controller('/')\nclass MyController {\n  @Get('/')\n  render() {\n    return new RenderResponse('view name', {\n      /* view data */\n    });\n  }\n}\n\nlet app = warp({\n  controllers: [MyController]\n});\n\napp.set('view engine', 'a view engine');\n\napp.listen(3000);\n```\n\n#### Simple Response\n\nThe simple response behaves similar to just returning the value, however using the simple response you can optionally add a status code and custom headers.\n\n`new SimpleResponse(data, [status, headers])`\n\n### Accessing request data\n\nWarp offers a variety of decorators you can use to get request data, like path parameters, query, cookies and more.\n\n#### Query parameters\n\nYou can access query parameters using the `@Query()` decorator. If you want to get a specific value from the query object you can also pass the value's name as a parameter.\n\n```typescript\n@Controller('/')\nclass MyController {\n  // Get all query parameters as an object\n  @Get('/all')\n  handler(@Query() everything: any) {\n    // ...\n  }\n\n  // Get a single query parameter called name\n  @Get('/one')\n  handler(@Query('name') name: string) {\n    // ...\n  }\n}\n```\n\n#### Headers\n\nThe header parameter behaves similar to the `@Query()`. When `@Header()` receives no argument you will get an object containing all header values, however you can optionally specify a header name as the first parameter.\n\n```typescript\n@Controller('/')\nclass MyController {\n  // Get all headers as an object\n  @Get('/all')\n  handler(@Header() everything: any) {\n    // ...\n  }\n\n  // Get the \"Content-Type\" header\n  @Get('/one')\n  handler(@Header('Content-Type') contentType: string) {\n    // ...\n  }\n}\n```\n\n#### Cookies\n\nUsing the cookie parameter, you can easily access cookies. When no parameter is specified, you will get an array containing all cookies. Optionally you can specify a cookie's name in the first parameter.\n\n```typescript\n@Controller('/')\nclass MyController {\n  // Get all cookies as an object\n  @Get('/all')\n  handler(@Cookie() everything: any) {\n    // ...\n  }\n\n  // Get a single cookie called token\n  @Get('/one')\n  handler(@Cookie('token') token: string) {\n    // ...\n  }\n}\n```\n\nWarp also has decorators for setting and clearing cookies.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/')\n  handler(@SetCookie() setCookie: CookieSetter, @ClearCookie() clearCookie: CookieClearer) {\n    setCookie('name', 'value', {\n      /* options */\n    });\n\n    clearCookie('name');\n  }\n}\n```\n\nYou can use `setCookie` to set cookies. The first param must be the cookies name, the second param is the cookies value using the third param, you can optionally specify [additional options](http://expressjs.com/en/4x/api.html#res.cookie), like an expiration date.\n\n`clearCookie` can be used to remove a cookie. The first parameter is the cookies name.\n\n#### Path Parameters\n\nWarp inherits support for parameters in the URL path from Express. You can use the `@Param()` decorator to access all or one specify url parameter.\n\n```typescript\n@Controller('/')\nclass MyController {\n  // Get all params as an object\n  @Get('/users/:userId/task/:taskId')\n  handler(@Param() everything: any) {\n    // ...\n  }\n\n  // Get a single param called userId\n  @Get('/users/:userId')\n  handler(@Param('userId') userId: string) {\n    // ...\n  }\n}\n```\n\n#### Request Object\n\nIn some cases you might want to access Express's native request object. You can do this using the `@Req()` decorator. You should avoid using `@Req()` if possible and use the decorators listed above instead.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/')\n  handler(@Req() req: Request) {\n    // ...\n  }\n}\n```\n\n#### Response Object\n\nYou might need to access Express's native response object. You can do this using the `@Res()` decorator. In most cases you should use Warp's response classes instead.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/')\n  handler(@Res() res: Response) {\n    // ...\n  }\n}\n```\n\n#### Custom Parameters\n\nIn addition to the built in parameter decorators, Warp also offers the ability to create custom parameters.\n\n```typescript\nimport { BaseParam /*...*/ } from '@varld/warp';\n\nlet CustomParam = () =\u003e {\n  BaseParam((req, res) =\u003e req.ip);\n};\n\n@Controller('/')\nclass MyController {\n  @Get('/')\n  handler(@CustomParam() ip: string) {\n    return `Your IP-Address is: ${ip}`;\n  }\n}\n```\n\n### Enabling CORS\n\nWarp includes native support for cors. You can enable cors when creating a new Warp instance.\n\n```typescript\nlet app = warp({\n  controllers: [\n    /*...*/\n  ],\n  cors: true\n});\n\n// ...\n```\n\n`cors` is optional and can be a `boolean` or a [cors-options-object](https://github.com/expressjs/cors#configuration-options). By default the `cors` value is `false` and hance cors is disabled.\n\n### Accessing the Request Body\n\nWarp has support for accessing, validating and transforming the request body using the `@Body()` decorator.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Post('/')\n  handler(@Body() body: any) {\n    // do something with the body\n  }\n}\n```\n\n#### Validating The Request Body\n\nRequest body validation is achieved using [class validator](https://github.com/typestack/class-validator). Class validator makes it easy to specify validation rules using decorators.\n\n```typescript\nclass MyBody {\n  @Length(5, 25)\n  title: string;\n\n  @Contains('hello')\n  text: string;\n\n  @IsInt()\n  @Min(0)\n  @Max(5)\n  rating: number;\n}\n\n@Controller('/')\nclass MyController {\n  @Post('/')\n  handler(@Body() body: MyBody) {\n    // The body has already been validated\n    // and can be used now.\n  }\n}\n```\n\nIf the body is not valid, a not acceptable error, including an array of validation-errors will be sent to the client. In this case the handler will not be executed.\n\n### Authentication\n\nAuthentication is important for many APIs. Warp includes support for standard token authentication using a header or a query parameter. By default warp is configured to support bearer authentication.\n\n#### The Authenticator\n\nWarp automatically extracts a token from the request object. If a token exists, the token will be handed to an async authenticator function, which you have to implement.\n\nWarp expects you to return a user. This user can be of any type.\n\nIf no user is returned, warp will not execute any handlers and send an unauthorized error to the client.\n\n```typescript\nlet app = warp({\n  controllers: [\n    /*...*/\n  ],\n  authenticator: async (token: string, req: Request) =\u003e {\n    // fetch user by token from database\n    let user = await db.getUserByToken(token);\n\n    return user;\n  }\n});\n```\n\n#### Enabling Authentication\n\nWarp supports two types of authentication: global authentication, which protects every route of the warp instance and handler based authentication, using the `@Authenticated()` decorator.\n\n**Global authentication:**\n\n```typescript\nlet app = warp({\n  // ...\n  authentication: {\n    global: true\n  }\n});\n```\n\n**Handler based authentication:**\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/')\n  @Authenticated()\n  handler() {\n    // The user is authenticated\n  }\n}\n```\n\n#### Accessing The User\n\nIn authenticated routes, the user (from the authenticator function) can be accessed using the `@User()` decorator.\n\n```typescript\n@Controller('/')\nclass MyController {\n  @Get('/')\n  @Authenticated()\n  handler(@User() user: MyUser) {\n    // Do something with the user\n  }\n}\n```\n\n#### Authentication Options\n\nBy default, Warp will check the `Authorization` header and the `access_token` query parameter. Warp expects tokens in the `Authorization` header to be prefixed with the `bearer` keyword. This behavior can be altered using `authentication` object when creating a warp instance.\n\n```typescript\nlet app = warp({\n  // ...\n  authentication: {\n    global: false,\n    header: 'Authorization',\n    headerScheme: 'bearer',\n    query: 'access_token'\n  }\n});\n```\n\n### Logging and Error Handling\n\nYou can override Warp's default error logger by providing a `logger` function when creating a Wrap instance. The function receives the error as its first parameter.\n\n```typescript\nlet app = warp({\n  controllers: [...],\n  logger: (error: Error | HTTPException) =\u003e {\n    // do something with the error\n  }\n});\n```\n\n### Dependency Injection\n\nWarp has support for dependency injection in controllers using [typedi](https://github.com/typestack/typedi). Injectable classes must be marked using the `@Service()` decorator.\n\n```typescript\n@Service()\nclass MyService {\n  doSomething() {\n    return 'did something';\n  }\n}\n\n@Controller('/')\nclass MyController {\n  constructor(private myService: MyService) {}\n\n  @Get('/')\n  handler() {\n    return this.myService.doSomething();\n  }\n}\n```\n\n### HTTP Errors\n\nWarp automatically catches errors thrown in middleware, param functions and http handlers. If the exception is unknown, Warp will return an internal server error. However, you can use Warp's builtin HTTP-Exceptions to specify which error should be returned to the client. Warp has an exception for all standard http errors.\n\n```typescript\nimport { GoneException } from '@varld/warp';\n\n@Controller('/')\nclass MyController {\n  @Get('/')\n  gone() {\n    throw new GoneException();\n  }\n}\n```\n\nThe response sent to the client looks like this:\n\n```json\n{\n  \"status\": \"410\",\n  \"code\": \"gone\"\n}\n```\n\nThe code can be customized using the exceptions first parameter: `throw new GoneException('It is gone!')`.\n\n#### Custom HTTP Errors\n\nFor some usecases you might need custom HTTP-Exceptions. You can create those by extending the the `HttpException` class.\n\n```typescript\nimport { HttpException } from '@varld/warp';\n\nexport class CustomException extends HttpException {\n  constructor() {\n    super(\n      {\n        code: 'A custom error',\n        additionalField: 'something'\n      },\n      418\n    );\n  }\n}\n```\n\nAs you can see, the super function expects two parameters, the first one can be a `string` or an object which must contain the `code` property, but can also contain additional properties. The second parameters is an HTTP-status-code.\n\n### Testing\n\nTesting a warp app is very simple, since warp apps are basically just Express apps. The simples way to test an api built with warp is using [supertest](https://github.com/visionmedia/supertest). Supertest has also been used to test the warp library itself, take a look at [the tests](https://github.com/varld/warp/tree/master/packages/warp/tests) to learn more.\n\n```typescript\ntest('serves basic api', async () =\u003e {\n  @Controller('/')\n  class IndexController {\n    @Get('/')\n    sendHello() {\n      return 'hello';\n    }\n  }\n\n  let app = warp({\n    controllers: [IndexController]\n  });\n\n  let response = await request(app).get('/');\n\n  expect(response.status).toEqual(200);\n  expect(response.text).toEqual('hello');\n});\n```\n\n## Examples\n\n- [A basic Warp app](https://github.com/varld/warp/tree/master/examples/simple)\n- [Warp, TypeORM and authentication](https://github.com/varld/warp/tree/master/examples/with-typeorm-auth)\n- [Warp's test suite](https://github.com/varld/warp/tree/master/packages/warp/tests)\n\n## Questions and Answers\n\n### What was the inspiration for Warp?\n\nWarp was mostly inspired by [Nest.js](https://nestjs.com/), [Tachijs](https://github.com/BoostIO/tachijs) and [Express](https://expressjs.com/). All of those libraries are amazing and I greatly appreciate their maintainers! Warp would not exist without those libraries.\n\n### Can't I just use Nest.js?\n\nYeah! Nest.js is great, but it includes a lot of bloat that most people don't need or don't even know about, like _Interceptors_, or built in support for microservice. Warp aims be much simple, while offering the features most APIs need.\n\nIf you need a bunch of abstractions and enterprise-level features, then Nest.js is great. If you want to build an API (big or small) but don't need all of those features, then Warp is a great choice.\n\n### Can't I just use Express?\n\nSure! Warp is built on Express. Express is battle tested and very unopinionated, so you can build basically anything with Express. Since Express does not do that much by itself you will have to write a lot of boilerplate the get started. Warp comes will all of the basics, like body parsing and cors, already setup and extends Express with controllers, useful decorators and authentication.\n\n### Is Warp safe to use?\n\nHonestly, Warp is a really simple library. All it does is glueing a few other libraries together. All of those libraries are battle tested and used by thousands (sometimes even millions) of developers. In addition to that Warp is very well tested (99% coverage). So it is safe to say that you can use Warp in production. However, if you do encounter any problems or inconveniences feel free to open an issue or poll request on Warp's GitHub.\n\n## License\n\nMIT © [Tobias Herber](https://herber.space)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherber%2Fwarp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fherber%2Fwarp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fherber%2Fwarp/lists"}