{"id":13525400,"url":"https://github.com/fastify/fastify-sensible","last_synced_at":"2025-04-11T01:42:19.856Z","repository":{"id":31437749,"uuid":"127635922","full_name":"fastify/fastify-sensible","owner":"fastify","description":"Defaults for Fastify that everyone can agree on","archived":false,"fork":false,"pushed_at":"2025-04-01T05:32:03.000Z","size":219,"stargazers_count":494,"open_issues_count":2,"forks_count":40,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-04-10T15:27:15.834Z","etag":null,"topics":["defaults","fastify","fastify-plugin","http","utility"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@fastify/sensible","language":"JavaScript","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/fastify.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},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2018-04-01T14:20:12.000Z","updated_at":"2025-04-02T23:31:11.000Z","dependencies_parsed_at":"2023-01-14T19:02:52.474Z","dependency_job_id":"140d760e-4fd7-4636-8fc4-3c6f8460df71","html_url":"https://github.com/fastify/fastify-sensible","commit_stats":{"total_commits":190,"total_committers":41,"mean_commits":4.634146341463414,"dds":0.7210526315789474,"last_synced_commit":"17828866cf85f986670277cb79fc410565bb7bc3"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-sensible","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-sensible/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-sensible/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-sensible/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/fastify-sensible/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248327488,"owners_count":21085251,"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":["defaults","fastify","fastify-plugin","http","utility"],"created_at":"2024-08-01T06:01:18.357Z","updated_at":"2025-04-11T01:42:19.849Z","avatar_url":"https://github.com/fastify.png","language":"JavaScript","readme":"# @fastify/sensible\n\n[![CI](https://github.com/fastify/fastify-sensible/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/fastify-sensible/actions/workflows/ci.yml)\n[![NPM version](https://img.shields.io/npm/v/@fastify/sensible.svg?style=flat)](https://www.npmjs.com/package/@fastify/sensible)\n[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)\n\nDefaults for Fastify that everyone can agree on™.\u003cbr\u003e\nThis plugin adds some useful utilities to your Fastify instance, see the API section to learn more.\n\n*Why are these APIs here and not included with Fastify?\u003cbr\u003e\nBecause Fastify aims to be as small and focused as possible, every utility that is not essential should be shipped as a standalone plugin.*\n\n## Install\n```\nnpm i @fastify/sensible\n```\n\n### Compatibility\n\n| Plugin version | Fastify version |\n| -------------- | --------------- |\n| `\u003e=6.x`        | `^5.x`          |\n| `^5.x`         | `^4.x`          |\n| `^4.x`         | `^3.x`          |\n| `\u003e=2.x \u003c4.x`   | `^2.x`          |\n| `^1.x`         | `^1.x`          |\n\n\nPlease note that if a Fastify version is out of support, then so are the corresponding versions of this plugin\nin the table above.\nSee [Fastify's LTS policy](https://github.com/fastify/fastify/blob/main/docs/Reference/LTS.md) for more details.\n\n## Usage\n```js\nconst fastify = require('fastify')()\nfastify.register(require('@fastify/sensible'))\n\nfastify.get('/', (req, reply) =\u003e {\n  reply.notFound()\n})\n\nfastify.get('/async', async (req, reply) =\u003e {\n  throw fastify.httpErrors.notFound()\n})\n\nfastify.get('/async-return', async (req, reply) =\u003e {\n  return reply.notFound()\n})\n\nfastify.listen({ port: 3000 })\n```\n\n## Shared JSON Schema for HTTP errors\nIf you set the `sharedSchemaId` option, a shared JSON Schema is added and can be used in your routes.\n```js\nconst fastify = require('fastify')()\nfastify.register(require('@fastify/sensible'), {\n  sharedSchemaId: 'HttpError'\n})\n\nfastify.get('/async', {\n  schema: {\n    response: {\n      404: { $ref: 'HttpError' }\n    }\n  },\n  handler: async (req, reply) =\u003e {\n    return reply.notFound()\n  }\n})\n\nfastify.listen({ port: 3000 })\n```\n\n## API\n#### `fastify.httpErrors`\nObject that exposes `createError` and all of the `4xx` and `5xx` error constructors.\n\nUse of `4xx` and `5xx` error constructors follows the same structure as [`new createError[code || name]([msg]))`](https://github.com/jshttp/http-errors#new-createerrorcode--namemsg) in [http-errors](https://github.com/jshttp/http-errors):\n\n```js\n // the custom message is optional\nconst notFoundErr = fastify.httpErrors.notFound('custom message')\n```\n\n`4xx`\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003ebadRequest()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eunauthorized()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003epaymentRequired()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eforbidden()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003enotFound()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003emethodNotAllowed()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003enotAcceptable()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eproxyAuthenticationRequired()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003erequestTimeout()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003econflict()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003egone()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003elengthRequired()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003epreconditionFailed()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003epayloadTooLarge()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003euriTooLong()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eunsupportedMediaType()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003erangeNotSatisfiable()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eexpectationFailed()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eimateapot()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003emisdirectedRequest()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eunprocessableEntity()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003elocked()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003efailedDependency()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003etooEarly()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eupgradeRequired()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003epreconditionRequired()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003etooManyRequests()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003erequestHeaderFieldsTooLarge()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eunavailableForLegalReasons()\u003c/b\u003e\u003c/code\u003e\n\n`5xx`\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003einternalServerError()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003enotImplemented()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003ebadGateway()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eserviceUnavailable()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003egatewayTimeout()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003ehttpVersionNotSupported()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003evariantAlsoNegotiates()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003einsufficientStorage()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003eloopDetected()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003ebandwidthLimitExceeded()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003enotExtended()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.httpErrors.\u003cb\u003enetworkAuthenticationRequired()\u003c/b\u003e\u003c/code\u003e\n\n`createError`\n\nUse of `createError` follows the same structure as [`createError([status], [message], [properties])`](https://github.com/jshttp/http-errors#createerrorstatus-message-properties) in [http-errors](https://github.com/jshttp/http-errors):\n\n```js\nconst err = fastify.httpErrors.createError(404, 'This video does not exist!')\n```\n\n#### `reply.[httpError]`\nThe `reply` interface is decorated with all of the functions declared above, using it is easy:\n```js\nfastify.get('/', (req, reply) =\u003e {\n  reply.notFound()\n})\n```\n\n#### `reply.vary`\nThe `reply` interface is decorated with [`jshttp/vary`](https://github.com/jshttp/vary), the API is the same, but you do not need to pass the res object.\n```js\nfastify.get('/', (req, reply) =\u003e {\n  reply.vary('Accept')\n  reply.send('ok')\n})\n```\n\n#### `reply.cacheControl`\nThe `reply` interface is decorated with a helper to configure cache control response headers.\n```js\n// configure a single type\nfastify.get('/', (req, reply) =\u003e {\n  reply.cacheControl('public')\n  reply.send('ok')\n})\n\n// configure multiple types\nfastify.get('/', (req, reply) =\u003e {\n  reply.cacheControl('public')\n  reply.cacheControl('immutable')\n  reply.send('ok')\n})\n\n// configure a type time\nfastify.get('/', (req, reply) =\u003e {\n  reply.cacheControl('max-age', 42)\n  reply.send('ok')\n})\n\n// the time can be defined as string\nfastify.get('/', (req, reply) =\u003e {\n  // all the formats of github.com/vercel/ms are supported\n  reply.cacheControl('max-age', '1d') // will set to 'max-age=86400'\n  reply.send('ok')\n})\n```\n\n#### `reply.preventCache`\nThe `reply` interface is decorated with a helper to set the cache control header to a no caching configuration.\n```js\nfastify.get('/', (req, reply) =\u003e {\n  // will set cache-control to 'no-store, max-age=0, private'\n  // and for HTTP/1.0 compatibility\n  // will set pragma to 'no-cache' and expires to 0\n  reply.preventCache()\n  reply.send('ok')\n})\n```\n\n#### `reply.revalidate`\nThe `reply` interface is decorated with a helper to set the cache control header to a no caching configuration.\n```js\nfastify.get('/', (req, reply) =\u003e {\n  reply.revalidate() // will set to 'max-age=0, must-revalidate'\n  reply.send('ok')\n})\n```\n\n#### `reply.staticCache`\nThe `reply` interface is decorated with a helper to set the cache control header to a public and immutable configuration.\n```js\nfastify.get('/', (req, reply) =\u003e {\n  // the time can be defined as a string\n  reply.staticCache(42) // will set to 'public, max-age=42, immutable'\n  reply.send('ok')\n})\n```\n\n#### `reply.stale`\nThe `reply` interface is decorated with a helper to set the cache control header for [stale content](https://tools.ietf.org/html/rfc5861).\n```js\nfastify.get('/', (req, reply) =\u003e {\n  // the time can be defined as a string\n  reply.stale('while-revalidate', 42)\n  reply.stale('if-error', 1)\n  reply.send('ok')\n})\n```\n\n#### `reply.maxAge`\nThe `reply` interface is decorated with a helper to set max age of the response. It can be used in conjunction with `reply.stale`, see [here](https://web.dev/stale-while-revalidate/).\n```js\nfastify.get('/', (req, reply) =\u003e {\n  // the time can be defined as a string\n  reply.maxAge(86400)\n  reply.stale('while-revalidate', 42)\n  reply.send('ok')\n})\n```\n\n#### `request.forwarded`\nThe `request` interface is decorated with [`jshttp/forwarded`](https://github.com/jshttp/forwarded), the API is the same, but you do not need to pass the request object:\n```js\nfastify.get('/', (req, reply) =\u003e {\n  reply.send(req.forwarded())\n})\n```\n\n#### `request.is`\nThe `request` interface is decorated with [`jshttp/type-is`](https://github.com/jshttp/type-is), the API is the same but you do not need to pass the request object:\n```js\nfastify.get('/', (req, reply) =\u003e {\n  reply.send(req.is(['html', 'json']))\n})\n```\n\n#### `assert`\nVerify if a given condition is true, if not it throws the specified http error.\u003cbr\u003e Useful if you work with *async* routes:\n```js\n// the custom message is optional\nfastify.assert(\n  req.headers.authorization, 400, 'Missing authorization header'\n)\n```\nThe `assert` API also exposes the following methods:\n- \u003ccode\u003efastify.assert.\u003cb\u003eok()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003eequal()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003enotEqual()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003estrictEqual()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003enotStrictEqual()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003edeepEqual()\u003c/b\u003e\u003c/code\u003e\n- \u003ccode\u003efastify.assert.\u003cb\u003enotDeepEqual()\u003c/b\u003e\u003c/code\u003e\n\n#### `to`\nAsync await wrapper for easy error handling without try-catch, inspired by [`await-to-js`](https://github.com/scopsy/await-to-js):\n\n```js\nconst [err, user] = await fastify.to(\n  db.findOne({ user: 'tyrion' })\n)\n```\n\n## Contributing\nDo you feel there is some utility that *everyone can agree on* that is not present?\u003cbr\u003e\nOpen an issue and let's discuss it! Even better a pull request!\n\n## Acknowledgments\n\nThe project name is inspired by [`vim-sensible`](https://github.com/tpope/vim-sensible), an awesome package that if you use vim you should use too.\n\n## License\n\nLicensed under [MIT](./LICENSE).\n","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"categories":["JavaScript","\u003ch2 align=\"center\"\u003eAwesome Fastify\u003c/h2\u003e"],"sub_categories":["\u003ch2 align=\"center\"\u003eEcosystem\u003c/h2\u003e"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Ffastify-sensible","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastify%2Ffastify-sensible","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Ffastify-sensible/lists"}