{"name":"cloudworker-router","version":"4.0.5","description":"A router for cloudflare workers","main":"dist/src/index.js","scripts":{"build":"tsc","lint":"eslint src/**","test":"yarn run lint && jest","prepare":"husky install; yarn build","semantic-release":"semantic-release"},"repository":{"type":"git","url":"git+https://github.com/markusahlstrand/cloudworker-router.git"},"keywords":["cloudflare","workers","router"],"author":{"name":"Markus Ahlstrand"},"license":"MIT","bugs":{"url":"https://github.com/markusahlstrand/cloudworker-router/issues"},"homepage":"https://github.com/markusahlstrand/cloudworker-router#readme","devDependencies":{"@cloudflare/workers-types":"^3.16.0","@commitlint/cli":"^17.1.2","@commitlint/config-conventional":"^17.1.0","@commitlint/types":"^17.0.0","@jest/types":"^29.0.3","@semantic-release/git":"^10.0.1","@types/jest":"^29.0.3","@types/node":"^18.7.18","@types/service-worker-mock":"^2.0.1","@typescript-eslint/eslint-plugin":"^5.37.0","@typescript-eslint/parser":"^5.37.0","eslint":"^8.23.1","eslint-config-airbnb-typescript":"^17.0.0","eslint-config-prettier":"^8.5.0","eslint-plugin-import":"^2.26.0","eslint-plugin-jsx-a11y":"^6.6.1","eslint-plugin-prettier":"^4.2.1","husky":"^8.0.1","jest":"^29.0.3","jest-environment-miniflare":"^2.9.0","prettier":"^2.7.1","semantic-release":"^19.0.5","service-worker-mock":"^2.0.5","source-map-support":"^0.5.21","ts-jest":"^29.0.1","ts-loader":"^9.3.1","ts-node":"^10.9.1","typescript":"^4.8.3"},"dependencies":{"path-to-regexp":"^6.2.1"},"types":"./dist/src/index.d.ts","readme":"# Cloudworker Router V4\n\nThe router V4 is an update to make it behave more like koa-router with a the more familiar `async (ctx, next)` syntax.\n\nThe new version accepts passing an array of middlewares in each route, just like the koa-router does. This change is breaking as it's no longer possible to pass the options to path-to-regexp as a third option.\n\nTo make it more flexible it also supports adding RegExp support to the routing in addition to the path-to-regexp strings.\n\nThe router is based on [path-to-regexp](https://github.com/pillarjs/path-to-regexp) for the path matching, which is used by many other routers as well.\n\nThe goal is to make a battery included, opinionated typescript router for cloudflare workers.\n\n- Express style routing with router.get, router.post ..\n- Named URL paramters\n- Multiple route middlewares\n- Responds to OPTIONS requests with allowed methods\n- HEAD request served automagically\n- ES7 async/await support\n\n## Installation\n\n```bash\nnpm install cloudworker-router --save\n```\n\n## Basic Usage\n\nThe router handlers simply returns Response objects for basic handlers.\n\nBasic example with GET request\n\n```js\nconst Router = require('cloudworker-router');\n\nconst router = new Router();\n\nrouter.get('/', async (ctx) => {\n  return new Response('Hello World');\n});\n\nexport default {\n  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {\n    return router.handle(request, env, ctx);\n  },\n};\n```\n\nThe router exposes get, post, patch and del methods as shorthands for the most common use cases. For examples of their usage, see the example folder. HEAD requests are handled automatically by the router.\n\nFor more examples on usage and deployment see the examples folder in the project.\n\n### Defining paths\n\nThe paths are translated to regular expressions for matching. Query strings are not considred when matching requests.\n\nNamed router paramteres are captured and added to `ctx.params` :\n\n```js\nrouter.get('/hello/:name', async (ctx) => {\n  return new Response('Hello ' + ctx.params.name);\n});\n\nrouter.get('/:wildcard*', async (ctx) => {\n  return new Response(ctx.params.wildcard; // Will return the whole path\n});\n```\n\n### Middlewares\n\nThe middlewares are implemented by calling next, just like in koa-router.\n\nThe can be added by calling router.use:\n\n```js\nrouter.use(async (ctx, next) => {\n  // Maybe store the request start timestamp\n  const start = new Date();\n\n  try {\n    return await next();\n  } catch (err) {\n    // handle an error\n    return new Response(error.message, {\n      status: 500,\n    });\n  }\n});\n```\n\nIt is also posisble to pass a middlewared when defining a route:\n\n```js\nasync function middleware(ctx, next) {\n  console.log('do something clever');\n\n  await next();\n}\n\nrouter.get('/test', middleware, async (ctx) => {\n  return new Response('Hello');\n});\n```\n\n### Context\n\nThe context encapsulates the request and the response object.\n\nA new context instance are created for each request.\n\nAn example of a context object created for a request:\n\n```js\n{\n  request: Request,\n  event: ExecutionContext\n  state: {},\n  query: {\n    foo: \"bar\"\n  },\n  params: {}\n  env: {}\n}\n```\n\n### Env\n\nThe Router is generic class that makes it possible to get strictly typed env.\n\nIt supports the cloudflare services that is passed as env variables, such as Fetcher and KVStorage.\n\n```js\nconst Router = require('cloudworker-router');\n\ninterface MyEnv {\n  test: string;\n  KV_NAMESPACE: KVNamespace;\n  DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;\n  A_FETCHER: Fetcher;\n}\nconst router = new Router<MyEnv>();\n\nrouter.get('/', async (ctx) => {\n  return new Response(ctx.env.test);\n});\n\nexport default {\n  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {\n    return router.handle(reuquest, env, ctx);\n  },\n};\n```\n\n### Allow headers\n\nThe router can match OPTIONS request against the registered routes to respond with the correct allowed headers.\n\nTo enable handling of OPTIONS requests call allowHeaders after all other routes:\n\n```js\nconst router = new Router();\n\nrouter.get('/', async (ctx) => {\n  ctx.status = 200;\n});\n\nrouter.use(router.allowMethods());\n```\n\n## Cloudflare specifics\n\n### Chunked encoding\n\nBy default cloudflare uses chunked encoding. Content-Length headers are not allowed in chunked responses according to the http-spec so they are automatically removed by cloudflare. If the worker respondes directly with a buffer rather than streaming the response cloudflare will automatically add/overwrite with a correct Content-Length header.\n","readmeFilename":"README.md","gitHead":"c35350169985e9727183de594f054d320d49bef5","_id":"cloudworker-router@4.0.5","_nodeVersion":"16.15.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-qhlPh2cknaBZAg957zU2B1LSMQyO8B3MNxAcg45VWq+lTfjWfRqKqaPhRmK4eaJnW7oFgNbBRXtC8aNDJs17fg==","shasum":"15ecb106cfbc16984f74b4d934fa207e0b1581a6","tarball":"https://registry.npmjs.org/cloudworker-router/-/cloudworker-router-4.0.5.tgz","fileCount":33,"unpackedSize":27245,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCfRCHl0uNPtVMe4n66vhWU8fhbCPUptgr6WbvZGBR+SAIgTacAYeDG6HtIhxHeOiG8h59OQrBB7KKjWcNOL6u3TLM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjgR31ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqr7g/9ETHv3/9OsgkoszqjvFPdTLJvDli2cx+Z8nK42HTMo8y77EFL\r\nnK19Hic2w7BmBK8Bh3vAJJ2TZfxQNlNOHHlQRMt2VkbrlcER4YMuDXscm2r0\r\nfthC3YW52alqMp36OG83rKlTTyRacsF2ZhdIvVohVEi3l0l/pGa572YQ6PFZ\r\nQqE1WawnutxCZumMD+YXZiyNkOGQ4QLcy0IAm6okWxCYkWLj5B9vtWjR9X2E\r\nRlaI4yXa9N7zqbkdgW69Gqp1++M+TvYFIgt1fOlrGZ9m3jiGjUA0qu4iRCxx\r\nhb8YiSt2p7l8OvYnice/rQMdKvE8nzKyzqrwALOwFI5aLH4wqM7h7e53Q+Gp\r\nThAw0pTvAFVFpHyAjqujE9kS20UxxAchrXnj136v+r1q6pzfGhbblJ28IjgT\r\n8OcGjVlGQ156LrSDMeS3Fq3gr/LrsKTQARMeO0jb8E52hDTirntITdOxGoqu\r\nPiuU71dIZtnuIfrSjkzhrZ47lxJ6KxT/si8Nj2Jv0q/fVIU1iRbg7wyZtaH8\r\nPqCNpL/d/pFgQzrmhZjt57A8cxuT9+T5eznJ+od3jCYJEc4yTigPcV/LNXNm\r\noNyjevt7Y3GHr+YFAfALNqpCn2qVZ44jh8OqxJd3i3mD+Eg6C7LQltfkQuRR\r\nXmC/1hOoDzavq6Y29IYELoNx1rhQMBCYsi8=\r\n=CZor\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"markusahlstrand","email":"markus@ahlstrand.de"},"directories":{},"maintainers":[{"name":"markusahlstrand","email":"markus@ahlstrand.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/cloudworker-router_4.0.5_1669406196818_0.6401882956879521"},"_hasShrinkwrap":false}