├── .github └── CONTRIBUTING.md ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE.md ├── Readme.md ├── docs ├── .nojekyll ├── README.md ├── _404.md ├── _coverpage.md ├── _media │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── logo.png │ ├── logo.svg │ ├── mstile-144x144.png │ ├── mstile-150x150.png │ ├── mstile-310x150.png │ ├── mstile-310x310.png │ ├── mstile-70x70.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest ├── favicon.ico └── index.html ├── examples ├── basic │ ├── .cargo-ok │ ├── .prettierrc │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── webpack.config.js │ ├── wrangler.toml │ └── yarn.lock ├── domain-routing │ ├── .cargo-ok │ ├── .gitignore │ ├── .prettierrc │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tsconfig.json │ ├── webpack.config.js │ ├── wrangler.toml │ └── yarn.lock └── hello-world │ ├── .cargo-ok │ ├── .gitignore │ ├── .prettierrc │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ ├── tsconfig.json │ ├── webpack.config.js │ ├── wrangler.toml │ └── yarn.lock ├── package.json ├── rollup.config.js ├── src ├── context.ts ├── default.ts ├── global.d.ts ├── index.ts ├── middlewares │ ├── cors.ts │ └── static.ts ├── request.ts ├── response.ts ├── router.ts ├── types.ts └── vhost │ └── index.ts ├── tsconfig.json ├── workers ├── .cargo-ok ├── .gitignore ├── index.js ├── package.json └── yarn.lock ├── wrangler.toml └── yarn.lock /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 4 | 5 | Please note we have a code of conduct, please follow it in all your interactions with the project. 6 | 7 | ## Pull Request Process 8 | 9 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. 10 | 2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. 11 | 3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 12 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you. 13 | 14 | ## Code of Conduct 15 | 16 | ### Our Pledge 17 | 18 | In the interest of fostering an open and welcoming environment, we as 19 | contributors and maintainers pledge to making participation in our project and 20 | our community a harassment-free experience for everyone, regardless of age, body 21 | size, disability, ethnicity, gender identity and expression, level of experience, 22 | nationality, personal appearance, race, religion, or sexual identity and 23 | orientation. 24 | 25 | ### Our Standards 26 | 27 | Examples of behavior that contributes to creating a positive environment 28 | include: 29 | 30 | - Using welcoming and inclusive language 31 | - Being respectful of differing viewpoints and experiences 32 | - Gracefully accepting constructive criticism 33 | - Focusing on what is best for the community 34 | - Showing empathy towards other community members 35 | 36 | Examples of unacceptable behavior by participants include: 37 | 38 | - The use of sexualized language or imagery and unwelcome sexual attention or 39 | advances 40 | - Trolling, insulting/derogatory comments, and personal or political attacks 41 | - Public or private harassment 42 | - Publishing others' private information, such as a physical or electronic 43 | address, without explicit permission 44 | - Other conduct which could reasonably be considered inappropriate in a 45 | professional setting 46 | 47 | ### Our Responsibilities 48 | 49 | Project maintainers are responsible for clarifying the standards of acceptable 50 | behavior and are expected to take appropriate and fair corrective action in 51 | response to any instances of unacceptable behavior. 52 | 53 | Project maintainers have the right and responsibility to remove, edit, or 54 | reject comments, commits, code, wiki edits, issues, and other contributions 55 | that are not aligned to this Code of Conduct, or to ban temporarily or 56 | permanently any contributor for other behaviors that they deem inappropriate, 57 | threatening, offensive, or harmful. 58 | 59 | ### Scope 60 | 61 | This Code of Conduct applies both within project spaces and in public spaces 62 | when an individual is representing the project or its community. Examples of 63 | representing a project or community include using an official project e-mail 64 | address, posting via an official social media account, or acting as an appointed 65 | representative at an online or offline event. Representation of a project may be 66 | further defined and clarified by project maintainers. 67 | 68 | ### Enforcement 69 | 70 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 71 | reported by contacting the project team at [dev@edgehub.in](mailto:dev@edgehub.in). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is 72 | obligated to maintain confidentiality with regard to the reporter of an incident. 73 | Further details of specific enforcement policies may be posted separately. 74 | 75 | Project maintainers who do not follow or enforce the Code of Conduct in good 76 | faith may face temporary or permanent repercussions as determined by other 77 | members of the project's leadership. 78 | 79 | ### Attribution 80 | 81 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 82 | 83 | [homepage]: http://contributor-covenant.org 84 | [version]: http://contributor-covenant.org/version/1/4/ 85 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | 82 | # Nuxt.js build / generate output 83 | .nuxt 84 | dist 85 | 86 | # Gatsby files 87 | .cache/ 88 | # Comment in the public line in if your project uses Gatsby and not Next.js 89 | # https://nextjs.org/blog/next-9-1#public-directory-support 90 | # public 91 | 92 | # vuepress build output 93 | .vuepress/dist 94 | 95 | # Serverless directories 96 | .serverless/ 97 | 98 | # FuseBox cache 99 | .fusebox/ 100 | 101 | # DynamoDB Local files 102 | .dynamodb/ 103 | 104 | # TernJS port file 105 | .tern-port 106 | 107 | # Stores VSCode versions used for testing VSCode extensions 108 | .vscode-test 109 | 110 | # yarn v2 111 | 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .pnp.* 116 | 117 | # microbundle 118 | .rts* 119 | .DS_Store 120 | docs/_lib/ 121 | worker/ -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": false, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "arrowParens": "always", 11 | "rangeStart": 0 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2020, Vinay Puppal. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | > Still in development and not production ready 2 | 3 | # EdgeRouter 4 | 5 | A minimal Express.js like router for cloudflare workers. 6 | 7 |

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

18 | 19 | ## Documentation 20 | 21 | Visit https://router.edgehub.in to view the documentation. 22 | 23 | ## Todo 24 | 25 | - [ ] Tests 26 | - [ ] Preview examples and library with `https://cloudflareworkers.com/` 27 | 28 | ## Contributing 29 | 30 | Please see our [contributing.md](/.github/CONTRIBUTING.md). 31 | 32 | ## Authors 33 | 34 | - [VinayPuppal](https://vinaypuppal.com) 35 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## ✨ Features 2 | 3 | - Based on [trouter](https://github.com/lukeed/trouter) 4 | - Express style routes. 5 | - Helper functions 6 | - Read requests: Built-in body-parser, cookie-parser, and a query string-parser. 7 | - To modify headers and 8 | - Send a response. 9 | - Middleware support. 10 | - CORS Middleware 11 | - Workers site Middleware 12 | - Domain routing. 13 | 14 | ## 🔋 Install 15 | 16 | With Yarn 17 | 18 | ```bash 19 | yarn add @edgehub/router 20 | ``` 21 | 22 | With NPM 23 | 24 | ```bash 25 | npm install @edgehub/router 26 | ``` 27 | 28 | ## 💻 Hello world example 29 | 30 | You can try this example with [wrangler](https://github.com/cloudflare/wrangler) by running this command 31 | 32 | ```bash 33 | wrangler generate myapp https://github.com/edge-hub/router/tree/master/examples/hello-world 34 | ``` 35 | 36 | ```js 37 | import { EdgeRouter } from "@edgehub/router"; 38 | 39 | const worker = new EdgeRouter(); 40 | 41 | // Middleware to set a header for all routes 42 | worker.use((req, res) => { 43 | res.setHeader("x-router", "EdgeRouter"); 44 | }); 45 | 46 | // The worker responds with `Hello World` for requests to root URL(/). For every other path, it will fallback to origin response if its exists or error. 47 | worker.get("/", (req, res) => { 48 | return res.send(`Hello World`); 49 | }); 50 | 51 | worker.listen({ passThroughOnException: true }); 52 | ``` 53 | 54 | > You can find more examples [here](https://github.com/edge-hub/router/tree/master/examples/) 55 | 56 | ## 🥳 Basic Routing 57 | 58 | Routing refers to determining how a worker responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on). 59 | 60 | Each route can have one or more handler functions, which are executed when the route is matched. 61 | 62 | Route definition takes the following structure: 63 | 64 | ```js 65 | worker.METHOD(PATTERN, HANDLER); 66 | ``` 67 | 68 | Where: 69 | 70 | - `worker` is an instance of EdgeRouter 71 | - `METHOD` is one of the HTTP methods in lowercase. For a full list of valid METHODs, please see [this list](https://github.com/lukeed/trouter#method) 72 | - `PATTERN` is a routing pattern (pathname) which is `string`. The supported pattern types are: 73 | - static (`/posts`) 74 | - named parameters (`/posts/:id`) 75 | - nested parameters (`/posts/:id/users/:id`) 76 | - optional parameters (`/users/:id?/books/:title?`) 77 | - any match / wildcards (`/users/*`) 78 | - `HANDLER` is the function executed when the route is matched. 79 | - Every route definition must contain a valid handler function, or else an error will be thrown at runtime. 80 | - It accepts a two arguments **[req](#📨-request)** and **[res](#📣-response)** 81 | 82 | ## 👀 API 83 | 84 | EdgeRouter extends [Trouter](https://github.com/lukeed/trouter) which means it inherits its API 85 | 86 | ### ✏️ Options 87 | 88 | ```js 89 | import { EdgeRouter } from "@edgehub/router"; 90 | 91 | const worker = new EdgeRouter(options); 92 | ``` 93 | 94 | > All options are optional which means you need to specify them if you want to change the default behavior. 95 | 96 | The following table describes the properties of the optional options object. 97 | 98 | | Property | Description | Type | Default | 99 | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------- | 100 | | onNoMatch | A handler to be executed when no route is matched. | Function | undefined | 101 | | onError | A catch-all error handler; executed whenever a middleware throws an error. | Function | undefined | 102 | | onBeforeResponse | A handler which executes right before sending a response from a route handler.**If this handler returns a Response object then normal route processing will stop and the response will be sent out.** | Function | undefined | 103 | 104 | > The signature of these handlers is same as the route handlers which you saw in [Basic Routing](#🥳-basic-routing) 105 | 106 | ### ☁️ Instance 107 | 108 | The `worker` object conventionally denotes the Cloudflare worker. Create it by calling the `new EdgeRouter()` class exported by the `@edgehub/router` module: 109 | 110 | ```js 111 | import { EdgeRouter } from "@edgehub/router"; 112 | 113 | const worker = new EdgeRouter(); 114 | 115 | // The worker responds with `Hello World` for requests to root URL(/). For every other path, it will fallback to origin response if its exists or error. 116 | worker.get("/", (req, res) => { 117 | return res.send(`Hello World`); 118 | }); 119 | 120 | worker.listen({ passThroughOnException: true }); 121 | ``` 122 | 123 | The `worker` object has methods for 124 | 125 | - Routing HTTP requests; see for example, [worker.METHOD()](#workermethod) 126 | - Configuring middleware; see [worker.use()](#workeruse) 127 | - Listening for incoming requests; see [worker.listen()](#workerlisten) 128 | 129 | #### worker.METHOD() 130 | 131 | Routes an HTTP request, where METHOD is the HTTP method of the request, such as GET, PUT, POST, and so on, in lowercase. 132 | 133 | See [Basic Routing Section](#🥳-basic-routing) for more info. 134 | 135 | #### worker.use() 136 | 137 | Mounts the specified middleware function or functions at the specified path or for all routes. 138 | _The middleware function is executed when the base of the requested path matches path or for every request in case of global middleware_. 139 | 140 | See [Middlewares Section](#middlewares) for more info. 141 | 142 | #### worker.listen() 143 | 144 | It defines the `fetch` event listener to listen for incoming requests. 145 | 146 | Example: 147 | 148 | ```js 149 | worker.listen({ passThroughOnException: true }); 150 | ``` 151 | 152 | Options: 153 | 154 | | Property | Description | Type | Default | 155 | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- | 156 | | passThroughOnException | Cause the script to "fail open" unhandled exceptions. Instead of returning a runtime error response, the runtime proxies the request to its destination. To prevent JavaScript errors from causing entire requests to fail on uncaught exceptions, passThroughOnException causes the Worker script to act as if the exception wasn’t there. This allows the script to yield control to your origin server. | boolean | false | 157 | 158 | #### Custom listener 159 | 160 | You can set up a custom listener as shown below 161 | 162 | ```js 163 | import { EdgeRouter } from "@edgehub/router"; 164 | 165 | const worker = new EdgeRouter(); 166 | 167 | worker.get("/", async (req, res) => { 168 | return res.send({ hello: "world" }); 169 | }); 170 | 171 | addEventListener("fetch", (event) => { 172 | event.respondWith(worker.onRequest(event)); 173 | }); 174 | ``` 175 | 176 | ### 📨 Request 177 | 178 | The req object has properties for the request query string, parameters, body, HTTP headers, original _Fetch Request_, _FetchEvent_ and so on. In this documentation and by convention, the object is always referred to as req (and the response is res) but its actual name is determined by the parameters to the callback function in which you’re working. 179 | 180 | #### req.query 181 | 182 | This property is an object containing a property for each query string parameter in the route. 183 | It can be: 184 | 185 | - This object defaults to {} 186 | - Each property inside the query object can be either `string` or `array` as shown below 187 | 188 | ```js 189 | // GET /posts?limit=10 190 | console.log(req.query.limit); 191 | // => "10" 192 | 193 | // GET /search?tags=javascript&tags=react 194 | console.log(req.query.tags); 195 | // => ["javascript", "react"] 196 | ``` 197 | 198 | #### req.params 199 | 200 | This property is an object containing properties mapped to the named route “parameters”. For example, if you have the route `/posts/:id`, then the “name” property is available as `req.params.id`. This object defaults to `{}`. 201 | 202 | ```js 203 | // GET /posts/123456 204 | console.log(req.params.id); 205 | // => "123456" 206 | ``` 207 | 208 | #### req.url 209 | 210 | This property contains the original request URL as shown below. 211 | 212 | ```js 213 | // If request comes for https://edgehub.in/posts/123456 214 | worker.get("/posts/:id", (req, res) => { 215 | console.log(req.url); 216 | }); 217 | // => https://edgehub.in/posts/123456 218 | ``` 219 | 220 | #### req.host 221 | 222 | This property contains `host` parsed from the original request URL as shown below. 223 | 224 | ```js 225 | // If request comes for https://edgehub.in/posts/123456 226 | worker.get("/posts/:id", (req, res) => { 227 | console.log(req.url); 228 | }); 229 | // => edgehub.in 230 | ``` 231 | 232 | #### req.pathname 233 | 234 | This property contains `path` parsed from the original request URL as shown below. 235 | 236 | ```js 237 | // If request comes for https://edgehub.in/posts/123456 238 | worker.get("/posts/:id", (req, res) => { 239 | console.log(req.url); 240 | }); 241 | // => /posts/123456 242 | ``` 243 | 244 | #### req.protocol 245 | 246 | This property contains `protocol` parsed from the original request URL as shown below. 247 | 248 | ```js 249 | // If request comes for https://edgehub.in/posts/123456 250 | worker.get("/posts/:id", (req, res) => { 251 | console.log(req.url); 252 | }); 253 | // => https: 254 | ``` 255 | 256 | #### req.method 257 | 258 | This property contains a string corresponding to the HTTP method of the request: GET, POST, PUT, and so on. 259 | 260 | #### req.search 261 | 262 | This property contains the unparsed query string parameter in the route. 263 | 264 | ```js 265 | // GET /posts?limit=10 266 | console.log(req.query.limit); 267 | // => "?limit=10" 268 | ``` 269 | 270 | #### req.querystring 271 | 272 | This property is same as [req.search](#req.search) but without the leading `?`. 273 | 274 | ```js 275 | // GET /posts?limit=10 276 | console.log(req.query.limit); 277 | // => "limit=10" 278 | ``` 279 | 280 | #### req.cookies 281 | 282 | EdgeRouter includes built-in cookie parser and this property is an object that contains cookies sent by the request. If the request contains no cookies, it defaults to {}. 283 | 284 | ```js 285 | // Cookie: token=skenfklwnefklwnfkwnefklmwekldm 286 | console.log(req.cookies.token); 287 | // => // "skenfklwnefklwnfkwnefklmwekldm" 288 | ``` 289 | 290 | #### req.headers 291 | 292 | This object conatains the request header list. You can use 293 | 294 | - `get()` to get a header by name and 295 | - `has()` to check if a header exists 296 | 297 | ```js 298 | console.log(req.headers.has("content-type")); 299 | // => true 300 | 301 | console.log(req.headers.get("content-type")); 302 | // => "application/json" 303 | ``` 304 | 305 | #### req.header() 306 | 307 | Returns the specified HTTP request header field (case-insensitive match). 308 | 309 | ```js 310 | req.header("content-type"); 311 | // => "text/plain" 312 | 313 | req.header("Content-Type"); 314 | // => "text/plain" 315 | ``` 316 | 317 | #### req.body() 318 | 319 | Returns an object which contains key-value pairs of data submitted in the request body. 320 | 321 | > It's a `async` function so you need to use `await` to get the data back when called. 322 | 323 | ```js 324 | // A post request sending this JSON data "{"name": "EdgeRouter"}" 325 | worker.post("/user", async (req, res) => { 326 | const data = await req.body(); 327 | console.log(data); 328 | }); 329 | // => { name: "EdgeRouter" } 330 | ``` 331 | 332 | #### req.\_originalRequest 333 | 334 | This property contains original fetch request recieved by the Coudflare Worker. You can read about available properties and methods on this object [here](https://developers.cloudflare.com/workers/reference/apis/request/) 335 | 336 | #### req.\_event 337 | 338 | This property contains original fetchEvent recieved by the Coudflare Worker. You can read about available properties and methods on this object [here](https://developers.cloudflare.com/workers/reference/apis/fetch-event/) 339 | 340 | ### 📣 Response 341 | 342 | The res object is used to create a response that a worker sends when it gets an HTTP request. In this documentation and by convention, the object is always referred to as res (and the request is req) but its actual name is determined by the parameters to the callback function in which you’re working. 343 | 344 | #### res.setHeader() 345 | 346 | Sets the response’s HTTP header field to value. 347 | 348 | ```js 349 | res.setHeader(field [, value]) 350 | ``` 351 | 352 | #### res.setCookie() 353 | 354 | Sets cookie name to value. The value parameter may be a string or object converted to JSON. 355 | 356 | ```js 357 | res.cookie(name, value [, options]) 358 | ``` 359 | 360 | > The options parameter is an object that can have the properties mentioned [here](https://github.com/jshttp/cookie#options-1). 361 | 362 | #### res.status() 363 | 364 | Sets the HTTP status for the response. It is a chainable as shown below 365 | 366 | ```js 367 | res.status(400).send("Bad Request"); 368 | ``` 369 | 370 | #### res.sendStatus() 371 | 372 | Sets the response HTTP status code to statusCode and creates its string representation as the response body. 373 | 374 | !> `res.sendStatus` only creates the Response and it does not really send it. Inorder to send it you need to return the response generated from your route handler. 375 | 376 | ```js 377 | import { EdgeRouter } from "@edgehub/router"; 378 | 379 | const worker = new EdgeRouter(); 380 | 381 | worker.get("/", async (req, res) => { 382 | return res.sendStatus(200); 383 | }); 384 | 385 | worker.listen({ passThroughOnException: true }); 386 | ``` 387 | 388 | #### res.send() 389 | 390 | Creates the HTTP response. It takes `body` as argument. 391 | 392 | - The `body` parameter can be a String, a Number, a Boolean, an object, or an Array. 393 | - When the `body` is an object or array the response is sent with content-type `application/json` 394 | - For rest of the types it's sent with content-type `text/html` 395 | 396 | For example: 397 | 398 | ```js 399 | res.send({ some: "json" }); 400 | res.send("

some html

"); 401 | res.status(404).send("Sorry, we cannot find that!"); 402 | res.status(500).send({ error: "something blew up" }); 403 | ``` 404 | 405 | !> `res.send` only creates the Response and it does not really send it. Inorder to send it you need to return the response generated from your route handler. 406 | 407 | ```js 408 | import { EdgeRouter } from "@edgehub/router"; 409 | 410 | const worker = new EdgeRouter(); 411 | 412 | worker.get("/", async (req, res) => { 413 | return res.send({ hello: "world" }); 414 | }); 415 | 416 | worker.listen({ passThroughOnException: true }); 417 | ``` 418 | 419 | #### res.redirect() 420 | 421 | Redirects to the specified URL and status, a positive integer that corresponds to an HTTP status code . If not specified, status defaults to “302 “Found”. 422 | 423 | It takes `url` and `status` as arguments 424 | 425 | ```js 426 | // Default status code 302 427 | res.redirect("http://google.com"); 428 | 429 | // With status code 301 430 | res.redirect("http://google.com", 301); 431 | ``` 432 | 433 | ### 🧚 Middlewares 434 | 435 | Middleware are functions that run in between (hence "middle") receiving the request & executing your route's handler response. 436 | 437 | #### Middleware Sequence 438 | 439 | ```js 440 | worker.use([path], [function, ...] function) 441 | ``` 442 | 443 | - Global middleware are defined via `worker.use('/', ...fn)` or `worker.use(...fn)`, which are synonymous. Because every request's pathname begins with a `/`, this tier is always triggered. 444 | - Sub-group or "filtered" middleware are defined with a base pathname that's more specific than `/`. For example, defining `worker.use('/users', ...fn)` will run on any `/users/**/*` request. These functions will execute after "global" middleware but before the route-specific handler. 445 | - Route handlers match specific paths and execute last in the chain. They must also match the method action. 446 | 447 | !> Most importantly, a middleware must either terminate the response (res.send) by returning it or return **nothing**. When it returns nothing the next route/middleware handler will invoked. 448 | 449 | #### Middleware Example 450 | 451 | ```js 452 | import { EdgeRouter } from "@edgehub/router"; 453 | 454 | const worker = new EdgeRouter(); 455 | 456 | // simple logger for this router's requests 457 | // all requests to this router will first hit this middleware 458 | worker.use((req, res) => { 459 | console.log(req.method, req.url, req.path); 460 | }); 461 | 462 | // Middleware to set a header for all routes 463 | worker.use((req, res) => { 464 | res.setHeader("x-router", "EdgeRouter"); 465 | }); 466 | 467 | // this will only be invoked if the path starts with /bar from the mount point 468 | worker.use("/bar", (req, res) => { 469 | // ... maybe some additional /bar logging ... 470 | }); 471 | 472 | // Authorization middleware 473 | worker.use((req, res) => { 474 | // mutate req; available later 475 | req.token = req.headers.get("authorization"); 476 | if (!req.token) { 477 | return res.status(401).send(`No token!`); 478 | } 479 | }); 480 | 481 | // The worker responds with `Hello World` for requests to root URL(/). For every other path, it will fallback to origin response if its exists or error. 482 | worker.get("/", (req, res) => { 483 | return res.send(`Hello World`); 484 | }); 485 | 486 | worker.listen({ passThroughOnException: true }); 487 | ``` 488 | 489 | #### Built In Middlewares 490 | 491 | ##### CORS Middleware 492 | 493 | This library comes with a cors middleware, which can be used a shown below 494 | 495 | ```js 496 | import { EdgeRouter } from "@edgehub/router"; 497 | import { cors } from "@edgehub/router/middlewares/cors"; 498 | 499 | const worker = new EdgeRouter(); 500 | 501 | // CORS middleware 502 | worker.use(cors()); 503 | 504 | // The worker responds with `Hello World` for requests to root URL(/). For every other path, it will fallback to origin response if its exists or error. 505 | worker.get("/", (req, res) => { 506 | return res.send(`Hello World`); 507 | }); 508 | 509 | worker.listen({ passThroughOnException: true }); 510 | ``` 511 | 512 | Options: 513 | 514 | | Property | Type | Default | 515 | | ---------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- | 516 | | allowMethods | Array | ['POST','GET','PUT','PATCH','DELETE','OPTIONS'] | 517 | | allowHeaders | Array | ['X-Requested-With','Access-Control-Allow-Origin','X-HTTP-Method-Override','Content-Type','Authorization','Accept'] | 518 | | exposeHeaders | Array | [] | 519 | | allowCredentials | Boolean | true | 520 | | origin | String/Function | \* | 521 | | maxAge | Number | 86400 | 522 | 523 | ```js 524 | // CORS middleware with options 525 | worker.use( 526 | cors({ 527 | allowMethods: ["PUT", "POST"], 528 | origin: (request) => { 529 | const origin = request.headers.get("Origin"); 530 | if (WHITELIST.includes(origin)) { 531 | return true; 532 | } 533 | return false; 534 | }, 535 | }) 536 | ); 537 | ``` 538 | 539 | !> Here `request` is original fetch request as mentioned [here](https://developers.cloudflare.com/workers/reference/apis/request/) 540 | 541 | ##### Worker Sites Middleware 542 | 543 | This library also comes with a `workersSite` middleware, which can be used to add support for [workers sites](https://developers.cloudflare.com/workers/sites) 544 | 545 | > Inorder to to use this middleware you need to install this package [@cloudflare/kv-asset-handler](https://github.com/cloudflare/kv-asset-handler) `yarn add @cloudflare/kv-asset-handler` 546 | 547 | ```js 548 | import { EdgeRouter } from "@edgehub/router"; 549 | import { workersSite } from "@edgehub/router/middlewares/static"; 550 | 551 | const worker = new EdgeRouter(); 552 | 553 | // workersSite middleware 554 | worker.use(workersSite()); 555 | 556 | // Here you can handle more routes 557 | 558 | worker.listen({ passThroughOnException: true }); 559 | ``` 560 | 561 | > The options supported by this middleware are same as of [cloudflare/kv-asset-handler](https://github.com/cloudflare/kv-asset-handler). You can find supported **[options here](https://github.com/cloudflare/kv-asset-handler#optional-arguments)** 562 | 563 | ```js 564 | // Example with options 565 | worker.use( 566 | workersSite({ 567 | cacheControl: { 568 | browserTTL: null, // do not set cache control ttl on responses 569 | edgeTTL: 2 * 60 * 60 * 24, // 2 days 570 | bypassCache: false, // do not bypass Cloudflare's cache 571 | }, 572 | }) 573 | ); 574 | ``` 575 | 576 | ## 🕸️ Domain Routing 577 | 578 | This library exposes `VHostRouter` to support domain routing. CLoudflare workers allows to associate multiple domains/subdomains for a worker script as [mentioned here](https://developers.cloudflare.com/workers/about/routes/) 579 | 580 | So using `VHostRouter` you can define/scope `EdgeRouter` to a particular domain and handler it's requests as shown below. 581 | 582 | ### API 583 | 584 | The `vhost` object conventionally denotes the Virtual Host. Create it by calling the `new VHostRouter()` class exported by the `@edgehub/router` module: 585 | 586 | ```js 587 | import { EdgeRouter } from "@edgehub/router"; 588 | import { VHostRouter } from "@edgehub/router/vhost"; 589 | 590 | const vhost = new VHostRouter(); 591 | const apiRouter = new EdgeRouter(); 592 | const cdnRouter = new EdgeRouter(); 593 | 594 | // API routes 595 | apiRouter.get("/posts", (req, res) => { 596 | return res.send({ posts: { title: "About EdgeRouter" } }); 597 | }); 598 | 599 | apiRouter.post("/posts", async (req, res) => { 600 | const data = await req.body(); 601 | if (!data) { 602 | return res.send(`Not data from POST req`); 603 | } 604 | // store data in db and send response 605 | return res.send(data); 606 | }); 607 | 608 | // CDN routes 609 | cdnRouter.all("*", (req, res) => { 610 | // Fetch image from CDN and modify on the fly to webp or resize ...etc 611 | res.send(`Some image`); 612 | }); 613 | 614 | vhost.use("api.example.com", apiRouter); 615 | vhost.use("cdn.example.com", cdnRouter); 616 | 617 | vhost.listen({ passThroughOnException: true }); 618 | ``` 619 | 620 | The `vhost` object has following methods: 621 | 622 | - Listening for incoming requests `vhost.listen()` and it's simillar to [worker.listen()](#workerlisten) 623 | - Routing requests for a particular domain `vhost.use()` 624 | ```js 625 | vhost.use(DOMAIN_PATTERN, EDGEROUTER_INSTANCE); 626 | ``` 627 | - `DOMAIN_PATTERN`: It can be a string or a RegExp object. When `DOMAIN_PATTERN` is a string it can contain `*` to match 1 or more characters in that section of the `DOMAIN_PATTERN`. When `DOMAIN_PATTERN` is a RegExp, it will be forced to case-insensitive (since `DOMAIN_PATTERN`s are) and will be forced to match based on the start and end of the `DOMAIN_PATTERN`. 628 | - `EDGEROUTER_INSTANCE`: This is executed when a `DOMAIN_PATTERN` is matched. 629 | - When `DOMAIN_PATTERN` is matched and the request is sent down to a EDGEROUTER_INSTANCE, the req.vhost property will be populated with an object. This object will have numeric properties corresponding to each wildcard (or capture group if RegExp object provided) and the hostname that was matched. 630 | 631 | ## 👉 Contributing 632 | 633 | Please see our [contributing.md](https://github.com/edge-hub/router/blob/master/.github/CONTRIBUTING.md). 634 | 635 | ## 👨‍💻 Authors 636 | 637 | - [VinayPuppal](https://vinaypuppal.com) 638 | 639 | See also the list of [contributors](https://github.com/edge-hub/router/graphs/contributors) who participated in this project. Join us 🍻 640 | -------------------------------------------------------------------------------- /docs/_404.md: -------------------------------------------------------------------------------- 1 | Page Not Found 2 | 3 | [Get Back](https://router.edgehub.in) 4 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | ![logo](_media/logo.svg ":size=100") 2 | 3 | # EdgeRouter 4 | 5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | npm bundle size 13 |

14 | 15 | > A minimal Express.js like router for [Cloudflare Workers](https://workers.cloudflare.com/). 16 | 17 | [Get Started](#🔋-install) 18 | [Features](#✨-features) 19 | -------------------------------------------------------------------------------- /docs/_media/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/_media/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/android-chrome-512x512.png -------------------------------------------------------------------------------- /docs/_media/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/_media/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #00aba9 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/_media/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/favicon-16x16.png -------------------------------------------------------------------------------- /docs/_media/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/favicon-32x32.png -------------------------------------------------------------------------------- /docs/_media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/logo.png -------------------------------------------------------------------------------- /docs/_media/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/_media/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/mstile-144x144.png -------------------------------------------------------------------------------- /docs/_media/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/mstile-150x150.png -------------------------------------------------------------------------------- /docs/_media/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/mstile-310x150.png -------------------------------------------------------------------------------- /docs/_media/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/mstile-310x310.png -------------------------------------------------------------------------------- /docs/_media/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/_media/mstile-70x70.png -------------------------------------------------------------------------------- /docs/_media/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 16 | 21 | 29 | 36 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /docs/_media/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EdgeRouter", 3 | "short_name": "EdgeRouter", 4 | "description": "A minimal Express.js like router for cloudflare workers.", 5 | "icons": [ 6 | { 7 | "src": "/android-chrome-192x192.png", 8 | "sizes": "192x192", 9 | "type": "image/png" 10 | }, 11 | { 12 | "src": "/android-chrome-512x512.png", 13 | "sizes": "512x512", 14 | "type": "image/png" 15 | } 16 | ], 17 | "theme_color": "#000000", 18 | "background_color": "#ffffff", 19 | "display": "standalone" 20 | } 21 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EdgeRouter 7 | 8 | 9 | 13 | 14 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 50 | 54 | 59 | 65 | 71 | 72 | 77 | 78 | 79 | 83 | 126 | 127 | 128 |
129 |
130 | 131 | Loading... Please wait. 132 | 133 |
134 |
135 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /examples/basic/.cargo-ok: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/examples/basic/.cargo-ok -------------------------------------------------------------------------------- /examples/basic/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": false, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "arrowParens": "always", 11 | "rangeStart": 0 12 | } 13 | -------------------------------------------------------------------------------- /examples/basic/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Cloudflare, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # A basic routing example with EdgeHub Router 2 | 3 | To generate using Wrangler, run this command: 4 | 5 | ```bash 6 | wrangler generate myapp https://github.com/edge-hub/router/tree/master/examples/basic 7 | ``` 8 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edgerouter", 3 | "version": "1.0.0", 4 | "description": "Cloudflare worker EdgeRouter template", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "dev": "NODE_ENV=development npm run build" 9 | }, 10 | "author": "edgehub", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "@cloudflare/workers-types": "^1.0.1", 14 | "prettier": "^1.18.2", 15 | "ts-loader": "^6.0.4", 16 | "typescript": "^3.5.3", 17 | "webpack": "^4.43.0", 18 | "webpack-cli": "^3.3.11" 19 | }, 20 | "dependencies": { 21 | "@edgehub/router": "^0.0.28" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/basic/src/index.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRouter } from "@edgehub/router"; 2 | import { cors } from "@edgehub/router/middlewares/cors"; 3 | 4 | const worker = new EdgeRouter(); 5 | 6 | worker.use(cors()); 7 | 8 | worker.get("/api/posts", async (req, res) => { 9 | // Get posts from some db or rest API 10 | const posts = await getPosts(); 11 | 12 | return res.send(posts); 13 | }); 14 | 15 | worker.get("/api/posts/:id", async (req, res) => { 16 | const { id } = req.params; 17 | // Get posts from some db or rest API 18 | const post = await getPost(Number(id)); 19 | 20 | return res.send(post); 21 | }); 22 | 23 | worker.post("/api/posts", async (req, res) => { 24 | const body = await req.body(); 25 | 26 | if (!body) { 27 | throw new Error(`POST body is not present`); 28 | } 29 | 30 | if (!body.title || !body.content) { 31 | throw new Error( 32 | `To add post please provide all these fields i.e title and content` 33 | ); 34 | } 35 | 36 | const posts = await addPost(body); 37 | 38 | return res.send(posts); 39 | }); 40 | 41 | worker.listen({ passThroughOnException: true }); 42 | 43 | // For Demo Purpose 44 | const POSTS = [ 45 | { 46 | id: 1, 47 | title: `EdgeRouter basic routing`, 48 | author: `EdgeHub`, 49 | content: `Lorem ipsum dolor sit amet, consectetur adipisicing elit.`, 50 | }, 51 | { 52 | id: 2, 53 | title: `EdgeRouter examples`, 54 | author: `EdgeHub`, 55 | content: `Lorem ipsum dolor sit amet, consectetur adipisicing elit.`, 56 | }, 57 | ]; 58 | 59 | async function getPosts() { 60 | return POSTS; 61 | } 62 | 63 | async function getPost(id: number) { 64 | return POSTS.find((post) => post.id === id); 65 | } 66 | 67 | async function addPost(body: Record) { 68 | return [...POSTS, { ...body, id: Date.now() }]; 69 | } 70 | -------------------------------------------------------------------------------- /examples/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "module": "commonjs", 5 | "target": "esnext", 6 | "lib": ["esnext", "webworker"], 7 | "alwaysStrict": true, 8 | "strict": true, 9 | "preserveConstEnums": true, 10 | "moduleResolution": "node", 11 | "sourceMap": true, 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "./src/*.ts", 16 | "./test/*.ts", 17 | "./src/**/*.ts", 18 | "./test/**/*.ts", 19 | "./node_modules/@cloudflare/workers-types/index.d.ts" 20 | ], 21 | "exclude": ["node_modules/", "dist/"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/basic/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const mode = process.env.NODE_ENV || "production"; 4 | 5 | module.exports = { 6 | output: { 7 | filename: `worker.${mode}.js`, 8 | path: path.join(__dirname, "dist"), 9 | }, 10 | devtool: "source-map", 11 | mode, 12 | resolve: { 13 | extensions: [".ts", ".tsx", ".js"], 14 | plugins: [], 15 | }, 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.tsx?$/, 20 | loader: "ts-loader", 21 | options: { 22 | transpileOnly: true, 23 | }, 24 | }, 25 | ], 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /examples/basic/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "basic" 2 | type = "webpack" 3 | workers_dev = true 4 | account_id = "" 5 | route = "" 6 | zone_id = "" 7 | webpack_config = "webpack.config.js" 8 | -------------------------------------------------------------------------------- /examples/domain-routing/.cargo-ok: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/examples/domain-routing/.cargo-ok -------------------------------------------------------------------------------- /examples/domain-routing/.gitignore: -------------------------------------------------------------------------------- 1 | worker/ -------------------------------------------------------------------------------- /examples/domain-routing/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": false, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "arrowParens": "always", 11 | "rangeStart": 0 12 | } 13 | -------------------------------------------------------------------------------- /examples/domain-routing/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Cloudflare, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /examples/domain-routing/README.md: -------------------------------------------------------------------------------- 1 | # Domain Routing example with EdgeHub Router 2 | 3 | To generate using Wrangler, run this command: 4 | 5 | ```bash 6 | wrangler generate myapp https://github.com/edge-hub/router/tree/master/examples/domain-routing 7 | ``` 8 | -------------------------------------------------------------------------------- /examples/domain-routing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edgerouter", 3 | "version": "1.0.0", 4 | "description": "Cloudflare worker EdgeRouter template", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "dev": "NODE_ENV=development npm run build" 9 | }, 10 | "author": "edgehub", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "@cloudflare/workers-types": "^1.0.1", 14 | "prettier": "^1.18.2", 15 | "ts-loader": "^6.0.4", 16 | "typescript": "^3.5.3", 17 | "webpack": "^4.35.3", 18 | "webpack-cli": "^3.3.6" 19 | }, 20 | "dependencies": { 21 | "@edgehub/router": "latest" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/domain-routing/src/index.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRouter } from "@edgehub/router"; 2 | import { VHostRouter } from "@edgehub/router/vhost"; 3 | 4 | const vhost = new VHostRouter(); 5 | const apiRouter = new EdgeRouter(); 6 | const cdnRouter = new EdgeRouter(); 7 | 8 | // API routes 9 | apiRouter.get("/posts", (req, res) => { 10 | return res.send({ posts: { title: "About EdgeRouter" } }); 11 | }); 12 | 13 | apiRouter.post("/posts", async (req, res) => { 14 | const data = await req.body(); 15 | if (!data) { 16 | return res.send(`Not data from POST req`); 17 | } 18 | // store data in db and send response 19 | return res.send(data); 20 | }); 21 | 22 | // CDN routes 23 | cdnRouter.all("*", (req, res) => { 24 | // Fetch image from CDN and modify on the fly to webp or resize ...etc 25 | res.send(`Some image`); 26 | }); 27 | 28 | vhost.use("api.example.com", apiRouter); 29 | vhost.use("cdn.example.com", cdnRouter); 30 | 31 | vhost.listen({ passThroughOnException: true }); 32 | -------------------------------------------------------------------------------- /examples/domain-routing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "module": "commonjs", 5 | "target": "esnext", 6 | "lib": ["esnext", "webworker"], 7 | "alwaysStrict": true, 8 | "strict": true, 9 | "preserveConstEnums": true, 10 | "moduleResolution": "node", 11 | "sourceMap": true, 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "./src/*.ts", 16 | "./test/*.ts", 17 | "./src/**/*.ts", 18 | "./test/**/*.ts", 19 | "./node_modules/@cloudflare/workers-types/index.d.ts" 20 | ], 21 | "exclude": ["node_modules/", "dist/"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/domain-routing/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const mode = process.env.NODE_ENV || "production"; 4 | 5 | module.exports = { 6 | output: { 7 | filename: `worker.js`, 8 | path: path.join(__dirname, "dist"), 9 | }, 10 | mode, 11 | resolve: { 12 | extensions: [".ts", ".tsx", ".js"], 13 | plugins: [], 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.tsx?$/, 19 | loader: "ts-loader", 20 | options: { 21 | transpileOnly: true, 22 | }, 23 | }, 24 | ], 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /examples/domain-routing/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "hello-world" 2 | type = "webpack" 3 | workers_dev = true 4 | account_id = "" 5 | route = "" 6 | zone_id = "" 7 | webpack_config = "webpack.config.js" 8 | -------------------------------------------------------------------------------- /examples/hello-world/.cargo-ok: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/examples/hello-world/.cargo-ok -------------------------------------------------------------------------------- /examples/hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | worker/ -------------------------------------------------------------------------------- /examples/hello-world/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": false, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": false, 10 | "arrowParens": "always", 11 | "rangeStart": 0 12 | } 13 | -------------------------------------------------------------------------------- /examples/hello-world/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Cloudflare, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /examples/hello-world/README.md: -------------------------------------------------------------------------------- 1 | # A simple helloworld example with EdgeHub Router 2 | 3 | To generate using Wrangler, run this command: 4 | 5 | ```bash 6 | wrangler generate myapp https://github.com/edge-hub/router/tree/master/examples/hello-world 7 | ``` 8 | -------------------------------------------------------------------------------- /examples/hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edgerouter", 3 | "version": "1.0.0", 4 | "description": "Cloudflare worker EdgeRouter template", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "dev": "NODE_ENV=development npm run build" 9 | }, 10 | "author": "edgehub", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "@cloudflare/workers-types": "^1.0.1", 14 | "prettier": "^1.18.2", 15 | "ts-loader": "^6.0.4", 16 | "typescript": "^3.5.3", 17 | "webpack": "^4.35.3", 18 | "webpack-cli": "^3.3.6" 19 | }, 20 | "dependencies": { 21 | "@edgehub/router": "latest" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/hello-world/src/index.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRouter } from "@edgehub/router"; 2 | 3 | const worker = new EdgeRouter(); 4 | 5 | // Middleware to set a header for all routes 6 | worker.use((req, res) => { 7 | res.setHeader("x-router", "EdgeRouter"); 8 | }); 9 | 10 | // The worker responds with `Hello World` for requests to root URL(/). For every other path, it will fallback to origin response if its exists or error. 11 | worker.get("/", (req, res) => { 12 | return res.send(`Hello World`); 13 | }); 14 | 15 | worker.listen({ passThroughOnException: true }); 16 | -------------------------------------------------------------------------------- /examples/hello-world/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "module": "commonjs", 5 | "target": "esnext", 6 | "lib": ["esnext", "webworker"], 7 | "alwaysStrict": true, 8 | "strict": true, 9 | "preserveConstEnums": true, 10 | "moduleResolution": "node", 11 | "sourceMap": true, 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "./src/*.ts", 16 | "./test/*.ts", 17 | "./src/**/*.ts", 18 | "./test/**/*.ts", 19 | "./node_modules/@cloudflare/workers-types/index.d.ts" 20 | ], 21 | "exclude": ["node_modules/", "dist/"] 22 | } 23 | -------------------------------------------------------------------------------- /examples/hello-world/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const mode = process.env.NODE_ENV || "production"; 4 | 5 | module.exports = { 6 | output: { 7 | filename: `worker.js`, 8 | path: path.join(__dirname, "dist"), 9 | }, 10 | mode, 11 | resolve: { 12 | extensions: [".ts", ".tsx", ".js"], 13 | plugins: [], 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.tsx?$/, 19 | loader: "ts-loader", 20 | options: { 21 | transpileOnly: true, 22 | }, 23 | }, 24 | ], 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /examples/hello-world/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "hello-world" 2 | type = "webpack" 3 | workers_dev = true 4 | account_id = "" 5 | route = "" 6 | zone_id = "" 7 | webpack_config = "webpack.config.js" 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@edgehub/router", 3 | "version": "0.0.31", 4 | "description": "A minimal Express.js like router for cloudflare workers.", 5 | "keywords": [ 6 | "cloudflare", 7 | "workers", 8 | "router", 9 | "cloudflare-workers" 10 | ], 11 | "homepage": "https://github.com/edge-hub/router#readme", 12 | "bugs": { 13 | "url": "https://github.com/edge-hub/router/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/edge-hub/router.git" 18 | }, 19 | "engines": { 20 | "node": ">=10" 21 | }, 22 | "license": "MIT", 23 | "author": "vinaypuppal", 24 | "main": "index.js", 25 | "module": "index.js", 26 | "types": "index.d.ts", 27 | "sideEffects": false, 28 | "scripts": { 29 | "prebuild": "rimraf dist", 30 | "build": "tsc && yarn rollup -c rollup.config.js", 31 | "copypackage": "cp package.json dist/package.json && cp Readme.md dist/Readme.md", 32 | "dist": "yarn build && yarn copypackage", 33 | "release": "npm publish --access public dist/", 34 | "pre-release": "npm publish --access public --tag next dist/" 35 | }, 36 | "husky": { 37 | "hooks": { 38 | "pre-commit": "lint-staged" 39 | } 40 | }, 41 | "lint-staged": { 42 | "**/*.md": [ 43 | "prettier --write", 44 | "git add" 45 | ], 46 | "*.{js,ts,json}": [ 47 | "prettier --write", 48 | "git add" 49 | ] 50 | }, 51 | "dependencies": { 52 | "@cloudflare/kv-asset-handler": "^0.0.9", 53 | "@types/cookie": "^0.3.3", 54 | "@types/trouter": "^3.1.0", 55 | "cookie": "^0.4.0", 56 | "trouter": "^3.1.0" 57 | }, 58 | "devDependencies": { 59 | "@rollup/plugin-commonjs": "^11.0.2", 60 | "@rollup/plugin-node-resolve": "^7.1.1", 61 | "@types/jest": "^25.2.1", 62 | "husky": "^4.2.3", 63 | "lint-staged": "^10.0.10", 64 | "prettier": "^2.0.2", 65 | "rimraf": "^3.0.2", 66 | "rollup": "^2.6.0", 67 | "rollup-plugin-node-globals": "^1.4.0", 68 | "rollup-plugin-terser": "^5.3.0", 69 | "rollup-plugin-typescript2": "^0.27.0", 70 | "typescript": "^3.8.3" 71 | }, 72 | "filesize": { 73 | "track": [ 74 | "./dist/index.umd.js" 75 | ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | const { terser } = require("rollup-plugin-terser"); 2 | const resolve = require("@rollup/plugin-node-resolve"); 3 | const commonjs = require("@rollup/plugin-commonjs"); 4 | const globals = require("rollup-plugin-node-globals"); 5 | const typescript = require("rollup-plugin-typescript2"); 6 | 7 | export default [ 8 | { 9 | input: "src/index.ts", 10 | output: [ 11 | { 12 | file: "docs/_lib/index.umd.js", 13 | format: "umd", 14 | name: "EdgeRouter", 15 | esModule: false, 16 | }, 17 | ], 18 | plugins: [ 19 | typescript({ 20 | tsconfig: "tsconfig.json", 21 | tsconfigOverride: { compilerOptions: { declaration: false } }, 22 | }), 23 | commonjs(), 24 | resolve({ preferBuiltins: true, module: false, browser: true }), 25 | globals(), 26 | terser({ output: { comments: false } }), 27 | ], 28 | }, 29 | ]; 30 | -------------------------------------------------------------------------------- /src/context.ts: -------------------------------------------------------------------------------- 1 | export class Context { 2 | constructor(event: FetchEvent) {} 3 | protected _instanceToJson(instance: any) { 4 | return [...instance].reduce((obj, item) => { 5 | const key = item[0] as string; 6 | if (obj[key]) { 7 | obj[key] = Array.isArray(obj[key]) 8 | ? [...obj[key], item[1]] 9 | : [obj[key], item[1]]; 10 | return obj; 11 | } 12 | 13 | const prop: { [key: string]: any } = {}; 14 | prop[key] = item[1]; 15 | return { ...obj, ...prop }; 16 | }, {}); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/default.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRequest } from "./request"; 2 | import { EdgeResponse } from "./response"; 3 | 4 | export function onNoMatch() { 5 | return new Response(`404 - Resource not found`, { status: 404 }); 6 | } 7 | 8 | export function onError(error: Error, req: EdgeRequest, res: EdgeResponse) { 9 | const acceptHeader = req.headers.get("Accept"); 10 | if (acceptHeader && acceptHeader.includes("text/html")) { 11 | return res.status(500).send(error.message || error.toString()); 12 | } 13 | return res 14 | .status(500) 15 | .raw( 16 | JSON.stringify(error, Object.getOwnPropertyNames(error)), 17 | "application/json" 18 | ) 19 | .end(); 20 | } 21 | -------------------------------------------------------------------------------- /src/global.d.ts: -------------------------------------------------------------------------------- 1 | interface FetchEvent { 2 | passThroughOnException: () => void; 3 | } 4 | 5 | declare function addEventListener( 6 | type: "fetch", 7 | handler: (event: FetchEvent) => void 8 | ): undefined | null | Response | Promise; 9 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./router"; 2 | export * from "./types"; 3 | -------------------------------------------------------------------------------- /src/middlewares/cors.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRequest } from "../request"; 2 | import { EdgeResponse } from "../response"; 3 | import { RouteHandler } from "../types"; 4 | 5 | const DEFAULT_ALLOW_METHODS = [ 6 | "POST", 7 | "GET", 8 | "PUT", 9 | "PATCH", 10 | "DELETE", 11 | "OPTIONS", 12 | ]; 13 | 14 | const DEFAULT_ALLOW_HEADERS = [ 15 | "X-Requested-With", 16 | "Access-Control-Allow-Origin", 17 | "X-HTTP-Method-Override", 18 | "Content-Type", 19 | "Authorization", 20 | "Accept", 21 | ]; 22 | 23 | const DEFAULT_MAX_AGE_SECONDS = 60 * 60 * 24; // 24 hours 24 | 25 | type Origin = ((request: EdgeRequest) => string | boolean) | string | boolean; 26 | interface Options { 27 | origin?: Origin; 28 | maxAge?: number; 29 | allowMethods?: string[]; 30 | allowHeaders?: string[]; 31 | exposeHeaders?: string[]; 32 | allowCredentials?: boolean; 33 | } 34 | 35 | function getOriginValue(origin: Origin, request: EdgeRequest) { 36 | if (typeof origin === "function") { 37 | return origin(request); 38 | } 39 | if (typeof origin === "boolean") { 40 | return origin ? "*" : ""; 41 | } 42 | return origin; 43 | } 44 | 45 | export function cors(options: Options = {}): RouteHandler { 46 | return (req: EdgeRequest, res: EdgeResponse) => { 47 | const origin = options.origin || "*"; 48 | const maxAge = options.maxAge || DEFAULT_MAX_AGE_SECONDS; 49 | const allowMethods = options.allowMethods || DEFAULT_ALLOW_METHODS; 50 | const allowHeaders = options.allowHeaders || DEFAULT_ALLOW_HEADERS; 51 | const allowCredentials = options.allowCredentials || true; 52 | const exposeHeaders = options.exposeHeaders || []; 53 | 54 | const originValue = getOriginValue(origin, req); 55 | 56 | if (originValue) { 57 | res.setHeader("Access-Control-Allow-Origin", String(originValue)); 58 | } 59 | 60 | if (allowCredentials) { 61 | res.setHeader("Access-Control-Allow-Credentials", "true"); 62 | } 63 | 64 | if (exposeHeaders.length) { 65 | res.setHeader("Access-Control-Expose-Headers", exposeHeaders.join(",")); 66 | } 67 | 68 | const preFlight = req.method === "OPTIONS"; 69 | if (preFlight) { 70 | res.setHeader("Access-Control-Allow-Methods", allowMethods.join(",")); 71 | res.setHeader("Access-Control-Allow-Headers", allowHeaders.join(",")); 72 | res.setHeader("Access-Control-Max-Age", String(maxAge)); 73 | } 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /src/middlewares/static.ts: -------------------------------------------------------------------------------- 1 | import { Options } from "@cloudflare/kv-asset-handler/src/types"; 2 | import { getAssetFromKV } from "@cloudflare/kv-asset-handler"; 3 | 4 | import { EdgeRequest } from "../request"; 5 | import { EdgeResponse } from "../response"; 6 | import { RouteHandler } from "../types"; 7 | 8 | export function workersSite(options?: Partial): RouteHandler { 9 | return async (req: EdgeRequest, _res: EdgeResponse) => { 10 | try { 11 | const response = await getAssetFromKV(req._event, options); 12 | return response; 13 | } catch (error) { 14 | switch (error.status) { 15 | case 404: 16 | return; 17 | case 405: 18 | return; 19 | default: 20 | throw error; 21 | } 22 | } 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/request.ts: -------------------------------------------------------------------------------- 1 | import cookie from "cookie"; 2 | 3 | import { Context } from "./context"; 4 | import { VHostData } from "./types"; 5 | 6 | export class EdgeRequest extends Context { 7 | public _originalRequest: Request; 8 | public _event: FetchEvent; 9 | public vhost?: VHostData; 10 | public url: string; 11 | public hash: string; 12 | public host: string; 13 | public origin: string; 14 | public hostname: string; 15 | public pathname: string; 16 | public protocol: string; 17 | public subdomains: string[]; 18 | public method: string; 19 | public search: string; 20 | public querystring: string; 21 | public query: Record; 22 | public params: Record = {}; 23 | public cookies: Record = {}; 24 | public headers: Headers; 25 | public header: (name: string) => string | null; 26 | public body: () => Promise | void>; 27 | constructor(event: FetchEvent) { 28 | super(event); 29 | const { request } = event; 30 | const url = new URL(request.url); 31 | this._event = event; 32 | this._originalRequest = request; 33 | this.method = request.method; 34 | this.url = url.href; 35 | this.hostname = url.hostname; 36 | this.host = url.hostname; 37 | this.origin = url.origin; 38 | this.subdomains = url.hostname.split(".").reverse().slice(2); 39 | this.hash = url.hash; 40 | this.pathname = url.pathname; 41 | this.protocol = url.protocol.slice(0, -1); 42 | this.search = url.search; 43 | this.querystring = url.search.slice(1); 44 | this.query = this._instanceToJson(url.searchParams); 45 | this.cookies = cookie.parse(request.headers.get("cookie") || ""); 46 | this.headers = request.headers; 47 | this.header = this._header(request.headers); 48 | this.body = this._getBodyParserHelper(request.clone()); 49 | } 50 | private _getBodyParserHelper(request: Request) { 51 | return async () => { 52 | const parsableMethods = ["post", "put"]; 53 | if (!parsableMethods.includes(request.method.toLowerCase())) { 54 | return; 55 | } 56 | const contentType = request.headers.get("content-type"); 57 | if (contentType === "application/json") { 58 | return await request.json(); 59 | } 60 | if (contentType === "application/x-www-form-urlencoded") { 61 | const formData = await request.formData(); 62 | return this._instanceToJson(formData); 63 | } 64 | }; 65 | } 66 | private _header(headers: Headers) { 67 | return (name: string) => { 68 | return headers.get(name); 69 | }; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/response.ts: -------------------------------------------------------------------------------- 1 | import cookie, { CookieSerializeOptions } from "cookie"; 2 | 3 | import { Context } from "./context"; 4 | 5 | type Body = 6 | | Blob 7 | | BufferSource 8 | | FormData 9 | | URLSearchParams 10 | | ReadableStream 11 | | string; 12 | 13 | export class EdgeResponse extends Context { 14 | private headers: Headers | string[][] | Record = {}; 15 | private cookies: Record< 16 | string, 17 | { value: string; options?: CookieSerializeOptions } 18 | > = {}; 19 | private statusCode?: number; 20 | private statusText?: string; 21 | private body?: Body | null; 22 | private type?: string; 23 | public _response?: Response; 24 | public raw(data: any, type?: string) { 25 | this.body = data; 26 | if (type) { 27 | this.type = type; 28 | } 29 | return this; 30 | } 31 | public text(data: string) { 32 | this.body = data; 33 | if (!this.type) { 34 | this.type = "text/plain"; 35 | } 36 | return this; 37 | } 38 | public html(data: string) { 39 | this.body = data; 40 | if (!this.type) { 41 | this.type = "text/html; charset=utf-8"; 42 | } 43 | return this; 44 | } 45 | public status(code: number, statusText?: string) { 46 | this.statusCode = code; 47 | this.statusText = statusText; 48 | return this; 49 | } 50 | public setHeader(key: string, value: string | string[]) { 51 | this.headers = { 52 | ...this.headers, 53 | [key]: Array.isArray(value) ? value.join(",") : value, 54 | }; 55 | return this; 56 | } 57 | public setCookie( 58 | key: string, 59 | value: string, 60 | options?: CookieSerializeOptions 61 | ) { 62 | this.cookies = { 63 | ...this.cookies, 64 | [key]: { value, options }, 65 | }; 66 | return this; 67 | } 68 | public redirect(url: string, status?: number) { 69 | return Response.redirect(url, status); 70 | } 71 | public sendStatus(status: number) { 72 | const headers = this._getheaders(); 73 | return new Response(null, { status, headers }); 74 | } 75 | public end( 76 | data: { 77 | body?: Body | null; 78 | status?: number; 79 | statusText?: string; 80 | headers?: Headers | string[][] | Record; 81 | } = {} 82 | ) { 83 | const { 84 | headers: endHeaders = {}, 85 | status = this.statusCode, 86 | statusText = this.statusText, 87 | body = this.body, 88 | } = data; 89 | this.headers = { 90 | ...this.headers, 91 | ...endHeaders, 92 | }; 93 | const headers = this._getheaders(); 94 | return new Response(body, { status, headers, statusText }); 95 | } 96 | public json(data: object) { 97 | return this._json(data).end(); 98 | } 99 | public send(data?: string | number | boolean | object) { 100 | switch (typeof data) { 101 | case "boolean": 102 | case "number": { 103 | return this.text(String(data)).end(); 104 | } 105 | case "object": { 106 | return this._json(data).end(); 107 | } 108 | case "string": { 109 | return this.html(data).end(); 110 | } 111 | default: { 112 | return this.end(); 113 | } 114 | } 115 | } 116 | private _json(data: object) { 117 | this.body = JSON.stringify(data); 118 | if (!this.type) { 119 | this.type = "application/json"; 120 | } 121 | return this; 122 | } 123 | private _getheaders() { 124 | const cookieHeader = Object.keys(this.cookies).reduce( 125 | (p: string, key: string) => { 126 | const { value, options } = this.cookies[key]; 127 | return `${p}${cookie.serialize(key, value, options)}`; 128 | }, 129 | `` 130 | ); 131 | return { 132 | ...(this.type ? { "Content-Type": this.type } : {}), 133 | ...this.headers, 134 | "Set-Cookie": cookieHeader, 135 | }; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/router.ts: -------------------------------------------------------------------------------- 1 | import Trouter from "trouter"; 2 | 3 | import { 4 | RouteHandler, 5 | ErrorHandler, 6 | RouterOptions, 7 | NoMatchHandler, 8 | OnRequestOptions, 9 | BeforeResponseHandler, 10 | } from "./types"; 11 | import { EdgeRequest } from "./request"; 12 | import { EdgeResponse } from "./response"; 13 | 14 | export class EdgeRouter extends Trouter { 15 | private onNoMatch: NoMatchHandler | undefined; 16 | private onError: ErrorHandler | undefined; 17 | private onBeforeResponse: BeforeResponseHandler | undefined; 18 | 19 | constructor(options?: RouterOptions) { 20 | super(); 21 | this.onNoMatch = options ? options.onNoMatch : undefined; 22 | this.onError = options ? options.onError : undefined; 23 | this.onBeforeResponse = options ? options.onBeforeResponse : undefined; 24 | } 25 | 26 | public use( 27 | path: string | RegExp | RouteHandler, 28 | ...handlers: RouteHandler[] 29 | ) { 30 | if (typeof path === "function") { 31 | handlers.unshift(path); 32 | super.use("/", ...handlers); 33 | } else { 34 | super.use(path, ...handlers); 35 | } 36 | return this; 37 | } 38 | 39 | public async onRequest(event: FetchEvent, ctx?: OnRequestOptions) { 40 | const { request } = event; 41 | const req = new EdgeRequest(event); 42 | const res = new EdgeResponse(event); 43 | 44 | if (ctx && ctx.vhost) { 45 | req.vhost = ctx.vhost; 46 | } 47 | 48 | try { 49 | const { handlers, params } = this.find( 50 | request.method as Trouter.HTTPMethod, 51 | req.pathname 52 | ); 53 | req.params = params; 54 | 55 | for (const handler of handlers) { 56 | const _response = await handler(req, res); 57 | if (_response instanceof Response) { 58 | if (this.onBeforeResponse !== undefined) { 59 | res._response = _response; 60 | const _res = await this.onBeforeResponse(req, res); 61 | if (_res instanceof Response) return _res; 62 | } 63 | return _response; 64 | } 65 | } 66 | 67 | if (this.onNoMatch) { 68 | return this.onNoMatch(req, res); 69 | } 70 | console.warn( 71 | `No response was returned by any router handler. Did you forgot to return "res.send"?` 72 | ); 73 | } catch (error) { 74 | if (this.onError) { 75 | return this.onError(error, req, res); 76 | } 77 | } 78 | } 79 | 80 | public listen({ 81 | passThroughOnException = false, 82 | }: { 83 | passThroughOnException?: boolean; 84 | } = {}) { 85 | addEventListener("fetch", (event) => { 86 | if (passThroughOnException) { 87 | event.passThroughOnException(); 88 | if (this.onError) { 89 | console.warn( 90 | `You enabled passThroughOnException and also have onError handler so onError handler will be used if any of your route handlers throw error instead of fallingback to origin response!` 91 | ); 92 | } 93 | } else { 94 | if (!this.onError) { 95 | console.warn( 96 | `You did not passThroughOnException and also did not set onError handler so if any of your route handlers throw error it will be ignored and a generic worker error will be returned!` 97 | ); 98 | } 99 | } 100 | 101 | // Why? 102 | // Because when passThroughOnException is set we want to ignore errors and return response from origin. 103 | // Incase of error or no match router does not send any response so worker will send response from origin as it is. 104 | // We can override this by specifying error and nomatch handlers. 105 | // @ts-ignore 106 | event.respondWith(this.onRequest(event)); 107 | }); 108 | return this; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRequest } from "./request"; 2 | import { EdgeResponse } from "./response"; 3 | 4 | export type RouteHandler = ( 5 | req: EdgeRequest, 6 | res: EdgeResponse 7 | ) => Response | Promise | void; 8 | 9 | export type ErrorHandler = ( 10 | error: Error, 11 | req: EdgeRequest, 12 | res: EdgeResponse 13 | ) => Response | Promise; 14 | 15 | export type NoMatchHandler = ( 16 | req: EdgeRequest, 17 | res: EdgeResponse 18 | ) => Response | Promise; 19 | 20 | export type BeforeResponseHandler = ( 21 | req: EdgeRequest, 22 | res: EdgeResponse 23 | ) => Response | Promise | void; 24 | 25 | export interface RouterOptions { 26 | onError?: ErrorHandler; 27 | onNoMatch?: NoMatchHandler; 28 | onBeforeResponse?: BeforeResponseHandler; 29 | } 30 | 31 | export interface VHostData { 32 | host: string; 33 | params: string[]; 34 | } 35 | 36 | export interface OnRequestOptions { 37 | vhost?: VHostData; 38 | } 39 | -------------------------------------------------------------------------------- /src/vhost/index.ts: -------------------------------------------------------------------------------- 1 | import { EdgeRouter } from "../router"; 2 | import { 3 | VHostData, 4 | NoMatchHandler, 5 | ErrorHandler, 6 | RouterOptions, 7 | } from "../types"; 8 | import { EdgeRequest } from "../request"; 9 | import { EdgeResponse } from "../response"; 10 | 11 | const ASTERISK_REGEXP = /\*/g; 12 | const ASTERISK_REPLACE = "([^.]+)"; 13 | const END_ANCHORED_REGEXP = /(?:^|[^\\])(?:\\\\)*\$$/; 14 | const ESCAPE_REGEXP = /([.+?^=!:${}()|[\]/\\])/g; 15 | const ESCAPE_REPLACE = "\\$1"; 16 | 17 | interface HostHandler extends VHostData { 18 | router: EdgeRouter; 19 | } 20 | 21 | export class VHostRouter { 22 | private onNoMatch: NoMatchHandler | undefined; 23 | private onError: ErrorHandler | undefined; 24 | private routers: { pattern: RegExp; handler: EdgeRouter }[]; 25 | 26 | constructor(options?: Omit) { 27 | this.routers = []; 28 | this.onNoMatch = options ? options.onNoMatch : undefined; 29 | this.onError = options ? options.onError : undefined; 30 | } 31 | 32 | private isregexp(val: string | RegExp) { 33 | return Object.prototype.toString.call(val) === "[object RegExp]"; 34 | } 35 | 36 | private parseHost(val: string | RegExp) { 37 | let source = !this.isregexp(val) 38 | ? String(val) 39 | .replace(ESCAPE_REGEXP, ESCAPE_REPLACE) 40 | .replace(ASTERISK_REGEXP, ASTERISK_REPLACE) 41 | : (val as RegExp).source; 42 | 43 | if (source[0] !== "^") { 44 | source = "^" + source; 45 | } 46 | 47 | if (!END_ANCHORED_REGEXP.test(source)) { 48 | source += "$"; 49 | } 50 | 51 | return new RegExp(source, "i"); 52 | } 53 | 54 | private vhostOf(host: string, pattern: RegExp) { 55 | const match = pattern.exec(host); 56 | if (!match) { 57 | return; 58 | } 59 | 60 | const params: string[] = []; 61 | params.length = match.length - 1; 62 | for (var i = 1; i < match.length; i++) { 63 | params[i - 1] = match[i]; 64 | } 65 | 66 | return { 67 | host, 68 | params, 69 | }; 70 | } 71 | 72 | private find(host: string) { 73 | const handlers: HostHandler[] = []; 74 | for (const r of this.routers) { 75 | const data = this.vhostOf(host, r.pattern); 76 | if (data) { 77 | handlers.push({ 78 | ...data, 79 | router: r.handler, 80 | }); 81 | } 82 | } 83 | return handlers; 84 | } 85 | 86 | public use(hostPattern: string | RegExp, router: EdgeRouter) { 87 | const pattern = this.parseHost(hostPattern); 88 | this.routers.push({ pattern, handler: router }); 89 | return this; 90 | } 91 | 92 | public async onRequest(event: FetchEvent) { 93 | try { 94 | const { request } = event; 95 | const url = new URL(request.url); 96 | const host = url.host; 97 | const handlers = this.find(host); 98 | 99 | for (const handler of handlers) { 100 | const { router, ...data } = handler; 101 | const _response = await router.onRequest(event, { vhost: data }); 102 | if (_response instanceof Response) { 103 | return _response; 104 | } 105 | } 106 | 107 | if (this.onNoMatch) { 108 | const req = new EdgeRequest(event); 109 | const res = new EdgeResponse(event); 110 | return this.onNoMatch(req, res); 111 | } 112 | } catch (error) { 113 | console.log(error.stack); 114 | if (this.onError) { 115 | const req = new EdgeRequest(event); 116 | const res = new EdgeResponse(event); 117 | return this.onError(error, req, res); 118 | } 119 | } 120 | } 121 | 122 | public listen({ 123 | passThroughOnException = false, 124 | }: { 125 | passThroughOnException?: boolean; 126 | } = {}) { 127 | addEventListener("fetch", (event) => { 128 | if (passThroughOnException) { 129 | event.passThroughOnException(); 130 | if (this.onError) { 131 | console.warn( 132 | `You enabled passThroughOnException and also have onError handler so onError handler will be used if any of your route handlers throw error instead of fallingback to origin response!` 133 | ); 134 | } 135 | } else { 136 | if (!this.onError) { 137 | console.warn( 138 | `You did not passThroughOnException and also did not set onError handler so if any of your route handlers throw error it will be ignored and a generic worker error will be returned!` 139 | ); 140 | } 141 | } 142 | 143 | // Why? 144 | // Because when passThroughOnException is set we want to ignore errors and return response from origin. 145 | // Incase of error or no match router does not send any response so worker will send response from origin as it is. 146 | // We can override this by specifying error and nomatch handlers. 147 | // @ts-ignore 148 | event.respondWith(this.onRequest(event)); 149 | }); 150 | return this; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "module": "ESNext", 5 | "target": "esnext", 6 | "lib": ["esnext", "webworker"], 7 | "declaration": true, 8 | "alwaysStrict": true, 9 | "strict": true, 10 | "preserveConstEnums": true, 11 | "moduleResolution": "node", 12 | "sourceMap": false, 13 | "esModuleInterop": true 14 | }, 15 | "include": ["./src/**/*.ts"], 16 | "exclude": ["node_modules", "dist/"] 17 | } 18 | -------------------------------------------------------------------------------- /workers/.cargo-ok: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edge-hub/router/1b3d3ade7ebab9685da069d1634a8b32346f0bbf/workers/.cargo-ok -------------------------------------------------------------------------------- /workers/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | worker 3 | -------------------------------------------------------------------------------- /workers/index.js: -------------------------------------------------------------------------------- 1 | import { EdgeRouter, workersSite } from "@edgehub/router"; 2 | 3 | const worker = new EdgeRouter({ 4 | onNoMatch: (_req, res) => { 5 | return res.status(404).send(`Resource not found! Go Back`); 6 | }, 7 | }); 8 | 9 | worker.use(workersSite()); 10 | 11 | worker.listen({ passThroughOnException: true }); 12 | -------------------------------------------------------------------------------- /workers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "worker", 4 | "version": "1.0.0", 5 | "description": "A template for kick starting a Cloudflare Workers project", 6 | "main": "index.js", 7 | "author": "Ashley Lewis ", 8 | "license": "MIT", 9 | "dependencies": { 10 | "@cloudflare/kv-asset-handler": "^0.0.9", 11 | "@edgehub/router": "^0.0.4" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /workers/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@cloudflare/kv-asset-handler@^0.0.9": 6 | version "0.0.9" 7 | resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.0.9.tgz#b49247eb49819080ed0db796992e6e5dd7cd81ce" 8 | integrity sha512-OP+uwr+5VShB9ktzJvkwy1AibGaTV7EoHs/YMemUY56fgnqI+IlV++e4T6cTUfHDAfE/pdXMx7q4zMf90dU00Q== 9 | dependencies: 10 | "@types/mime" "^2.0.1" 11 | mime "^2.4.4" 12 | 13 | "@edgehub/router@^0.0.4": 14 | version "0.0.4" 15 | resolved "https://registry.yarnpkg.com/@edgehub/router/-/router-0.0.4.tgz#60c0e062dfa2f11e20c30fdca403d04909658054" 16 | integrity sha512-Q77yF+9NpElIi1emJ39t0AfxxUZagKT5pTvOCDt82qJBA2EPWSeY8LE2AmbHt72rYjuVO7MZGsY1ZsUJQHWTXw== 17 | dependencies: 18 | "@types/cookie" "^0.3.3" 19 | "@types/trouter" "^3.1.0" 20 | cookie "^0.4.0" 21 | trouter "^3.1.0" 22 | 23 | "@types/cookie@^0.3.3": 24 | version "0.3.3" 25 | resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" 26 | integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== 27 | 28 | "@types/mime@^2.0.1": 29 | version "2.0.1" 30 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" 31 | integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== 32 | 33 | "@types/trouter@^3.1.0": 34 | version "3.1.0" 35 | resolved "https://registry.yarnpkg.com/@types/trouter/-/trouter-3.1.0.tgz#8a3c7b34352b1cb454217a194e8bf03e5cdf7cc4" 36 | integrity sha512-4LPNrqSJknLzILMVXn2P/mh0djNgFvom4T9Y1hmhaB8OBm1cY71bMMSrGRu1q5qF4JZzY6iaGT11BHmCMY/NZg== 37 | 38 | cookie@^0.4.0: 39 | version "0.4.0" 40 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" 41 | integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== 42 | 43 | mime@^2.4.4: 44 | version "2.4.4" 45 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" 46 | integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== 47 | 48 | regexparam@^1.3.0: 49 | version "1.3.0" 50 | resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" 51 | integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== 52 | 53 | trouter@^3.1.0: 54 | version "3.1.0" 55 | resolved "https://registry.yarnpkg.com/trouter/-/trouter-3.1.0.tgz#76f4faea81d5ebd11bba4762c664a3b55eda9b23" 56 | integrity sha512-3Swwu638QQWOefHLss9cdyLi5/9BKYmXZEXpH0KOFfB9YZwUAwHbDAcoYxaHfqAeFvbi/LqAK7rGkhCr1v1BJA== 57 | dependencies: 58 | regexparam "^1.3.0" 59 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "edge-router-docs" 2 | type = "webpack" 3 | account_id = "861533869cd09ff8b4ef02d65205ac54" 4 | workers_dev = false 5 | route = "router.edgehub.in/*" 6 | zone_id = "bd3c7073a97220f7952e86912a574a7c" 7 | 8 | [site] 9 | bucket = "docs" 10 | entry-point = "workers" 11 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": 6 | version "7.8.3" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" 8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== 9 | dependencies: 10 | "@babel/highlight" "^7.8.3" 11 | 12 | "@babel/helper-validator-identifier@^7.9.0": 13 | version "7.9.0" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz#ad53562a7fc29b3b9a91bbf7d10397fd146346ed" 15 | integrity sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw== 16 | 17 | "@babel/highlight@^7.8.3": 18 | version "7.9.0" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" 20 | integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.9.0" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@babel/runtime@^7.8.7": 27 | version "7.9.2" 28 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" 29 | integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== 30 | dependencies: 31 | regenerator-runtime "^0.13.4" 32 | 33 | "@cloudflare/kv-asset-handler@^0.0.9": 34 | version "0.0.9" 35 | resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.0.9.tgz#b49247eb49819080ed0db796992e6e5dd7cd81ce" 36 | integrity sha512-OP+uwr+5VShB9ktzJvkwy1AibGaTV7EoHs/YMemUY56fgnqI+IlV++e4T6cTUfHDAfE/pdXMx7q4zMf90dU00Q== 37 | dependencies: 38 | "@types/mime" "^2.0.1" 39 | mime "^2.4.4" 40 | 41 | "@jest/types@^25.3.0": 42 | version "25.3.0" 43 | resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.3.0.tgz#88f94b277a1d028fd7117bc1f74451e0fc2131e7" 44 | integrity sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw== 45 | dependencies: 46 | "@types/istanbul-lib-coverage" "^2.0.0" 47 | "@types/istanbul-reports" "^1.1.1" 48 | "@types/yargs" "^15.0.0" 49 | chalk "^3.0.0" 50 | 51 | "@rollup/plugin-commonjs@^11.0.2": 52 | version "11.0.2" 53 | resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.0.2.tgz#837cc6950752327cb90177b608f0928a4e60b582" 54 | integrity sha512-MPYGZr0qdbV5zZj8/2AuomVpnRVXRU5XKXb3HVniwRoRCreGlf5kOE081isNWeiLIi6IYkwTX9zE0/c7V8g81g== 55 | dependencies: 56 | "@rollup/pluginutils" "^3.0.0" 57 | estree-walker "^1.0.1" 58 | is-reference "^1.1.2" 59 | magic-string "^0.25.2" 60 | resolve "^1.11.0" 61 | 62 | "@rollup/plugin-node-resolve@^7.1.1": 63 | version "7.1.1" 64 | resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.1.tgz#8c6e59c4b28baf9d223028d0e450e06a485bb2b7" 65 | integrity sha512-14ddhD7TnemeHE97a4rLOhobfYvUVcaYuqTnL8Ti7Jxi9V9Jr5LY7Gko4HZ5k4h4vqQM0gBQt6tsp9xXW94WPA== 66 | dependencies: 67 | "@rollup/pluginutils" "^3.0.6" 68 | "@types/resolve" "0.0.8" 69 | builtin-modules "^3.1.0" 70 | is-module "^1.0.0" 71 | resolve "^1.14.2" 72 | 73 | "@rollup/pluginutils@^3.0.0", "@rollup/pluginutils@^3.0.6", "@rollup/pluginutils@^3.0.8": 74 | version "3.0.8" 75 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.0.8.tgz#4e94d128d94b90699e517ef045422960d18c8fde" 76 | integrity sha512-rYGeAc4sxcZ+kPG/Tw4/fwJODC3IXHYDH4qusdN/b6aLw5LPUbzpecYbEJh4sVQGPFJxd2dBU4kc1H3oy9/bnw== 77 | dependencies: 78 | estree-walker "^1.0.1" 79 | 80 | "@samverschueren/stream-to-observable@^0.3.0": 81 | version "0.3.0" 82 | resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" 83 | integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg== 84 | dependencies: 85 | any-observable "^0.3.0" 86 | 87 | "@types/color-name@^1.1.1": 88 | version "1.1.1" 89 | resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" 90 | integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== 91 | 92 | "@types/cookie@^0.3.3": 93 | version "0.3.3" 94 | resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803" 95 | integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow== 96 | 97 | "@types/estree@0.0.39": 98 | version "0.0.39" 99 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" 100 | integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== 101 | 102 | "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": 103 | version "2.0.1" 104 | resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" 105 | integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== 106 | 107 | "@types/istanbul-lib-report@*": 108 | version "3.0.0" 109 | resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" 110 | integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== 111 | dependencies: 112 | "@types/istanbul-lib-coverage" "*" 113 | 114 | "@types/istanbul-reports@^1.1.1": 115 | version "1.1.1" 116 | resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" 117 | integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== 118 | dependencies: 119 | "@types/istanbul-lib-coverage" "*" 120 | "@types/istanbul-lib-report" "*" 121 | 122 | "@types/jest@^25.2.1": 123 | version "25.2.1" 124 | resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" 125 | integrity sha512-msra1bCaAeEdkSyA0CZ6gW1ukMIvZ5YoJkdXw/qhQdsuuDlFTcEUrUw8CLCPt2rVRUfXlClVvK2gvPs9IokZaA== 126 | dependencies: 127 | jest-diff "^25.2.1" 128 | pretty-format "^25.2.1" 129 | 130 | "@types/mime@^2.0.1": 131 | version "2.0.1" 132 | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" 133 | integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== 134 | 135 | "@types/node@*": 136 | version "13.11.1" 137 | resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.1.tgz#49a2a83df9d26daacead30d0ccc8762b128d53c7" 138 | integrity sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g== 139 | 140 | "@types/parse-json@^4.0.0": 141 | version "4.0.0" 142 | resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" 143 | integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== 144 | 145 | "@types/resolve@0.0.8": 146 | version "0.0.8" 147 | resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" 148 | integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== 149 | dependencies: 150 | "@types/node" "*" 151 | 152 | "@types/trouter@^3.1.0": 153 | version "3.1.0" 154 | resolved "https://registry.yarnpkg.com/@types/trouter/-/trouter-3.1.0.tgz#8a3c7b34352b1cb454217a194e8bf03e5cdf7cc4" 155 | integrity sha512-4LPNrqSJknLzILMVXn2P/mh0djNgFvom4T9Y1hmhaB8OBm1cY71bMMSrGRu1q5qF4JZzY6iaGT11BHmCMY/NZg== 156 | 157 | "@types/yargs-parser@*": 158 | version "15.0.0" 159 | resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" 160 | integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== 161 | 162 | "@types/yargs@^15.0.0": 163 | version "15.0.4" 164 | resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" 165 | integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== 166 | dependencies: 167 | "@types/yargs-parser" "*" 168 | 169 | acorn@^5.7.3: 170 | version "5.7.4" 171 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" 172 | integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== 173 | 174 | ansi-escapes@^3.0.0: 175 | version "3.2.0" 176 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" 177 | integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== 178 | 179 | ansi-regex@^2.0.0: 180 | version "2.1.1" 181 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 182 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 183 | 184 | ansi-regex@^3.0.0: 185 | version "3.0.0" 186 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 187 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 188 | 189 | ansi-regex@^5.0.0: 190 | version "5.0.0" 191 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 192 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== 193 | 194 | ansi-styles@^2.2.1: 195 | version "2.2.1" 196 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 197 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= 198 | 199 | ansi-styles@^3.2.1: 200 | version "3.2.1" 201 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 202 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 203 | dependencies: 204 | color-convert "^1.9.0" 205 | 206 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 207 | version "4.2.1" 208 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" 209 | integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== 210 | dependencies: 211 | "@types/color-name" "^1.1.1" 212 | color-convert "^2.0.1" 213 | 214 | any-observable@^0.3.0: 215 | version "0.3.0" 216 | resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" 217 | integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== 218 | 219 | balanced-match@^1.0.0: 220 | version "1.0.0" 221 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 222 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 223 | 224 | brace-expansion@^1.1.7: 225 | version "1.1.11" 226 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 227 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 228 | dependencies: 229 | balanced-match "^1.0.0" 230 | concat-map "0.0.1" 231 | 232 | braces@^3.0.1: 233 | version "3.0.2" 234 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 235 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 236 | dependencies: 237 | fill-range "^7.0.1" 238 | 239 | buffer-es6@^4.9.3: 240 | version "4.9.3" 241 | resolved "https://registry.yarnpkg.com/buffer-es6/-/buffer-es6-4.9.3.tgz#f26347b82df76fd37e18bcb5288c4970cfd5c404" 242 | integrity sha1-8mNHuC33b9N+GLy1KIxJcM/VxAQ= 243 | 244 | buffer-from@^1.0.0: 245 | version "1.1.1" 246 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 247 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 248 | 249 | builtin-modules@^3.1.0: 250 | version "3.1.0" 251 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" 252 | integrity sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw== 253 | 254 | callsites@^3.0.0: 255 | version "3.1.0" 256 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 257 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 258 | 259 | chalk@^1.0.0, chalk@^1.1.3: 260 | version "1.1.3" 261 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 262 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= 263 | dependencies: 264 | ansi-styles "^2.2.1" 265 | escape-string-regexp "^1.0.2" 266 | has-ansi "^2.0.0" 267 | strip-ansi "^3.0.0" 268 | supports-color "^2.0.0" 269 | 270 | chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: 271 | version "2.4.2" 272 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 273 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 274 | dependencies: 275 | ansi-styles "^3.2.1" 276 | escape-string-regexp "^1.0.5" 277 | supports-color "^5.3.0" 278 | 279 | chalk@^3.0.0: 280 | version "3.0.0" 281 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" 282 | integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== 283 | dependencies: 284 | ansi-styles "^4.1.0" 285 | supports-color "^7.1.0" 286 | 287 | ci-info@^2.0.0: 288 | version "2.0.0" 289 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" 290 | integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== 291 | 292 | cli-cursor@^2.0.0, cli-cursor@^2.1.0: 293 | version "2.1.0" 294 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 295 | integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= 296 | dependencies: 297 | restore-cursor "^2.0.0" 298 | 299 | cli-truncate@^0.2.1: 300 | version "0.2.1" 301 | resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" 302 | integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= 303 | dependencies: 304 | slice-ansi "0.0.4" 305 | string-width "^1.0.1" 306 | 307 | code-point-at@^1.0.0: 308 | version "1.1.0" 309 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 310 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 311 | 312 | color-convert@^1.9.0: 313 | version "1.9.3" 314 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 315 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 316 | dependencies: 317 | color-name "1.1.3" 318 | 319 | color-convert@^2.0.1: 320 | version "2.0.1" 321 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 322 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 323 | dependencies: 324 | color-name "~1.1.4" 325 | 326 | color-name@1.1.3: 327 | version "1.1.3" 328 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 329 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 330 | 331 | color-name@~1.1.4: 332 | version "1.1.4" 333 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 334 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 335 | 336 | commander@^2.20.0: 337 | version "2.20.3" 338 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 339 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 340 | 341 | commander@^4.0.1: 342 | version "4.1.1" 343 | resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" 344 | integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== 345 | 346 | commondir@^1.0.1: 347 | version "1.0.1" 348 | resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 349 | integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= 350 | 351 | compare-versions@^3.5.1: 352 | version "3.6.0" 353 | resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" 354 | integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== 355 | 356 | concat-map@0.0.1: 357 | version "0.0.1" 358 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 359 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 360 | 361 | cookie@^0.4.0: 362 | version "0.4.0" 363 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" 364 | integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== 365 | 366 | cosmiconfig@^6.0.0: 367 | version "6.0.0" 368 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" 369 | integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== 370 | dependencies: 371 | "@types/parse-json" "^4.0.0" 372 | import-fresh "^3.1.0" 373 | parse-json "^5.0.0" 374 | path-type "^4.0.0" 375 | yaml "^1.7.2" 376 | 377 | cross-spawn@^7.0.0: 378 | version "7.0.1" 379 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" 380 | integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== 381 | dependencies: 382 | path-key "^3.1.0" 383 | shebang-command "^2.0.0" 384 | which "^2.0.1" 385 | 386 | date-fns@^1.27.2: 387 | version "1.30.1" 388 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" 389 | integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== 390 | 391 | debug@^4.1.1: 392 | version "4.1.1" 393 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 394 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 395 | dependencies: 396 | ms "^2.1.1" 397 | 398 | dedent@^0.7.0: 399 | version "0.7.0" 400 | resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" 401 | integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= 402 | 403 | diff-sequences@^25.2.6: 404 | version "25.2.6" 405 | resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" 406 | integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== 407 | 408 | elegant-spinner@^1.0.1: 409 | version "1.0.1" 410 | resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" 411 | integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= 412 | 413 | end-of-stream@^1.1.0: 414 | version "1.4.4" 415 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 416 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 417 | dependencies: 418 | once "^1.4.0" 419 | 420 | error-ex@^1.3.1: 421 | version "1.3.2" 422 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 423 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 424 | dependencies: 425 | is-arrayish "^0.2.1" 426 | 427 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 428 | version "1.0.5" 429 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 430 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 431 | 432 | estree-walker@^0.5.2: 433 | version "0.5.2" 434 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" 435 | integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig== 436 | 437 | estree-walker@^0.6.1: 438 | version "0.6.1" 439 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" 440 | integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== 441 | 442 | estree-walker@^1.0.1: 443 | version "1.0.1" 444 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" 445 | integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== 446 | 447 | execa@^3.4.0: 448 | version "3.4.0" 449 | resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" 450 | integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== 451 | dependencies: 452 | cross-spawn "^7.0.0" 453 | get-stream "^5.0.0" 454 | human-signals "^1.1.1" 455 | is-stream "^2.0.0" 456 | merge-stream "^2.0.0" 457 | npm-run-path "^4.0.0" 458 | onetime "^5.1.0" 459 | p-finally "^2.0.0" 460 | signal-exit "^3.0.2" 461 | strip-final-newline "^2.0.0" 462 | 463 | figures@^1.7.0: 464 | version "1.7.0" 465 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 466 | integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= 467 | dependencies: 468 | escape-string-regexp "^1.0.5" 469 | object-assign "^4.1.0" 470 | 471 | figures@^2.0.0: 472 | version "2.0.0" 473 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 474 | integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= 475 | dependencies: 476 | escape-string-regexp "^1.0.5" 477 | 478 | fill-range@^7.0.1: 479 | version "7.0.1" 480 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 481 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 482 | dependencies: 483 | to-regex-range "^5.0.1" 484 | 485 | find-cache-dir@^3.3.1: 486 | version "3.3.1" 487 | resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" 488 | integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== 489 | dependencies: 490 | commondir "^1.0.1" 491 | make-dir "^3.0.2" 492 | pkg-dir "^4.1.0" 493 | 494 | find-up@^4.0.0: 495 | version "4.1.0" 496 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 497 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 498 | dependencies: 499 | locate-path "^5.0.0" 500 | path-exists "^4.0.0" 501 | 502 | find-versions@^3.2.0: 503 | version "3.2.0" 504 | resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" 505 | integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== 506 | dependencies: 507 | semver-regex "^2.0.0" 508 | 509 | fs-extra@8.1.0: 510 | version "8.1.0" 511 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" 512 | integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== 513 | dependencies: 514 | graceful-fs "^4.2.0" 515 | jsonfile "^4.0.0" 516 | universalify "^0.1.0" 517 | 518 | fs.realpath@^1.0.0: 519 | version "1.0.0" 520 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 521 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 522 | 523 | fsevents@~2.1.2: 524 | version "2.1.2" 525 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" 526 | integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== 527 | 528 | get-own-enumerable-property-symbols@^3.0.0: 529 | version "3.0.2" 530 | resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" 531 | integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== 532 | 533 | get-stream@^5.0.0: 534 | version "5.1.0" 535 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" 536 | integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== 537 | dependencies: 538 | pump "^3.0.0" 539 | 540 | glob@^7.1.3: 541 | version "7.1.6" 542 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 543 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 544 | dependencies: 545 | fs.realpath "^1.0.0" 546 | inflight "^1.0.4" 547 | inherits "2" 548 | minimatch "^3.0.4" 549 | once "^1.3.0" 550 | path-is-absolute "^1.0.0" 551 | 552 | graceful-fs@^4.1.6, graceful-fs@^4.2.0: 553 | version "4.2.3" 554 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" 555 | integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== 556 | 557 | has-ansi@^2.0.0: 558 | version "2.0.0" 559 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 560 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= 561 | dependencies: 562 | ansi-regex "^2.0.0" 563 | 564 | has-flag@^3.0.0: 565 | version "3.0.0" 566 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 567 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 568 | 569 | has-flag@^4.0.0: 570 | version "4.0.0" 571 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 572 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 573 | 574 | human-signals@^1.1.1: 575 | version "1.1.1" 576 | resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" 577 | integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== 578 | 579 | husky@^4.2.3: 580 | version "4.2.3" 581 | resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.3.tgz#3b18d2ee5febe99e27f2983500202daffbc3151e" 582 | integrity sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ== 583 | dependencies: 584 | chalk "^3.0.0" 585 | ci-info "^2.0.0" 586 | compare-versions "^3.5.1" 587 | cosmiconfig "^6.0.0" 588 | find-versions "^3.2.0" 589 | opencollective-postinstall "^2.0.2" 590 | pkg-dir "^4.2.0" 591 | please-upgrade-node "^3.2.0" 592 | slash "^3.0.0" 593 | which-pm-runs "^1.0.0" 594 | 595 | import-fresh@^3.1.0: 596 | version "3.2.1" 597 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" 598 | integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== 599 | dependencies: 600 | parent-module "^1.0.0" 601 | resolve-from "^4.0.0" 602 | 603 | indent-string@^3.0.0: 604 | version "3.2.0" 605 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" 606 | integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= 607 | 608 | inflight@^1.0.4: 609 | version "1.0.6" 610 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 611 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 612 | dependencies: 613 | once "^1.3.0" 614 | wrappy "1" 615 | 616 | inherits@2: 617 | version "2.0.4" 618 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 619 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 620 | 621 | is-arrayish@^0.2.1: 622 | version "0.2.1" 623 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 624 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 625 | 626 | is-fullwidth-code-point@^1.0.0: 627 | version "1.0.0" 628 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 629 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 630 | dependencies: 631 | number-is-nan "^1.0.0" 632 | 633 | is-fullwidth-code-point@^2.0.0: 634 | version "2.0.0" 635 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 636 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 637 | 638 | is-module@^1.0.0: 639 | version "1.0.0" 640 | resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" 641 | integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= 642 | 643 | is-number@^7.0.0: 644 | version "7.0.0" 645 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 646 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 647 | 648 | is-obj@^1.0.1: 649 | version "1.0.1" 650 | resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 651 | integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= 652 | 653 | is-observable@^1.1.0: 654 | version "1.1.0" 655 | resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" 656 | integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== 657 | dependencies: 658 | symbol-observable "^1.1.0" 659 | 660 | is-promise@^2.1.0: 661 | version "2.1.0" 662 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 663 | integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= 664 | 665 | is-reference@^1.1.2: 666 | version "1.1.4" 667 | resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.1.4.tgz#3f95849886ddb70256a3e6d062b1a68c13c51427" 668 | integrity sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw== 669 | dependencies: 670 | "@types/estree" "0.0.39" 671 | 672 | is-regexp@^1.0.0: 673 | version "1.0.0" 674 | resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" 675 | integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= 676 | 677 | is-stream@^1.1.0: 678 | version "1.1.0" 679 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 680 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 681 | 682 | is-stream@^2.0.0: 683 | version "2.0.0" 684 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 685 | integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== 686 | 687 | isexe@^2.0.0: 688 | version "2.0.0" 689 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 690 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 691 | 692 | jest-diff@^25.2.1: 693 | version "25.3.0" 694 | resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" 695 | integrity sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w== 696 | dependencies: 697 | chalk "^3.0.0" 698 | diff-sequences "^25.2.6" 699 | jest-get-type "^25.2.6" 700 | pretty-format "^25.3.0" 701 | 702 | jest-get-type@^25.2.6: 703 | version "25.2.6" 704 | resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" 705 | integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== 706 | 707 | jest-worker@^24.9.0: 708 | version "24.9.0" 709 | resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" 710 | integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== 711 | dependencies: 712 | merge-stream "^2.0.0" 713 | supports-color "^6.1.0" 714 | 715 | js-tokens@^4.0.0: 716 | version "4.0.0" 717 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 718 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 719 | 720 | json-parse-better-errors@^1.0.1: 721 | version "1.0.2" 722 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 723 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 724 | 725 | jsonfile@^4.0.0: 726 | version "4.0.0" 727 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" 728 | integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= 729 | optionalDependencies: 730 | graceful-fs "^4.1.6" 731 | 732 | lines-and-columns@^1.1.6: 733 | version "1.1.6" 734 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 735 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 736 | 737 | lint-staged@^10.0.10: 738 | version "10.0.10" 739 | resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.0.10.tgz#d14d33ee02a31a31ad36cf9aa7973fc156c461b5" 740 | integrity sha512-91vNy3eYStExElLWw1Idva5lghKpFaXh9AJqjcyrJXf7AYZrThi4EhQ+GpmiHdPmJJauKhZMMSzQR1bMB90MtA== 741 | dependencies: 742 | chalk "^3.0.0" 743 | commander "^4.0.1" 744 | cosmiconfig "^6.0.0" 745 | debug "^4.1.1" 746 | dedent "^0.7.0" 747 | execa "^3.4.0" 748 | listr "^0.14.3" 749 | log-symbols "^3.0.0" 750 | micromatch "^4.0.2" 751 | normalize-path "^3.0.0" 752 | please-upgrade-node "^3.2.0" 753 | string-argv "0.3.1" 754 | stringify-object "^3.3.0" 755 | 756 | listr-silent-renderer@^1.1.1: 757 | version "1.1.1" 758 | resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" 759 | integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= 760 | 761 | listr-update-renderer@^0.5.0: 762 | version "0.5.0" 763 | resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" 764 | integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== 765 | dependencies: 766 | chalk "^1.1.3" 767 | cli-truncate "^0.2.1" 768 | elegant-spinner "^1.0.1" 769 | figures "^1.7.0" 770 | indent-string "^3.0.0" 771 | log-symbols "^1.0.2" 772 | log-update "^2.3.0" 773 | strip-ansi "^3.0.1" 774 | 775 | listr-verbose-renderer@^0.5.0: 776 | version "0.5.0" 777 | resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" 778 | integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== 779 | dependencies: 780 | chalk "^2.4.1" 781 | cli-cursor "^2.1.0" 782 | date-fns "^1.27.2" 783 | figures "^2.0.0" 784 | 785 | listr@^0.14.3: 786 | version "0.14.3" 787 | resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" 788 | integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== 789 | dependencies: 790 | "@samverschueren/stream-to-observable" "^0.3.0" 791 | is-observable "^1.1.0" 792 | is-promise "^2.1.0" 793 | is-stream "^1.1.0" 794 | listr-silent-renderer "^1.1.1" 795 | listr-update-renderer "^0.5.0" 796 | listr-verbose-renderer "^0.5.0" 797 | p-map "^2.0.0" 798 | rxjs "^6.3.3" 799 | 800 | locate-path@^5.0.0: 801 | version "5.0.0" 802 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 803 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 804 | dependencies: 805 | p-locate "^4.1.0" 806 | 807 | log-symbols@^1.0.2: 808 | version "1.0.2" 809 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" 810 | integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= 811 | dependencies: 812 | chalk "^1.0.0" 813 | 814 | log-symbols@^3.0.0: 815 | version "3.0.0" 816 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" 817 | integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== 818 | dependencies: 819 | chalk "^2.4.2" 820 | 821 | log-update@^2.3.0: 822 | version "2.3.0" 823 | resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" 824 | integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= 825 | dependencies: 826 | ansi-escapes "^3.0.0" 827 | cli-cursor "^2.0.0" 828 | wrap-ansi "^3.0.1" 829 | 830 | magic-string@^0.22.5: 831 | version "0.22.5" 832 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" 833 | integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== 834 | dependencies: 835 | vlq "^0.2.2" 836 | 837 | magic-string@^0.25.2: 838 | version "0.25.7" 839 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" 840 | integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== 841 | dependencies: 842 | sourcemap-codec "^1.4.4" 843 | 844 | make-dir@^3.0.2: 845 | version "3.0.2" 846 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392" 847 | integrity sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w== 848 | dependencies: 849 | semver "^6.0.0" 850 | 851 | merge-stream@^2.0.0: 852 | version "2.0.0" 853 | resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" 854 | integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== 855 | 856 | micromatch@^4.0.2: 857 | version "4.0.2" 858 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" 859 | integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== 860 | dependencies: 861 | braces "^3.0.1" 862 | picomatch "^2.0.5" 863 | 864 | mime@^2.4.4: 865 | version "2.4.4" 866 | resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" 867 | integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== 868 | 869 | mimic-fn@^1.0.0: 870 | version "1.2.0" 871 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 872 | integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== 873 | 874 | mimic-fn@^2.1.0: 875 | version "2.1.0" 876 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 877 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 878 | 879 | minimatch@^3.0.4: 880 | version "3.0.4" 881 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 882 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 883 | dependencies: 884 | brace-expansion "^1.1.7" 885 | 886 | ms@^2.1.1: 887 | version "2.1.2" 888 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 889 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 890 | 891 | normalize-path@^3.0.0: 892 | version "3.0.0" 893 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 894 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 895 | 896 | npm-run-path@^4.0.0: 897 | version "4.0.1" 898 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" 899 | integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== 900 | dependencies: 901 | path-key "^3.0.0" 902 | 903 | number-is-nan@^1.0.0: 904 | version "1.0.1" 905 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 906 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 907 | 908 | object-assign@^4.1.0: 909 | version "4.1.1" 910 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 911 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 912 | 913 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 914 | version "1.4.0" 915 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 916 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 917 | dependencies: 918 | wrappy "1" 919 | 920 | onetime@^2.0.0: 921 | version "2.0.1" 922 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 923 | integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= 924 | dependencies: 925 | mimic-fn "^1.0.0" 926 | 927 | onetime@^5.1.0: 928 | version "5.1.0" 929 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" 930 | integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== 931 | dependencies: 932 | mimic-fn "^2.1.0" 933 | 934 | opencollective-postinstall@^2.0.2: 935 | version "2.0.2" 936 | resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" 937 | integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== 938 | 939 | p-finally@^2.0.0: 940 | version "2.0.1" 941 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" 942 | integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== 943 | 944 | p-limit@^2.2.0: 945 | version "2.2.2" 946 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" 947 | integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== 948 | dependencies: 949 | p-try "^2.0.0" 950 | 951 | p-locate@^4.1.0: 952 | version "4.1.0" 953 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 954 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 955 | dependencies: 956 | p-limit "^2.2.0" 957 | 958 | p-map@^2.0.0: 959 | version "2.1.0" 960 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" 961 | integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== 962 | 963 | p-try@^2.0.0: 964 | version "2.2.0" 965 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 966 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 967 | 968 | parent-module@^1.0.0: 969 | version "1.0.1" 970 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 971 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 972 | dependencies: 973 | callsites "^3.0.0" 974 | 975 | parse-json@^5.0.0: 976 | version "5.0.0" 977 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" 978 | integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== 979 | dependencies: 980 | "@babel/code-frame" "^7.0.0" 981 | error-ex "^1.3.1" 982 | json-parse-better-errors "^1.0.1" 983 | lines-and-columns "^1.1.6" 984 | 985 | path-exists@^4.0.0: 986 | version "4.0.0" 987 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 988 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 989 | 990 | path-is-absolute@^1.0.0: 991 | version "1.0.1" 992 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 993 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 994 | 995 | path-key@^3.0.0, path-key@^3.1.0: 996 | version "3.1.1" 997 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 998 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 999 | 1000 | path-parse@^1.0.6: 1001 | version "1.0.6" 1002 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 1003 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 1004 | 1005 | path-type@^4.0.0: 1006 | version "4.0.0" 1007 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 1008 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1009 | 1010 | picomatch@^2.0.5: 1011 | version "2.2.2" 1012 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" 1013 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 1014 | 1015 | pkg-dir@^4.1.0, pkg-dir@^4.2.0: 1016 | version "4.2.0" 1017 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1018 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1019 | dependencies: 1020 | find-up "^4.0.0" 1021 | 1022 | please-upgrade-node@^3.2.0: 1023 | version "3.2.0" 1024 | resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" 1025 | integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== 1026 | dependencies: 1027 | semver-compare "^1.0.0" 1028 | 1029 | prettier@^2.0.2: 1030 | version "2.0.2" 1031 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08" 1032 | integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg== 1033 | 1034 | pretty-format@^25.2.1, pretty-format@^25.3.0: 1035 | version "25.3.0" 1036 | resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.3.0.tgz#d0a4f988ff4a6cd350342fdabbb809aeb4d49ad5" 1037 | integrity sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA== 1038 | dependencies: 1039 | "@jest/types" "^25.3.0" 1040 | ansi-regex "^5.0.0" 1041 | ansi-styles "^4.0.0" 1042 | react-is "^16.12.0" 1043 | 1044 | process-es6@^0.11.6: 1045 | version "0.11.6" 1046 | resolved "https://registry.yarnpkg.com/process-es6/-/process-es6-0.11.6.tgz#c6bb389f9a951f82bd4eb169600105bd2ff9c778" 1047 | integrity sha1-xrs4n5qVH4K9TrFpYAEFvS/5x3g= 1048 | 1049 | pump@^3.0.0: 1050 | version "3.0.0" 1051 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1052 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 1053 | dependencies: 1054 | end-of-stream "^1.1.0" 1055 | once "^1.3.1" 1056 | 1057 | react-is@^16.12.0: 1058 | version "16.13.1" 1059 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" 1060 | integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== 1061 | 1062 | regenerator-runtime@^0.13.4: 1063 | version "0.13.5" 1064 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" 1065 | integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== 1066 | 1067 | regexparam@^1.3.0: 1068 | version "1.3.0" 1069 | resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" 1070 | integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== 1071 | 1072 | resolve-from@^4.0.0: 1073 | version "4.0.0" 1074 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1075 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1076 | 1077 | resolve@1.15.1, resolve@^1.11.0, resolve@^1.14.2: 1078 | version "1.15.1" 1079 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" 1080 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== 1081 | dependencies: 1082 | path-parse "^1.0.6" 1083 | 1084 | restore-cursor@^2.0.0: 1085 | version "2.0.0" 1086 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 1087 | integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= 1088 | dependencies: 1089 | onetime "^2.0.0" 1090 | signal-exit "^3.0.2" 1091 | 1092 | rimraf@^3.0.2: 1093 | version "3.0.2" 1094 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 1095 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 1096 | dependencies: 1097 | glob "^7.1.3" 1098 | 1099 | rollup-plugin-node-globals@^1.4.0: 1100 | version "1.4.0" 1101 | resolved "https://registry.yarnpkg.com/rollup-plugin-node-globals/-/rollup-plugin-node-globals-1.4.0.tgz#5e1f24a9bb97c0ef51249f625e16c7e61b7c020b" 1102 | integrity sha512-xRkB+W/m1KLIzPUmG0ofvR+CPNcvuCuNdjVBVS7ALKSxr3EDhnzNceGkGi1m8MToSli13AzKFYH4ie9w3I5L3g== 1103 | dependencies: 1104 | acorn "^5.7.3" 1105 | buffer-es6 "^4.9.3" 1106 | estree-walker "^0.5.2" 1107 | magic-string "^0.22.5" 1108 | process-es6 "^0.11.6" 1109 | rollup-pluginutils "^2.3.1" 1110 | 1111 | rollup-plugin-terser@^5.3.0: 1112 | version "5.3.0" 1113 | resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz#9c0dd33d5771df9630cd027d6a2559187f65885e" 1114 | integrity sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g== 1115 | dependencies: 1116 | "@babel/code-frame" "^7.5.5" 1117 | jest-worker "^24.9.0" 1118 | rollup-pluginutils "^2.8.2" 1119 | serialize-javascript "^2.1.2" 1120 | terser "^4.6.2" 1121 | 1122 | rollup-plugin-typescript2@^0.27.0: 1123 | version "0.27.0" 1124 | resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.27.0.tgz#95ff96f9e07d5000a9d2df4d76b548f9a1f83511" 1125 | integrity sha512-SRKG/Canve3cxBsqhY1apIBznqnX9X/WU3Lrq3XSwmTmFqccj3+//logLXFEmp+PYFNllSVng+f4zjqRTPKNkA== 1126 | dependencies: 1127 | "@rollup/pluginutils" "^3.0.8" 1128 | find-cache-dir "^3.3.1" 1129 | fs-extra "8.1.0" 1130 | resolve "1.15.1" 1131 | tslib "1.11.1" 1132 | 1133 | rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.8.2: 1134 | version "2.8.2" 1135 | resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" 1136 | integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== 1137 | dependencies: 1138 | estree-walker "^0.6.1" 1139 | 1140 | rollup@^2.6.0: 1141 | version "2.6.0" 1142 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.6.0.tgz#e69d50dc2217af23ab5f6df9a48e45df4ab56df1" 1143 | integrity sha512-qbvQ9ZbvbhBdtRBZ/A4g+9z3iJQ1rHAtjinn3FiN+j5tfz8xiNyTE1JEEMcFWqlH7+NHadI9ieeqKdp8HwYLnQ== 1144 | optionalDependencies: 1145 | fsevents "~2.1.2" 1146 | 1147 | rxjs@^6.3.3: 1148 | version "6.5.4" 1149 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" 1150 | integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== 1151 | dependencies: 1152 | tslib "^1.9.0" 1153 | 1154 | semver-compare@^1.0.0: 1155 | version "1.0.0" 1156 | resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" 1157 | integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= 1158 | 1159 | semver-regex@^2.0.0: 1160 | version "2.0.0" 1161 | resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" 1162 | integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== 1163 | 1164 | semver@^6.0.0: 1165 | version "6.3.0" 1166 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" 1167 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 1168 | 1169 | serialize-javascript@^2.1.2: 1170 | version "2.1.2" 1171 | resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" 1172 | integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== 1173 | 1174 | shebang-command@^2.0.0: 1175 | version "2.0.0" 1176 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1177 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1178 | dependencies: 1179 | shebang-regex "^3.0.0" 1180 | 1181 | shebang-regex@^3.0.0: 1182 | version "3.0.0" 1183 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1184 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1185 | 1186 | signal-exit@^3.0.2: 1187 | version "3.0.3" 1188 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 1189 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 1190 | 1191 | slash@^3.0.0: 1192 | version "3.0.0" 1193 | resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" 1194 | integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 1195 | 1196 | slice-ansi@0.0.4: 1197 | version "0.0.4" 1198 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" 1199 | integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= 1200 | 1201 | source-map-support@~0.5.12: 1202 | version "0.5.16" 1203 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" 1204 | integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== 1205 | dependencies: 1206 | buffer-from "^1.0.0" 1207 | source-map "^0.6.0" 1208 | 1209 | source-map@^0.6.0, source-map@~0.6.1: 1210 | version "0.6.1" 1211 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1212 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 1213 | 1214 | sourcemap-codec@^1.4.4: 1215 | version "1.4.8" 1216 | resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" 1217 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== 1218 | 1219 | string-argv@0.3.1: 1220 | version "0.3.1" 1221 | resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" 1222 | integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== 1223 | 1224 | string-width@^1.0.1: 1225 | version "1.0.2" 1226 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1227 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 1228 | dependencies: 1229 | code-point-at "^1.0.0" 1230 | is-fullwidth-code-point "^1.0.0" 1231 | strip-ansi "^3.0.0" 1232 | 1233 | string-width@^2.1.1: 1234 | version "2.1.1" 1235 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1236 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 1237 | dependencies: 1238 | is-fullwidth-code-point "^2.0.0" 1239 | strip-ansi "^4.0.0" 1240 | 1241 | stringify-object@^3.3.0: 1242 | version "3.3.0" 1243 | resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" 1244 | integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== 1245 | dependencies: 1246 | get-own-enumerable-property-symbols "^3.0.0" 1247 | is-obj "^1.0.1" 1248 | is-regexp "^1.0.0" 1249 | 1250 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 1251 | version "3.0.1" 1252 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1253 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 1254 | dependencies: 1255 | ansi-regex "^2.0.0" 1256 | 1257 | strip-ansi@^4.0.0: 1258 | version "4.0.0" 1259 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1260 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 1261 | dependencies: 1262 | ansi-regex "^3.0.0" 1263 | 1264 | strip-final-newline@^2.0.0: 1265 | version "2.0.0" 1266 | resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" 1267 | integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== 1268 | 1269 | supports-color@^2.0.0: 1270 | version "2.0.0" 1271 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1272 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= 1273 | 1274 | supports-color@^5.3.0: 1275 | version "5.5.0" 1276 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1277 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1278 | dependencies: 1279 | has-flag "^3.0.0" 1280 | 1281 | supports-color@^6.1.0: 1282 | version "6.1.0" 1283 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" 1284 | integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== 1285 | dependencies: 1286 | has-flag "^3.0.0" 1287 | 1288 | supports-color@^7.1.0: 1289 | version "7.1.0" 1290 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" 1291 | integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== 1292 | dependencies: 1293 | has-flag "^4.0.0" 1294 | 1295 | symbol-observable@^1.1.0: 1296 | version "1.2.0" 1297 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" 1298 | integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== 1299 | 1300 | terser@^4.6.2: 1301 | version "4.6.11" 1302 | resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.11.tgz#12ff99fdd62a26de2a82f508515407eb6ccd8a9f" 1303 | integrity sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA== 1304 | dependencies: 1305 | commander "^2.20.0" 1306 | source-map "~0.6.1" 1307 | source-map-support "~0.5.12" 1308 | 1309 | to-regex-range@^5.0.1: 1310 | version "5.0.1" 1311 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1312 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1313 | dependencies: 1314 | is-number "^7.0.0" 1315 | 1316 | trouter@^3.1.0: 1317 | version "3.1.0" 1318 | resolved "https://registry.yarnpkg.com/trouter/-/trouter-3.1.0.tgz#76f4faea81d5ebd11bba4762c664a3b55eda9b23" 1319 | integrity sha512-3Swwu638QQWOefHLss9cdyLi5/9BKYmXZEXpH0KOFfB9YZwUAwHbDAcoYxaHfqAeFvbi/LqAK7rGkhCr1v1BJA== 1320 | dependencies: 1321 | regexparam "^1.3.0" 1322 | 1323 | tslib@1.11.1, tslib@^1.9.0: 1324 | version "1.11.1" 1325 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" 1326 | integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== 1327 | 1328 | typescript@^3.8.3: 1329 | version "3.8.3" 1330 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" 1331 | integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== 1332 | 1333 | universalify@^0.1.0: 1334 | version "0.1.2" 1335 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 1336 | integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 1337 | 1338 | vlq@^0.2.2: 1339 | version "0.2.3" 1340 | resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" 1341 | integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== 1342 | 1343 | which-pm-runs@^1.0.0: 1344 | version "1.0.0" 1345 | resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" 1346 | integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= 1347 | 1348 | which@^2.0.1: 1349 | version "2.0.2" 1350 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1351 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1352 | dependencies: 1353 | isexe "^2.0.0" 1354 | 1355 | wrap-ansi@^3.0.1: 1356 | version "3.0.1" 1357 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" 1358 | integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= 1359 | dependencies: 1360 | string-width "^2.1.1" 1361 | strip-ansi "^4.0.0" 1362 | 1363 | wrappy@1: 1364 | version "1.0.2" 1365 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1366 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1367 | 1368 | yaml@^1.7.2: 1369 | version "1.8.3" 1370 | resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.8.3.tgz#2f420fca58b68ce3a332d0ca64be1d191dd3f87a" 1371 | integrity sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw== 1372 | dependencies: 1373 | "@babel/runtime" "^7.8.7" 1374 | --------------------------------------------------------------------------------