{"id":13454911,"url":"https://github.com/openapistack/openapi-backend","last_synced_at":"2025-03-24T07:32:14.240Z","repository":{"id":33205007,"uuid":"154916760","full_name":"openapistack/openapi-backend","owner":"openapistack","description":"Build, Validate, Route, Authenticate and Mock using OpenAPI","archived":false,"fork":false,"pushed_at":"2025-02-12T19:50:01.000Z","size":4997,"stargazers_count":635,"open_issues_count":100,"forks_count":85,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-18T05:15:21.583Z","etag":null,"topics":["express","hacktoberfest","mock","nodejs","openapi","router","serverless","swagger"],"latest_commit_sha":null,"homepage":"https://openapistack.co","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/openapistack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":"anttiviljami","open_collective":"openapi-stack","custom":["https://buymeacoff.ee/anttiviljami"]}},"created_at":"2018-10-27T02:31:25.000Z","updated_at":"2025-03-03T18:15:32.000Z","dependencies_parsed_at":"2023-12-29T11:02:03.384Z","dependency_job_id":"d8b04f72-1ccd-433c-a14e-b483131d8d2b","html_url":"https://github.com/openapistack/openapi-backend","commit_stats":{"total_commits":593,"total_committers":32,"mean_commits":18.53125,"dds":0.7065767284991569,"last_synced_commit":"71735ae656688e86eeaa20fd0511c12724648708"},"previous_names":["openapistack/openapi-backend","anttiviljami/openapi-backend"],"tags_count":118,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openapistack%2Fopenapi-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openapistack%2Fopenapi-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openapistack%2Fopenapi-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openapistack%2Fopenapi-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openapistack","download_url":"https://codeload.github.com/openapistack/openapi-backend/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244920431,"owners_count":20532032,"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","hacktoberfest","mock","nodejs","openapi","router","serverless","swagger"],"created_at":"2024-07-31T08:00:59.310Z","updated_at":"2025-03-24T07:32:13.577Z","avatar_url":"https://github.com/openapistack.png","language":"TypeScript","funding_links":["https://github.com/sponsors/anttiviljami","https://opencollective.com/openapi-stack","https://buymeacoff.ee/anttiviljami"],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cspan id=\"npm--fix-hidden-readme-header\"\u003e\u003c/span\u003e\n\n\u003ch1 align=\"center\"\u003e\u003cimg alt=\"openapi-backend\" src=\"https://github.com/openapistack/openapi-backend/raw/main/header.png\" style=\"max-width:50rem\"\u003e\u003c/h1\u003e\n\n[![CI](https://github.com/openapistack/openapi-backend/workflows/CI/badge.svg)](https://github.com/openapistack/openapi-backend/actions?query=workflow%3ACI)\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/openapistack/openapi-backend/blob/main/LICENSE)\n[![npm version](https://img.shields.io/npm/v/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend)\n[![npm downloads](https://img.shields.io/npm/dw/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend)\n[![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/openapi-backend.svg)](https://www.npmjs.com/package/openapi-backend?activeTab=dependencies)\n![npm type definitions](https://img.shields.io/npm/types/openapi-backend.svg)\n[![Buy me a coffee](https://img.shields.io/badge/donate-buy%20me%20a%20coffee-orange)](https://buymeacoff.ee/anttiviljami)\n\n\u003cp align=\"center\"\u003e\u003cb\u003eBuild, Validate, Route, Authenticate, and Mock using OpenAPI definitions.\u003c/b\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eOpenAPI Backend is a Framework-agnostic middleware tool for building beautiful APIs with \u003ca href=\"https://github.com/OAI/OpenAPI-Specification\"\u003eOpenAPI Specification\u003c/a\u003e.\u003c/p\u003e\n\n## Features\n\n- [x] Build APIs by describing them in [OpenAPI specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md)\n- [x] Register handlers for [operationIds](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#fixed-fields-8)\nto route requests in your favourite Node.js backend\n- [x] Use [JSON Schema](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#data-types) to validate\nAPI requests and/or responses. OpenAPI Backend uses the [AJV](https://ajv.js.org/) library under the hood for performant validation\n- [x] Register Auth / Security Handlers for [OpenAPI Security Schemes](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)\nto authorize API requests\n- [x] Auto-mock API responses using [OpenAPI examples objects](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#example-object)\nor [JSON Schema definitions](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#schema-object)\n- [x] Built with TypeScript, types included\n- [x] Optimised runtime routing and validation. **No generated code!**\n- [x] OpenAPI 3.1 support\n\n## Documentation\n\n**New!** OpenAPI Backend documentation is now found on [openapistack.co](https://openapistack.co)\n\nhttps://openapistack.co/docs/openapi-backend/intro\n\n## Quick Start\n\nFull [example projects](https://github.com/openapistack/openapi-backend/tree/main/examples) included in the repo\n\n```\nnpm install --save openapi-backend\n```\n\n```javascript\nimport OpenAPIBackend from 'openapi-backend';\n\n// create api with your definition file or object\nconst api = new OpenAPIBackend({ definition: './petstore.yml' });\n\n// register your framework specific request handlers here\napi.register({\n  getPets: (c, req, res) =\u003e res.status(200).json({ result: 'ok' }),\n  getPetById: (c, req, res) =\u003e res.status(200).json({ result: 'ok' }),\n  validationFail: (c, req, res) =\u003e res.status(400).json({ err: c.validation.errors }),\n  notFound: (c, req, res) =\u003e res.status(404).json({ err: 'not found' }),\n});\n\n// initalize the backend\napi.init();\n```\n\n### Express\n\n```javascript\nimport express from 'express';\n\nconst app = express();\napp.use(express.json());\napp.use((req, res) =\u003e api.handleRequest(req, req, res));\napp.listen(9000);\n```\n\n[See full Express example](https://github.com/openapistack/openapi-backend/tree/main/examples/express)\n\n[See full Express TypeScript example](https://github.com/openapistack/openapi-backend/tree/main/examples/express-typescript)\n\n### AWS Serverless (Lambda)\n\n```javascript\n// API Gateway Proxy handler\nmodule.exports.handler = (event, context) =\u003e\n  api.handleRequest(\n    {\n      method: event.httpMethod,\n      path: event.path,\n      query: event.queryStringParameters,\n      body: event.body,\n      headers: event.headers,\n    },\n    event,\n    context,\n  );\n```\n\n[See full AWS SAM example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-sam)\n\n[See full AWS CDK example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-cdk)\n\n[See full SST example](https://github.com/openapistack/openapi-backend/tree/main/examples/aws-sst)\n\n[See full Serverless Framework example](https://github.com/openapistack/openapi-backend/tree/main/examples/serverless-framework)\n\n### Azure Function\n\n```javascript\nmodule.exports = (context, req) =\u003e\n  api.handleRequest(\n    {\n      method: req.method,\n      path: req.params.path,\n      query: req.query,\n      body: req.body,\n      headers: req.headers,\n    },\n    context,\n    req,\n  );\n```\n\n[See full Azure Function example](https://github.com/openapistack/openapi-backend/tree/main/examples/azure-function)\n\n### Fastify\n\n```ts\nimport fastify from 'fastify';\n\nfastify.route({\n  method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],\n  url: '/*',\n  handler: async (request, reply) =\u003e\n    api.handleRequest(\n      {\n        method: request.method,\n        path: request.url,\n        body: request.body,\n        query: request.query,\n        headers: request.headers,\n      },\n      request,\n      reply,\n    ),\n});\nfastify.listen();\n```\n\n[See full Fastify example](https://github.com/openapistack/openapi-backend/tree/main/examples/fastify)\n\n### Hapi\n\n```javascript\nimport Hapi from '@hapi/hapi';\n\nconst server = new Hapi.Server({ host: '0.0.0.0', port: 9000 });\nserver.route({\n  method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],\n  path: '/{path*}',\n  handler: (req, h) =\u003e\n    api.handleRequest(\n      {\n        method: req.method,\n        path: req.path,\n        body: req.payload,\n        query: req.query,\n        headers: req.headers,\n      },\n      req,\n      h,\n    ),\n});\nserver.start();\n```\n\n[See full Hapi example](https://github.com/openapistack/openapi-backend/tree/main/examples/hapi-typescript)\n\n\n### Koa\n\n```javascript\nimport Koa from 'koa';\nimport bodyparser from 'koa-bodyparser';\n\nconst app = new Koa();\n\napp.use(bodyparser());\napp.use((ctx) =\u003e\n  api.handleRequest(\n    ctx.request,\n    ctx,\n  ),\n);\napp.listen(9000);\n```\n\n[See full Koa example](https://github.com/openapistack/openapi-backend/tree/main/examples/koa)\n\n## Registering Handlers for Operations\n\nHandlers are registered for [`operationIds`](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.2.md#fixed-fields-8)\nfound in the OpenAPI definitions. You can register handlers as shown above with [`new OpenAPIBackend()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#parameter-optshandlers)\nconstructor opts, or using the [`register()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#registeroperationid-handler)\nmethod.\n\n```javascript\nasync function getPetByIdHandler(c, req, res) {\n  const id = c.request.params.id;\n  const pet = await pets.getPetById(id);\n  return res.status(200).json({ result: pet });\n}\napi.register('getPetById', getPetByIdHandler);\n// or\napi.register({\n  getPetById: getPetByIdHandler,\n});\n```\n\nOperation handlers are passed a special [Context object](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#context-object)\nas the first argument, which contains the parsed request, the\nmatched API operation and input validation results. The other arguments in the example above are Express-specific\nhandler arguments.\n\n## Request validation\n\nThe easiest way to enable request validation in your API is to register a [`validationFail`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validationfail-handler)\nhandler.\n\n```javascript\nfunction validationFailHandler(c, req, res) {\n  return res.status(400).json({ status: 400, err: c.validation.errors });\n}\napi.register('validationFail', validationFailHandler);\n```\n\nOnce registered, this handler gets called if any JSON Schemas in either operation parameters (in: path, query, header,\ncookie) or requestPayload don't match the request.\n\nThe context object `c` gets a `validation` property with the [validation result](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validationresult-object).\n\n## Response validation\n\nOpenAPIBackend doesn't automatically perform response validation for your handlers, but you can register a\n[`postResponseHandler`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#postresponsehandler-handler)\nto add a response validation step using [`validateResponse`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validateresponseres-operation).\n\n```javascript\napi.register({\n  getPets: (c) =\u003e {\n    // when a postResponseHandler is registered, your operation handlers' return value gets passed to context.response\n    return [{ id: 1, name: 'Garfield' }];\n  },\n  postResponseHandler: (c, req, res) =\u003e {\n    const valid = c.api.validateResponse(c.response, c.operation);\n    if (valid.errors) {\n      // response validation failed\n      return res.status(502).json({ status: 502, err: valid.errors });\n    }\n    return res.status(200).json(c.response);\n  },\n});\n```\n\nIt's also possible to validate the response headers using [`validateResponseHeaders`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#validateresponseheadersheaders-operation-opts).\n\n```javascript\napi.register({\n  getPets: (c) =\u003e {\n    // when a postResponseHandler is registered, your operation handlers' return value gets passed to context.response\n    return [{ id: 1, name: 'Garfield' }];\n  },\n  postResponseHandler: (c, req, res) =\u003e {\n    const valid = c.api.validateResponseHeaders(res.headers, c.operation, {\n      statusCode: res.statusCode,\n      setMatchType: 'exact',\n    });\n    if (valid.errors) {\n      // response validation failed\n      return res.status(502).json({ status: 502, err: valid.errors });\n    }\n    return res.status(200).json(c.response);\n  },\n});\n```\n\n## Auth / Security Handlers\n\nIf your OpenAPI definition contains [Security Schemes](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securitySchemeObject)\nyou can register security handlers to handle authorization for your API:\n\n```yaml\ncomponents:\n  securitySchemes:\n  - ApiKey:\n      type: apiKey\n      in: header\n      name: x-api-key\nsecurity:\n  - ApiKey: []\n```\n\n```javascript\napi.registerSecurityHandler('ApiKey', (c) =\u003e {\n  const authorized = c.request.headers['x-api-key'] === 'SuperSecretPassword123';\n  // truthy return values are interpreted as auth success\n  // you can also add any auth information to the return value\n  return authorized;\n});\n```\n\nThe authorization status and return values of each security handler can be\naccessed via the [Context Object](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#context-object)\n\nYou can also register an [`unauthorizedHandler`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#unauthorizedhandler-handler)\nto handle unauthorized requests.\n\n```javascript\napi.register('unauthorizedHandler', (c, req, res) =\u003e {\n  return res.status(401).json({ err: 'unauthorized' })\n});\n```\n\nSee examples:\n- [API Key auth (express)](https://github.com/openapistack/openapi-backend/tree/main/examples/express-apikey-auth)\n- [JWT auth (express)](https://github.com/openapistack/openapi-backend/tree/main/examples/express-jwt-auth)\n\n## Mocking API responses\n\nMocking APIs just got really easy with OpenAPI Backend! Register a [`notImplemented`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md#notimplemented-handler)\nhandler and use [`mockResponseForOperation()`](https://github.com/openapistack/openapi-backend/blob/main/DOCS.md##mockresponseforoperationoperationid-opts)\nto generate mock responses for operations with no custom handlers specified yet:\n\n```javascript\napi.register('notImplemented', (c, req, res) =\u003e {\n  const { status, mock } = c.api.mockResponseForOperation(c.operation.operationId);\n  return res.status(status).json(mock);\n});\n```\n\nOpenAPI Backend supports mocking responses using both OpenAPI example objects and JSON Schema:\n```yaml\npaths:\n  '/pets':\n    get:\n      operationId: getPets\n      summary: List pets\n      responses:\n        200:\n          $ref: '#/components/responses/PetListWithExample'\n  '/pets/{id}':\n    get:\n      operationId: getPetById\n      summary: Get pet by its id\n      responses:\n        200:\n          $ref: '#/components/responses/PetResponseWithSchema'\ncomponents:\n  responses:\n    PetListWithExample:\n      description: List of pets\n      content:\n        'application/json':\n          example:\n            - id: 1\n              name: Garfield\n            - id: 2\n              name: Odie\n    PetResponseWithSchema:\n      description: A single pet\n      content:\n        'application/json':\n          schema:\n            type: object\n            properties:\n              id:\n                type: integer\n                minimum: 1\n              name:\n                type: string\n                example: Garfield\n```\n\nThe example above will yield:\n```javascript\napi.mockResponseForOperation('getPets'); // =\u003e { status: 200, mock: [{ id: 1, name: 'Garfield' }, { id: 2, name: 'Odie' }]}\napi.mockResponseForOperation('getPetById'); // =\u003e { status: 200, mock: { id: 1, name: 'Garfield' }}\n```\n\n[See full Mock API example on Express](https://github.com/openapistack/openapi-backend/tree/main/examples/express-ts-mock)\n\n## Commercial support\n\nFor assistance with integrating openapi-backend in your company, reach out at support@openapistack.co.\n\n## Contributing\n\nOpenAPI Backend is Free and Open Source Software. Issues and pull requests are more than welcome!\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenapistack%2Fopenapi-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenapistack%2Fopenapi-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenapistack%2Fopenapi-backend/lists"}