├── .babelrc ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .node-version ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .storybook ├── addons.js ├── config.js ├── public │ └── assets └── webpack.config.js ├── .vscode ├── extensions.json └── settings.json ├── .yarn-version ├── LICENSE ├── README.md ├── assets ├── global.css └── logo.svg ├── dist └── .gitkeep ├── flow-typed └── npm │ ├── @babel │ ├── cli_vx.x.x.js │ ├── core_vx.x.x.js │ ├── plugin-transform-flow-strip-types_vx.x.x.js │ └── preset-react_vx.x.x.js │ ├── @storybook │ ├── addon-actions_v3.x.x.js │ ├── addon-links_v3.x.x.js │ ├── addons_vx.x.x.js │ └── react_v3.x.x.js │ ├── babel-core_vx.x.x.js │ ├── babel-eslint_vx.x.x.js │ ├── babel-runtime_vx.x.x.js │ ├── cross-spawn_vx.x.x.js │ ├── debug_v3.x.x.js │ ├── eslint-config-unobtrusive_vx.x.x.js │ ├── eslint-plugin-flowtype_vx.x.x.js │ ├── eslint-plugin-import_vx.x.x.js │ ├── eslint-plugin-react_vx.x.x.js │ ├── eslint_vx.x.x.js │ ├── express_v4.16.x.js │ ├── flow-bin_v0.x.x.js │ ├── flow-typed_vx.x.x.js │ ├── github-app_vx.x.x.js │ ├── github-webhook-handler_vx.x.x.js │ ├── memory-fs_vx.x.x.js │ ├── nodemon_vx.x.x.js │ ├── prettier_v1.x.x.js │ ├── promise-queue_vx.x.x.js │ ├── react-helmet_v5.x.x.js │ ├── rimraf_v2.x.x.js │ ├── shelljs_vx.x.x.js │ ├── signal-exit_vx.x.x.js │ ├── strip-ansi_vx.x.x.js │ ├── uid_vx.x.x.js │ └── yargs_vx.x.x.js ├── github-screenshot.png ├── logo ├── README.md ├── quinCI.ai ├── quinCI.png └── quinCI.svg ├── package.json ├── src ├── app-context.js ├── cli.js ├── comment-templates.js ├── create-github-app.js ├── create-github-app.shim.js ├── create-http-middleware.js ├── create-webhook-handler.js ├── events │ ├── commit-comment.js │ ├── pull-request-comment.js │ ├── pull-request.js │ └── push-to-named-branch.js ├── github-reporter.js ├── index.js ├── job.js ├── job.shim.js ├── normalize-config.js ├── queue.js ├── queue.shim.js ├── queues.js └── web-ui │ ├── components │ ├── AppBar.js │ ├── JobRunOutput.js │ ├── JobStatusItem.js │ ├── LabelWithIcon.js │ ├── Material.js │ ├── Padding.js │ ├── Page.js │ ├── StatusPage.js │ └── StatusPage.stories.js │ ├── index.js │ ├── render-react.js │ ├── route-helpers.js │ └── routes │ ├── cancel-job.js │ └── status-page.js ├── web-ui-screenshot.png └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react"], 3 | "plugins": [ 4 | "@babel/plugin-transform-flow-strip-types", 5 | "@babel/plugin-proposal-object-rest-spread", 6 | "@babel/plugin-proposal-class-properties", 7 | "@babel/plugin-proposal-nullish-coalescing-operator" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | flow-typed 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "unobtrusive", 4 | "unobtrusive/import", 5 | "unobtrusive/flowtype", 6 | "unobtrusive/react" 7 | ], 8 | "env": { 9 | "node": true, 10 | "es6": true 11 | }, 12 | "rules": { 13 | "react/no-unused-prop-types": "off" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /dist/.* 3 | 4 | [include] 5 | 6 | [libs] 7 | 8 | [lints] 9 | 10 | [options] 11 | 12 | [strict] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | secrets 4 | jobs 5 | yarn-error.log 6 | dist 7 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v8.17.0 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | secrets 2 | jobs 3 | yarn-error.log 4 | src 5 | .babelrc 6 | .eslintrc 7 | .eslintignore 8 | .flowconfig 9 | .gitignore 10 | .prettierignore 11 | .prettierrc 12 | flow-typed 13 | .storybook 14 | github-screenshot.png 15 | web-ui-screenshot.png 16 | .vscode 17 | logo 18 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | dist 3 | flow-typed 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "arrowParens": "always" 4 | } -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import "@storybook/addon-actions/register"; 2 | import "@storybook/addon-links/register"; 3 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from "@storybook/react"; 2 | 3 | // automatically import all files ending in *.stories.js 4 | const req = require.context("../src", true, /.stories.js$/); 5 | function loadStories() { 6 | req.keys().forEach((filename) => req(filename)); 7 | } 8 | 9 | configure(loadStories, module); 10 | -------------------------------------------------------------------------------- /.storybook/public/assets: -------------------------------------------------------------------------------- 1 | ../../assets -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | resolve: { 3 | extensions: [".shim.js", ".wasm", ".mjs", ".js", ".json"], 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "flowtype.flow-for-vscode", 4 | "esbenp.prettier-vscode", 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "javascript.validate.enable": false, 3 | "flow.pathToFlow": "${workspaceFolder}/node_modules/.bin/flow", 4 | "flow.useBundledFlow": false 5 | } 6 | -------------------------------------------------------------------------------- /.yarn-version: -------------------------------------------------------------------------------- 1 | 1.22.18 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2022 Suchipi 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

quinCI logo

2 | 3 | quinCI is a self-hosted, minimal GitHub CI server that runs scripts in response to GitHub webhook events. 4 | 5 | It is an alternative to complex, monolithic CI servers like Jenkins. Instead of providing a runner architecture, loggers, a plugin system, and pipelines... it just runs script files. If your CI needs are not very complex, quinCI may be easier to set up and debug than Jenkins. 6 | 7 | quinCI is a good fit for you if: 8 | 9 | - You want to run CI on your own server 10 | - You use GitHub 11 | - You want to run CI when a commit is added to the `master` branch 12 | - You want to run CI when a pull request is opened or updated 13 | 14 | | | | 15 | | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | 16 | | ![quinCI's web UI, showing the status of different jobs and their run output](https://cdn.rawgit.com/suchipi/quinci/master/web-ui-screenshot.png) | ![quinCI's GitHub bot posting comments on GitHub and setting the commit status](https://cdn.rawgit.com/suchipi/quinci/master/github-screenshot.png) | 17 | 18 | ## How it Works 19 | 20 | quinCI runs "tasks" when certain "events" occur. A task is an executable file that lives in your repo in the `quinci` folder. An event is something that can happen on GitHub, like a commit being added to master, or a Pull Request being opened. 21 | 22 | Whenever quinCI runs a task, the instance of that task running for a given commit or pull request is called a "job". 23 | 24 | You can view all the jobs quinCI is running or has run recently by opening the port quinCI is running on in your browser. You can also cancel jobs from this page. 25 | 26 | Here's a list of the events quinCI reacts to, and what task it will run for each event: 27 | 28 | | Event | Task | 29 | | ---------------------------------------------- | ---------------------------------------------- | 30 | | Commit pushed to or merged into a named branch | matches the branch name, eg `main` or `master` | 31 | 32 | When you push a commit to master/main, or merge a PR into master/main, quinCI will run the `master` or `main` task on your repo. To do so, it: 33 | 34 | - Clones your repo 35 | - Checks out the commit you just pushed 36 | - Marks the commit status on GitHub as "pending" 37 | - Runs `./quinci/master` or `./quinci/main` inside your repo (depending on the name of the branch that got new commits) 38 | 39 | - If `./quinci/master` or `./quinci/main` exits with a nonzero status code, quinCI will mark the commit status on GitHub as "failure" and leave a comment on the commit with information about the failure. 40 | - If `./quinci/master` or `./quinci/main` exits with a status code of zero, quinCI will mark the commit status on GitHub as "success". 41 | 42 | To run tasks for branches with different names, pass a comma-separated list of branch names on the command line using the `--named-branches` CLI flag. The default value of `--named-branches` is `master,main`. When you specify named branches using this CLI flag, it replaces the default value. So, if you want to include the default `master` and `main` tasks, you will need to include them, eg `--named-branches master,main,staging,production`. 43 | 44 | > Note: When adding a task for a named branch, you may wish to also use `--queue-concurrency` to specify how many jobs can run concurrently for that task. If unspecified, the concurrency defaults to 1, meaning only one job can be running for that task at a time, and other jobs will wait until a running job has completed. 45 | 46 | | Event | Task | 47 | | ------------------------------------- | -------------- | 48 | | PR opened, or new commits added to PR | `pull-request` | 49 | 50 | When you open a Pull Request or push new commits onto a PR, quinCI will run the `pull-request` task on your repo. To do so, it: 51 | 52 | - Clones your repo 53 | - Checks out the commit you just pushed or opened a PR for 54 | - Marks the commit status on GitHub as "pending" 55 | - Runs `./quinci/pull-request` inside your repo 56 | 57 | quinCI will post a comment when it starts running the task, and another comment when it has finished the task, which will include the results of the build. 58 | 59 | - If `./quinci/pull-request` exits with a nonzero status code, quinCI will mark the commit status on GitHub as "failure" and leave a comment on the PR indicating the task failed. 60 | - If `./quinci/pull-request` exits with a status code of zero, quinCI will mark the commit status on GitHub as "success" and leave a comment on the PR indicating the task succeeded. 61 | 62 | | Event | Task | 63 | | ---------------------------------------- | -------------- | 64 | | Comment with special phrase posted on PR | `pull-request` | 65 | 66 | In any PR, you can leave a comment with the phrase "quinCI run" or "quinCI test", and quinCI will re-run the `pull-request` task. 67 | 68 | The phrase only needs to match `/quin+c[eyi]+.* (?:re)?(?:run|test)/i`, so you can write "Mr. Quincy, please test the code again, if you wouldn't mind" and it will work, too. 69 | 70 | | Event | Task | 71 | | -------------------------------------------- | ------ | 72 | | Comment with special phrase posted on commit | varies | 73 | 74 | On any commit, you can leave a comment with the phrase "quinCI run master", "quinCI run main", or "quinCI run pull-request" to run the `master`, `main`, or `pull-request` tasks on that commit. 75 | 76 | The phrase only needs to match `/quin+c[eyi]+.* run ([\w.-]+)/i`, so you can write "Quinncey, could you please run master" and it will work, too. 77 | 78 | You can also use this to run custom tasks; for example, if you create the file `quinci/deploy` in your repo, you can comment "quinCI run deploy" on a commit, and quinCI will clone the repo, check out the commit, and run `./quinci/deploy`. 79 | 80 | > Note: When creating a custom task, you may wish to also use `--queue-concurrency` to specify how many jobs can run concurrently for that task. If unspecified, the concurrency defaults to Infinity, meaning as many jobs as are requested can be running for that task at a time. 81 | 82 | ## Installation and Setup 83 | 84 | ### Create tasks for quinCI to run 85 | 86 | quinCI expects to find two executable files in your repo: `quinci/master` (or `quinci/main`), and `quinci/pull-request`. Create these in your repo before installing quinCI, or else your builds will fail. 87 | 88 | `quinci/master` will be run for every commit added to master, `quinci/main` will be run for every commit added to main, and `quinci/pull-request` will be run for every pull request. 89 | 90 | If you override the `--named-branches` setting via the CLI in such a way that `master` and/or `main` are no longer present, you don't need to have executable files at `quinci/master` or `quinci/main`. 91 | 92 | The scripts can do whatever you want. Here's an example `quinci/master` script that runs tests and then deploys the code: 93 | 94 | ```sh 95 | #!/usr/bin/env bash 96 | set -e 97 | 98 | yarn test 99 | yarn deploy 100 | ``` 101 | 102 | And here's an example `qunci/pull-request` script that just runs the tests (without deploying): 103 | 104 | ```sh 105 | #!/usr/bin/env bash 106 | set -e 107 | 108 | yarn test 109 | ``` 110 | 111 | Make sure to make these files executable: 112 | 113 | ```sh 114 | chmod +x quinci/master 115 | chmod +x quinci/pull-request 116 | ``` 117 | 118 | ### Create GitHub App 119 | 120 | quinCI is used as a [GitHub App](https://developer.github.com/apps/). Because it's self-hosted, the webhook URL and authentication details will vary, so you need to create a custom GitHub App for your quinCI server. You can [create a new GitHub App here](https://github.com/settings/apps/new). 121 | 122 | - **Name** the app whatever you want 123 | - **Description** is optional 124 | - **Homepage URL** needs to be filled in but it doesn't matter what it is 125 | - **User authorization callback URL** needs to be filled in but it doesn't matter what it is 126 | - Leave **Setup URL** blank 127 | - For the **Webhook URL**, use a public URL that you will run quinCI on, eg `http://mydomain.com:7777/`. You can use [ngrok](https://ngrok.com/) to expose a URL to your local box for testing. Also, you can change this later without re-creating the GitHub App. 128 | - You have to have a **Webhook secret**. Generate something random. You'll need to include it when running quinCI on your server, so keep it somewhere. 129 | 130 | Your app needs these permissions: 131 | 132 | - **Repository contents**: Read only 133 | - **Issues**: Read & write 134 | - **Pull requests**: Read & write 135 | - **Commit statuses**: Read & write 136 | 137 | Everything else can be "No access". 138 | 139 | Subscribe to these events: 140 | 141 | - **Commit comment** 142 | - **Push** 143 | - **Issue comment** 144 | - **Pull request** 145 | 146 | You don't need to subscribe to anything else. 147 | 148 | ### Get GitHub App ID 149 | 150 | After creating your GitHub App, go to its page under "GitHub Apps" in [GitHub Developer settings](https://github.com/settings/apps) and copy its ID from the "About" section. You'll need this when running quinCI on your server. 151 | 152 | ### Generate Private Key 153 | 154 | From your GitHub App page, generate a private key and download it (It'll be a `.pem` file). You'll need to use it when running quinCI on your server, so keep it somewhere. 155 | 156 | ### Configure your repo to use the GitHub App 157 | 158 | Go to your App's page in [GitHub Developer settings](https://github.com/settings/apps) and click "Install app" to install your Github App onto your repo. 159 | 160 | ### Run quinCI on your server 161 | 162 | - You need [Node.js](https://nodejs.org/en/) 8.11.1 or higher to run quinCI. 163 | - Install the quinCI client on your server: `npm i -g quinci` 164 | - Copy the `.pem` private key you downloaded earlier somewhere on your server 165 | - Make a text file and put your webhook secret in it, and put this file somewhere on your server 166 | - Run `quinci` with the following command line switches: 167 | 168 | ``` 169 | Options: 170 | --help Show help [boolean] 171 | --version Show version number [boolean] 172 | --port Port to run the HTTP server on [required] [default: 7777] 173 | --app-id GitHub App ID [required] 174 | --app-cert Path to the GitHub App's private key pem file [required] 175 | --webhook-secret-file Path to a text file containing your Webhook secret [required] 176 | --queue-concurrency How many instances of a job are allowed to run at once. 177 | Use 'Infinity' for no limit. [default: "master=1,main=1,pull-request=3"] 178 | --web-url URL at which the web UI can be accessed [required] 179 | --named-branches Comma-separated list of branch names that have 180 | corresponding jobs in the 'quinci' folder in the repo 181 | root, that should be run when commits are pushed to 182 | that branch. [default: "master,main"] 183 | ``` 184 | 185 | So for example: 186 | 187 | ```sh 188 | quinci --port 8080 --app-id 12345 --app-cert secrets/quinci.private-key.pem --webhook-secret-file secrets/webhook-secret.txt --web-url http://example.com:8080 189 | ``` 190 | 191 | This will run quinCI in the current directory. 192 | 193 | ## Troubleshooting 194 | 195 | - quinCI will not run in response to actions from users who do not have write access to the repository, as a security measure. If a user without write access opens a PR and you want to run its tests, comment "quinCI test this" on the PR. 196 | - quinCI uses the [debug](https://www.npmjs.com/package/debug) module to log debugging information. To view debug logs while running, set the environment variable `DEBUG` to `quinci:*`. 197 | 198 | ## License 199 | 200 | MIT 201 | -------------------------------------------------------------------------------- /assets/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: rgb(217, 227, 255); 3 | font-family: "Roboto", sans-serif; 4 | } 5 | 6 | * { 7 | box-sizing: border-box; 8 | margin: 0; 9 | padding: 0; 10 | } 11 | 12 | a { 13 | text-decoration: none; 14 | } 15 | 16 | a:hover { 17 | text-decoration: underline; 18 | } 19 | 20 | summary::-webkit-details-marker { 21 | display: none; 22 | } 23 | 24 | summary:first-of-type { 25 | list-style-type: none; 26 | } 27 | 28 | details .details-icon { 29 | transition: transform 100ms ease-in-out; 30 | } 31 | 32 | details[open] .details-icon { 33 | transform: rotate(90deg); 34 | } 35 | 36 | details pre { 37 | transform: scaleY(0); 38 | transform-origin: top; 39 | transition: transform 100ms ease-in-out; 40 | } 41 | 42 | details[open] pre { 43 | transform: scaleY(1); 44 | } 45 | 46 | svg { 47 | overflow: visible; 48 | } 49 | -------------------------------------------------------------------------------- /dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suchipi/quinci/c7b3ff707d77bad5246a4c8712026362d2ad9af6/dist/.gitkeep -------------------------------------------------------------------------------- /flow-typed/npm/@babel/cli_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 5fb4df044cdd5cbc1fe1bd951e367f15 2 | // flow-typed version: <>/@babel/cli_v^7.0.0-beta.46/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@babel/cli' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@babel/cli' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module '@babel/cli/bin/babel-external-helpers' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module '@babel/cli/bin/babel' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module '@babel/cli/lib/babel-external-helpers' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module '@babel/cli/lib/babel/dir' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module '@babel/cli/lib/babel/file' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module '@babel/cli/lib/babel/index' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module '@babel/cli/lib/babel/util' { 50 | declare module.exports: any; 51 | } 52 | 53 | // Filename aliases 54 | declare module '@babel/cli/bin/babel-external-helpers.js' { 55 | declare module.exports: $Exports<'@babel/cli/bin/babel-external-helpers'>; 56 | } 57 | declare module '@babel/cli/bin/babel.js' { 58 | declare module.exports: $Exports<'@babel/cli/bin/babel'>; 59 | } 60 | declare module '@babel/cli/index' { 61 | declare module.exports: $Exports<'@babel/cli'>; 62 | } 63 | declare module '@babel/cli/index.js' { 64 | declare module.exports: $Exports<'@babel/cli'>; 65 | } 66 | declare module '@babel/cli/lib/babel-external-helpers.js' { 67 | declare module.exports: $Exports<'@babel/cli/lib/babel-external-helpers'>; 68 | } 69 | declare module '@babel/cli/lib/babel/dir.js' { 70 | declare module.exports: $Exports<'@babel/cli/lib/babel/dir'>; 71 | } 72 | declare module '@babel/cli/lib/babel/file.js' { 73 | declare module.exports: $Exports<'@babel/cli/lib/babel/file'>; 74 | } 75 | declare module '@babel/cli/lib/babel/index.js' { 76 | declare module.exports: $Exports<'@babel/cli/lib/babel/index'>; 77 | } 78 | declare module '@babel/cli/lib/babel/util.js' { 79 | declare module.exports: $Exports<'@babel/cli/lib/babel/util'>; 80 | } 81 | -------------------------------------------------------------------------------- /flow-typed/npm/@babel/core_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b117fb4490cb2d93a1838eff38d722cd 2 | // flow-typed version: <>/@babel/core_v^7.0.0-beta.46/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@babel/core' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@babel/core' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module '@babel/core/lib/config/caching' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module '@babel/core/lib/config/config-chain' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module '@babel/core/lib/config/config-descriptors' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module '@babel/core/lib/config/files/configuration' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module '@babel/core/lib/config/files/index-browser' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module '@babel/core/lib/config/files/index' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module '@babel/core/lib/config/files/package' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module '@babel/core/lib/config/files/plugins' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module '@babel/core/lib/config/files/types' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module '@babel/core/lib/config/files/utils' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module '@babel/core/lib/config/full' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module '@babel/core/lib/config/helpers/config-api' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module '@babel/core/lib/config/helpers/environment' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module '@babel/core/lib/config/index' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module '@babel/core/lib/config/item' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module '@babel/core/lib/config/partial' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module '@babel/core/lib/config/plugin' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module '@babel/core/lib/config/util' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module '@babel/core/lib/config/validation/option-assertions' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module '@babel/core/lib/config/validation/options' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module '@babel/core/lib/config/validation/plugins' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module '@babel/core/lib/config/validation/removed' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module '@babel/core/lib/index' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module '@babel/core/lib/parse' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module '@babel/core/lib/tools/build-external-helpers' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module '@babel/core/lib/transform-ast-sync' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module '@babel/core/lib/transform-ast' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module '@babel/core/lib/transform-file-browser' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module '@babel/core/lib/transform-file-sync-browser' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module '@babel/core/lib/transform-file-sync' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module '@babel/core/lib/transform-file' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module '@babel/core/lib/transform-sync' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module '@babel/core/lib/transform' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module '@babel/core/lib/transformation/block-hoist-plugin' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module '@babel/core/lib/transformation/file/file' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module '@babel/core/lib/transformation/file/generate' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module '@babel/core/lib/transformation/index' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module '@babel/core/lib/transformation/normalize-file' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module '@babel/core/lib/transformation/normalize-opts' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module '@babel/core/lib/transformation/plugin-pass' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module '@babel/core/lib/transformation/util/missing-plugin-helper' { 186 | declare module.exports: any; 187 | } 188 | 189 | // Filename aliases 190 | declare module '@babel/core/lib/config/caching.js' { 191 | declare module.exports: $Exports<'@babel/core/lib/config/caching'>; 192 | } 193 | declare module '@babel/core/lib/config/config-chain.js' { 194 | declare module.exports: $Exports<'@babel/core/lib/config/config-chain'>; 195 | } 196 | declare module '@babel/core/lib/config/config-descriptors.js' { 197 | declare module.exports: $Exports<'@babel/core/lib/config/config-descriptors'>; 198 | } 199 | declare module '@babel/core/lib/config/files/configuration.js' { 200 | declare module.exports: $Exports<'@babel/core/lib/config/files/configuration'>; 201 | } 202 | declare module '@babel/core/lib/config/files/index-browser.js' { 203 | declare module.exports: $Exports<'@babel/core/lib/config/files/index-browser'>; 204 | } 205 | declare module '@babel/core/lib/config/files/index.js' { 206 | declare module.exports: $Exports<'@babel/core/lib/config/files/index'>; 207 | } 208 | declare module '@babel/core/lib/config/files/package.js' { 209 | declare module.exports: $Exports<'@babel/core/lib/config/files/package'>; 210 | } 211 | declare module '@babel/core/lib/config/files/plugins.js' { 212 | declare module.exports: $Exports<'@babel/core/lib/config/files/plugins'>; 213 | } 214 | declare module '@babel/core/lib/config/files/types.js' { 215 | declare module.exports: $Exports<'@babel/core/lib/config/files/types'>; 216 | } 217 | declare module '@babel/core/lib/config/files/utils.js' { 218 | declare module.exports: $Exports<'@babel/core/lib/config/files/utils'>; 219 | } 220 | declare module '@babel/core/lib/config/full.js' { 221 | declare module.exports: $Exports<'@babel/core/lib/config/full'>; 222 | } 223 | declare module '@babel/core/lib/config/helpers/config-api.js' { 224 | declare module.exports: $Exports<'@babel/core/lib/config/helpers/config-api'>; 225 | } 226 | declare module '@babel/core/lib/config/helpers/environment.js' { 227 | declare module.exports: $Exports<'@babel/core/lib/config/helpers/environment'>; 228 | } 229 | declare module '@babel/core/lib/config/index.js' { 230 | declare module.exports: $Exports<'@babel/core/lib/config/index'>; 231 | } 232 | declare module '@babel/core/lib/config/item.js' { 233 | declare module.exports: $Exports<'@babel/core/lib/config/item'>; 234 | } 235 | declare module '@babel/core/lib/config/partial.js' { 236 | declare module.exports: $Exports<'@babel/core/lib/config/partial'>; 237 | } 238 | declare module '@babel/core/lib/config/plugin.js' { 239 | declare module.exports: $Exports<'@babel/core/lib/config/plugin'>; 240 | } 241 | declare module '@babel/core/lib/config/util.js' { 242 | declare module.exports: $Exports<'@babel/core/lib/config/util'>; 243 | } 244 | declare module '@babel/core/lib/config/validation/option-assertions.js' { 245 | declare module.exports: $Exports<'@babel/core/lib/config/validation/option-assertions'>; 246 | } 247 | declare module '@babel/core/lib/config/validation/options.js' { 248 | declare module.exports: $Exports<'@babel/core/lib/config/validation/options'>; 249 | } 250 | declare module '@babel/core/lib/config/validation/plugins.js' { 251 | declare module.exports: $Exports<'@babel/core/lib/config/validation/plugins'>; 252 | } 253 | declare module '@babel/core/lib/config/validation/removed.js' { 254 | declare module.exports: $Exports<'@babel/core/lib/config/validation/removed'>; 255 | } 256 | declare module '@babel/core/lib/index.js' { 257 | declare module.exports: $Exports<'@babel/core/lib/index'>; 258 | } 259 | declare module '@babel/core/lib/parse.js' { 260 | declare module.exports: $Exports<'@babel/core/lib/parse'>; 261 | } 262 | declare module '@babel/core/lib/tools/build-external-helpers.js' { 263 | declare module.exports: $Exports<'@babel/core/lib/tools/build-external-helpers'>; 264 | } 265 | declare module '@babel/core/lib/transform-ast-sync.js' { 266 | declare module.exports: $Exports<'@babel/core/lib/transform-ast-sync'>; 267 | } 268 | declare module '@babel/core/lib/transform-ast.js' { 269 | declare module.exports: $Exports<'@babel/core/lib/transform-ast'>; 270 | } 271 | declare module '@babel/core/lib/transform-file-browser.js' { 272 | declare module.exports: $Exports<'@babel/core/lib/transform-file-browser'>; 273 | } 274 | declare module '@babel/core/lib/transform-file-sync-browser.js' { 275 | declare module.exports: $Exports<'@babel/core/lib/transform-file-sync-browser'>; 276 | } 277 | declare module '@babel/core/lib/transform-file-sync.js' { 278 | declare module.exports: $Exports<'@babel/core/lib/transform-file-sync'>; 279 | } 280 | declare module '@babel/core/lib/transform-file.js' { 281 | declare module.exports: $Exports<'@babel/core/lib/transform-file'>; 282 | } 283 | declare module '@babel/core/lib/transform-sync.js' { 284 | declare module.exports: $Exports<'@babel/core/lib/transform-sync'>; 285 | } 286 | declare module '@babel/core/lib/transform.js' { 287 | declare module.exports: $Exports<'@babel/core/lib/transform'>; 288 | } 289 | declare module '@babel/core/lib/transformation/block-hoist-plugin.js' { 290 | declare module.exports: $Exports<'@babel/core/lib/transformation/block-hoist-plugin'>; 291 | } 292 | declare module '@babel/core/lib/transformation/file/file.js' { 293 | declare module.exports: $Exports<'@babel/core/lib/transformation/file/file'>; 294 | } 295 | declare module '@babel/core/lib/transformation/file/generate.js' { 296 | declare module.exports: $Exports<'@babel/core/lib/transformation/file/generate'>; 297 | } 298 | declare module '@babel/core/lib/transformation/index.js' { 299 | declare module.exports: $Exports<'@babel/core/lib/transformation/index'>; 300 | } 301 | declare module '@babel/core/lib/transformation/normalize-file.js' { 302 | declare module.exports: $Exports<'@babel/core/lib/transformation/normalize-file'>; 303 | } 304 | declare module '@babel/core/lib/transformation/normalize-opts.js' { 305 | declare module.exports: $Exports<'@babel/core/lib/transformation/normalize-opts'>; 306 | } 307 | declare module '@babel/core/lib/transformation/plugin-pass.js' { 308 | declare module.exports: $Exports<'@babel/core/lib/transformation/plugin-pass'>; 309 | } 310 | declare module '@babel/core/lib/transformation/util/missing-plugin-helper.js' { 311 | declare module.exports: $Exports<'@babel/core/lib/transformation/util/missing-plugin-helper'>; 312 | } 313 | -------------------------------------------------------------------------------- /flow-typed/npm/@babel/plugin-transform-flow-strip-types_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 57e05cde26a197072a71102591663e0a 2 | // flow-typed version: <>/@babel/plugin-transform-flow-strip-types_v^7.0.0-beta.46/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@babel/plugin-transform-flow-strip-types' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@babel/plugin-transform-flow-strip-types' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module '@babel/plugin-transform-flow-strip-types/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module '@babel/plugin-transform-flow-strip-types/lib/index.js' { 31 | declare module.exports: $Exports<'@babel/plugin-transform-flow-strip-types/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/@babel/preset-react_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 69738bb104c2ac9c16f363c0ed88c94a 2 | // flow-typed version: <>/@babel/preset-react_v^7.0.0-beta.54/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@babel/preset-react' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@babel/preset-react' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module '@babel/preset-react/lib/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module '@babel/preset-react/lib/index.js' { 31 | declare module.exports: $Exports<'@babel/preset-react/lib/index'>; 32 | } 33 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-actions_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 2f5b0f18c5b5b31b01f63163429685c7 2 | // flow-typed version: 5edd39ab2e/@storybook/addon-actions_v3.x.x/flow_>=v0.25.x 3 | 4 | declare module '@storybook/addon-actions' { 5 | declare type Action = (name: string) => (...args: Array) => void; 6 | declare type DecorateFn = (args: Array) => Array; 7 | 8 | declare module.exports: { 9 | action: Action, 10 | decorateAction(args: Array): Action; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addon-links_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: d869098d1e7c7ccd5477ac7f10a9148d 2 | // flow-typed version: 8e2ca848b1/@storybook/addon-links_v3.x.x/flow_>=v0.53.x 3 | 4 | declare module '@storybook/addon-links' { 5 | declare type LinkToFunction = (...args: Array) => string; 6 | 7 | declare module.exports: { 8 | linkTo( 9 | book: string | LinkToFunction, 10 | kind?: string | LinkToFunction 11 | ): SyntheticMouseEvent, 12 | hrefTo(kind: string, story: string): Promise, 13 | }; 14 | } 15 | 16 | declare module '@storybook/addon-links/react' { 17 | declare type Props = { 18 | kind?: string, 19 | story?: string, 20 | }; 21 | 22 | declare class LinkTo extends React$Component {} 23 | declare module.exports: typeof LinkTo; 24 | } 25 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/addons_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: a74b268546732b2c9c2eb32fd5b6108f 2 | // flow-typed version: <>/@storybook/addons_v^3.4.8/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * '@storybook/addons' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module '@storybook/addons' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module '@storybook/addons/dist/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module '@storybook/addons/src/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | // Filename aliases 34 | declare module '@storybook/addons/dist/index.js' { 35 | declare module.exports: $Exports<'@storybook/addons/dist/index'>; 36 | } 37 | declare module '@storybook/addons/src/index.js' { 38 | declare module.exports: $Exports<'@storybook/addons/src/index'>; 39 | } 40 | -------------------------------------------------------------------------------- /flow-typed/npm/@storybook/react_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: c2e1b132d2729c977d6b3e54e0134de5 2 | // flow-typed version: 1709d3212d/@storybook/react_v3.x.x/flow_>=v0.28.x 3 | 4 | type NodeModule = typeof module; 5 | 6 | declare module '@storybook/react' { 7 | declare type Renderable = React$Element; 8 | declare type RenderFunction = () => Renderable; 9 | 10 | declare type StoryDecorator = ( 11 | story: RenderFunction, 12 | context: { kind: string, story: string } 13 | ) => Renderable | null; 14 | 15 | declare interface Story { 16 | add(storyName: string, callback: RenderFunction): Story, 17 | addDecorator(decorator: StoryDecorator): Story, 18 | } 19 | 20 | declare interface StoryObject { 21 | name: string, 22 | render: RenderFunction, 23 | } 24 | 25 | declare interface StoryBucket { 26 | kind: string, 27 | stories: Array, 28 | } 29 | 30 | declare function addDecorator(decorator: StoryDecorator): void; 31 | declare function configure(fn: () => void, module: NodeModule): void; 32 | declare function setAddon(addon: Object): void; 33 | declare function storiesOf(name: string, module: NodeModule): Story; 34 | declare function storiesOf(name: string, module: NodeModule): Story & T; 35 | 36 | declare function getStorybook(): Array; 37 | } 38 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-core_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 81ccc0e8142005a2e4b8aa008c9e03f6 2 | // flow-typed version: <>/babel-core_v^7.0.0-0/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-core' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-core' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'babel-core/index' { 29 | declare module.exports: $Exports<'babel-core'>; 30 | } 31 | declare module 'babel-core/index.js' { 32 | declare module.exports: $Exports<'babel-core'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/babel-eslint_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 456d87a08ec4ee9c58866eed9ef617cd 2 | // flow-typed version: <>/babel-eslint_v^8.2.3/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'babel-eslint' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'babel-eslint' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'babel-eslint/lib/analyze-scope' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'babel-eslint/lib/babylon-to-espree/attachComments' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'babel-eslint/lib/babylon-to-espree/convertComments' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'babel-eslint/lib/babylon-to-espree/convertTemplateType' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'babel-eslint/lib/babylon-to-espree/index' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'babel-eslint/lib/babylon-to-espree/toAST' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'babel-eslint/lib/babylon-to-espree/toToken' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'babel-eslint/lib/babylon-to-espree/toTokens' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'babel-eslint/lib/index' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'babel-eslint/lib/parse-with-patch' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'babel-eslint/lib/parse-with-scope' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'babel-eslint/lib/parse' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'babel-eslint/lib/patch-eslint-scope' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'babel-eslint/lib/visitor-keys' { 78 | declare module.exports: any; 79 | } 80 | 81 | // Filename aliases 82 | declare module 'babel-eslint/lib/analyze-scope.js' { 83 | declare module.exports: $Exports<'babel-eslint/lib/analyze-scope'>; 84 | } 85 | declare module 'babel-eslint/lib/babylon-to-espree/attachComments.js' { 86 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/attachComments'>; 87 | } 88 | declare module 'babel-eslint/lib/babylon-to-espree/convertComments.js' { 89 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/convertComments'>; 90 | } 91 | declare module 'babel-eslint/lib/babylon-to-espree/convertTemplateType.js' { 92 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/convertTemplateType'>; 93 | } 94 | declare module 'babel-eslint/lib/babylon-to-espree/index.js' { 95 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/index'>; 96 | } 97 | declare module 'babel-eslint/lib/babylon-to-espree/toAST.js' { 98 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/toAST'>; 99 | } 100 | declare module 'babel-eslint/lib/babylon-to-espree/toToken.js' { 101 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/toToken'>; 102 | } 103 | declare module 'babel-eslint/lib/babylon-to-espree/toTokens.js' { 104 | declare module.exports: $Exports<'babel-eslint/lib/babylon-to-espree/toTokens'>; 105 | } 106 | declare module 'babel-eslint/lib/index.js' { 107 | declare module.exports: $Exports<'babel-eslint/lib/index'>; 108 | } 109 | declare module 'babel-eslint/lib/parse-with-patch.js' { 110 | declare module.exports: $Exports<'babel-eslint/lib/parse-with-patch'>; 111 | } 112 | declare module 'babel-eslint/lib/parse-with-scope.js' { 113 | declare module.exports: $Exports<'babel-eslint/lib/parse-with-scope'>; 114 | } 115 | declare module 'babel-eslint/lib/parse.js' { 116 | declare module.exports: $Exports<'babel-eslint/lib/parse'>; 117 | } 118 | declare module 'babel-eslint/lib/patch-eslint-scope.js' { 119 | declare module.exports: $Exports<'babel-eslint/lib/patch-eslint-scope'>; 120 | } 121 | declare module 'babel-eslint/lib/visitor-keys.js' { 122 | declare module.exports: $Exports<'babel-eslint/lib/visitor-keys'>; 123 | } 124 | -------------------------------------------------------------------------------- /flow-typed/npm/cross-spawn_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 0ec832124717887cc8e36ad799ad0a8b 2 | // flow-typed version: <>/cross-spawn_v^6.0.5/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'cross-spawn' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'cross-spawn' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'cross-spawn/lib/enoent' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'cross-spawn/lib/parse' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'cross-spawn/lib/util/escape' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'cross-spawn/lib/util/readShebang' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'cross-spawn/lib/util/resolveCommand' { 42 | declare module.exports: any; 43 | } 44 | 45 | // Filename aliases 46 | declare module 'cross-spawn/index' { 47 | declare module.exports: $Exports<'cross-spawn'>; 48 | } 49 | declare module 'cross-spawn/index.js' { 50 | declare module.exports: $Exports<'cross-spawn'>; 51 | } 52 | declare module 'cross-spawn/lib/enoent.js' { 53 | declare module.exports: $Exports<'cross-spawn/lib/enoent'>; 54 | } 55 | declare module 'cross-spawn/lib/parse.js' { 56 | declare module.exports: $Exports<'cross-spawn/lib/parse'>; 57 | } 58 | declare module 'cross-spawn/lib/util/escape.js' { 59 | declare module.exports: $Exports<'cross-spawn/lib/util/escape'>; 60 | } 61 | declare module 'cross-spawn/lib/util/readShebang.js' { 62 | declare module.exports: $Exports<'cross-spawn/lib/util/readShebang'>; 63 | } 64 | declare module 'cross-spawn/lib/util/resolveCommand.js' { 65 | declare module.exports: $Exports<'cross-spawn/lib/util/resolveCommand'>; 66 | } 67 | -------------------------------------------------------------------------------- /flow-typed/npm/debug_v3.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: da5374f88debab76c20fc67be7295ba7 2 | // flow-typed version: da30fe6876/debug_v3.x.x/flow_>=v0.28.x 3 | 4 | declare module "debug" { 5 | declare type Debugger = { 6 | (...args: Array): void, 7 | (formatter: string, ...args: Array): void, 8 | (err: Error, ...args: Array): void, 9 | enabled: boolean, 10 | log: () => {}, 11 | namespace: string 12 | }; 13 | 14 | declare module.exports: (namespace: string) => Debugger; 15 | 16 | declare var names: Array; 17 | declare var skips: Array; 18 | declare var colors: Array; 19 | 20 | declare function disable(): void; 21 | declare function enable(namespaces: string): void; 22 | declare function enabled(name: string): boolean; 23 | declare function humanize(): void; 24 | declare function useColors(): boolean; 25 | declare function log(): void; 26 | 27 | declare var formatters: { 28 | [formatter: string]: () => {} 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-config-unobtrusive_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9e3fdf10abf1e11fa9c76b5290f69c99 2 | // flow-typed version: <>/eslint-config-unobtrusive_v^1.2.2/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-config-unobtrusive' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-config-unobtrusive' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-config-unobtrusive/flowtype' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-config-unobtrusive/import' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-config-unobtrusive/react' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'eslint-config-unobtrusive/flowtype.js' { 39 | declare module.exports: $Exports<'eslint-config-unobtrusive/flowtype'>; 40 | } 41 | declare module 'eslint-config-unobtrusive/import.js' { 42 | declare module.exports: $Exports<'eslint-config-unobtrusive/import'>; 43 | } 44 | declare module 'eslint-config-unobtrusive/index' { 45 | declare module.exports: $Exports<'eslint-config-unobtrusive'>; 46 | } 47 | declare module 'eslint-config-unobtrusive/index.js' { 48 | declare module.exports: $Exports<'eslint-config-unobtrusive'>; 49 | } 50 | declare module 'eslint-config-unobtrusive/react.js' { 51 | declare module.exports: $Exports<'eslint-config-unobtrusive/react'>; 52 | } 53 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: bc4c68fa1ed881643fa2c5f502260924 2 | // flow-typed version: <>/eslint-plugin-flowtype_v^2.46.3/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-flowtype' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-plugin-flowtype' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-flowtype/dist/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-flowtype/dist/rules/newlineAfterFlowAnnotation' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'eslint-plugin-flowtype/dist/rules/noExistentialType' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'eslint-plugin-flowtype/dist/rules/noFlowFixMeComments' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'eslint-plugin-flowtype/dist/rules/requireExactType' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'eslint-plugin-flowtype/dist/rules/requireTypesAtTop' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'eslint-plugin-flowtype/dist/rules/semi' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'eslint-plugin-flowtype/dist/rules/typeImportStyle' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens' { 202 | declare module.exports: any; 203 | } 204 | 205 | declare module 'eslint-plugin-flowtype/dist/utilities/index' { 206 | declare module.exports: any; 207 | } 208 | 209 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile' { 210 | declare module.exports: any; 211 | } 212 | 213 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation' { 214 | declare module.exports: any; 215 | } 216 | 217 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes' { 218 | declare module.exports: any; 219 | } 220 | 221 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName' { 222 | declare module.exports: any; 223 | } 224 | 225 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers' { 226 | declare module.exports: any; 227 | } 228 | 229 | // Filename aliases 230 | declare module 'eslint-plugin-flowtype/bin/readmeAssertions.js' { 231 | declare module.exports: $Exports<'eslint-plugin-flowtype/bin/readmeAssertions'>; 232 | } 233 | declare module 'eslint-plugin-flowtype/dist/index.js' { 234 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/index'>; 235 | } 236 | declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle.js' { 237 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/booleanStyle'>; 238 | } 239 | declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType.js' { 240 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/defineFlowType'>; 241 | } 242 | declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle.js' { 243 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/delimiterDangle'>; 244 | } 245 | declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing.js' { 246 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/genericSpacing'>; 247 | } 248 | declare module 'eslint-plugin-flowtype/dist/rules/newlineAfterFlowAnnotation.js' { 249 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/newlineAfterFlowAnnotation'>; 250 | } 251 | declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys.js' { 252 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noDupeKeys'>; 253 | } 254 | declare module 'eslint-plugin-flowtype/dist/rules/noExistentialType.js' { 255 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noExistentialType'>; 256 | } 257 | declare module 'eslint-plugin-flowtype/dist/rules/noFlowFixMeComments.js' { 258 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noFlowFixMeComments'>; 259 | } 260 | declare module 'eslint-plugin-flowtype/dist/rules/noMutableArray.js' { 261 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noMutableArray'>; 262 | } 263 | declare module 'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes.js' { 264 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noPrimitiveConstructorTypes'>; 265 | } 266 | declare module 'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation.js' { 267 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noTypesMissingFileAnnotation'>; 268 | } 269 | declare module 'eslint-plugin-flowtype/dist/rules/noUnusedExpressions.js' { 270 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noUnusedExpressions'>; 271 | } 272 | declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes.js' { 273 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noWeakTypes'>; 274 | } 275 | declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter.js' { 276 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter'>; 277 | } 278 | declare module 'eslint-plugin-flowtype/dist/rules/requireExactType.js' { 279 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireExactType'>; 280 | } 281 | declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType.js' { 282 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireParameterType'>; 283 | } 284 | declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType.js' { 285 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReturnType'>; 286 | } 287 | declare module 'eslint-plugin-flowtype/dist/rules/requireTypesAtTop.js' { 288 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireTypesAtTop'>; 289 | } 290 | declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation.js' { 291 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation'>; 292 | } 293 | declare module 'eslint-plugin-flowtype/dist/rules/requireVariableType.js' { 294 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireVariableType'>; 295 | } 296 | declare module 'eslint-plugin-flowtype/dist/rules/semi.js' { 297 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/semi'>; 298 | } 299 | declare module 'eslint-plugin-flowtype/dist/rules/sortKeys.js' { 300 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/sortKeys'>; 301 | } 302 | declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon.js' { 303 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon'>; 304 | } 305 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket.js' { 306 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket'>; 307 | } 308 | declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon.js' { 309 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon'>; 310 | } 311 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions.js' { 312 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions'>; 313 | } 314 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer.js' { 315 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer'>; 316 | } 317 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty.js' { 318 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty'>; 319 | } 320 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType.js' { 321 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType'>; 322 | } 323 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression.js' { 324 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression'>; 325 | } 326 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical.js' { 327 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical'>; 328 | } 329 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index.js' { 330 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index'>; 331 | } 332 | declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter.js' { 333 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter'>; 334 | } 335 | declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch.js' { 336 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeIdMatch'>; 337 | } 338 | declare module 'eslint-plugin-flowtype/dist/rules/typeImportStyle.js' { 339 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeImportStyle'>; 340 | } 341 | declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing.js' { 342 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing'>; 343 | } 344 | declare module 'eslint-plugin-flowtype/dist/rules/useFlowType.js' { 345 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/useFlowType'>; 346 | } 347 | declare module 'eslint-plugin-flowtype/dist/rules/validSyntax.js' { 348 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/validSyntax'>; 349 | } 350 | declare module 'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation.js' { 351 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/checkFlowFileAnnotation'>; 352 | } 353 | declare module 'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch.js' { 354 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/fuzzyStringMatch'>; 355 | } 356 | declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName.js' { 357 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getParameterName'>; 358 | } 359 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens.js' { 360 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens'>; 361 | } 362 | declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens.js' { 363 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens'>; 364 | } 365 | declare module 'eslint-plugin-flowtype/dist/utilities/index.js' { 366 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/index'>; 367 | } 368 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile.js' { 369 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFile'>; 370 | } 371 | declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation.js' { 372 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation'>; 373 | } 374 | declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes.js' { 375 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes'>; 376 | } 377 | declare module 'eslint-plugin-flowtype/dist/utilities/quoteName.js' { 378 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/quoteName'>; 379 | } 380 | declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers.js' { 381 | declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/spacingFixers'>; 382 | } 383 | -------------------------------------------------------------------------------- /flow-typed/npm/eslint-plugin-import_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 49929c2e6208e8fa48ffddbb6eeb9854 2 | // flow-typed version: <>/eslint-plugin-import_v^2.11.0/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'eslint-plugin-import' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'eslint-plugin-import' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'eslint-plugin-import/config/electron' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'eslint-plugin-import/config/errors' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'eslint-plugin-import/config/react-native' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'eslint-plugin-import/config/react' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'eslint-plugin-import/config/recommended' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'eslint-plugin-import/config/stage-0' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'eslint-plugin-import/config/warnings' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'eslint-plugin-import/lib/core/importType' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'eslint-plugin-import/lib/core/staticRequire' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'eslint-plugin-import/lib/docsUrl' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'eslint-plugin-import/lib/ExportMap' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'eslint-plugin-import/lib/importDeclaration' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'eslint-plugin-import/lib/index' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'eslint-plugin-import/lib/rules/default' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'eslint-plugin-import/lib/rules/export' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'eslint-plugin-import/lib/rules/exports-last' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'eslint-plugin-import/lib/rules/extensions' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'eslint-plugin-import/lib/rules/first' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'eslint-plugin-import/lib/rules/group-exports' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'eslint-plugin-import/lib/rules/imports-first' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'eslint-plugin-import/lib/rules/max-dependencies' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'eslint-plugin-import/lib/rules/named' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'eslint-plugin-import/lib/rules/namespace' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'eslint-plugin-import/lib/rules/newline-after-import' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'eslint-plugin-import/lib/rules/no-absolute-path' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'eslint-plugin-import/lib/rules/no-amd' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'eslint-plugin-import/lib/rules/no-anonymous-default-export' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'eslint-plugin-import/lib/rules/no-commonjs' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'eslint-plugin-import/lib/rules/no-cycle' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'eslint-plugin-import/lib/rules/no-default-export' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'eslint-plugin-import/lib/rules/no-deprecated' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'eslint-plugin-import/lib/rules/no-duplicates' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'eslint-plugin-import/lib/rules/no-dynamic-require' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'eslint-plugin-import/lib/rules/no-extraneous-dependencies' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'eslint-plugin-import/lib/rules/no-internal-modules' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'eslint-plugin-import/lib/rules/no-mutable-exports' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'eslint-plugin-import/lib/rules/no-named-as-default-member' { 170 | declare module.exports: any; 171 | } 172 | 173 | declare module 'eslint-plugin-import/lib/rules/no-named-as-default' { 174 | declare module.exports: any; 175 | } 176 | 177 | declare module 'eslint-plugin-import/lib/rules/no-named-default' { 178 | declare module.exports: any; 179 | } 180 | 181 | declare module 'eslint-plugin-import/lib/rules/no-namespace' { 182 | declare module.exports: any; 183 | } 184 | 185 | declare module 'eslint-plugin-import/lib/rules/no-nodejs-modules' { 186 | declare module.exports: any; 187 | } 188 | 189 | declare module 'eslint-plugin-import/lib/rules/no-restricted-paths' { 190 | declare module.exports: any; 191 | } 192 | 193 | declare module 'eslint-plugin-import/lib/rules/no-self-import' { 194 | declare module.exports: any; 195 | } 196 | 197 | declare module 'eslint-plugin-import/lib/rules/no-unassigned-import' { 198 | declare module.exports: any; 199 | } 200 | 201 | declare module 'eslint-plugin-import/lib/rules/no-unresolved' { 202 | declare module.exports: any; 203 | } 204 | 205 | declare module 'eslint-plugin-import/lib/rules/no-useless-path-segments' { 206 | declare module.exports: any; 207 | } 208 | 209 | declare module 'eslint-plugin-import/lib/rules/no-webpack-loader-syntax' { 210 | declare module.exports: any; 211 | } 212 | 213 | declare module 'eslint-plugin-import/lib/rules/order' { 214 | declare module.exports: any; 215 | } 216 | 217 | declare module 'eslint-plugin-import/lib/rules/prefer-default-export' { 218 | declare module.exports: any; 219 | } 220 | 221 | declare module 'eslint-plugin-import/lib/rules/unambiguous' { 222 | declare module.exports: any; 223 | } 224 | 225 | declare module 'eslint-plugin-import/memo-parser/index' { 226 | declare module.exports: any; 227 | } 228 | 229 | // Filename aliases 230 | declare module 'eslint-plugin-import/config/electron.js' { 231 | declare module.exports: $Exports<'eslint-plugin-import/config/electron'>; 232 | } 233 | declare module 'eslint-plugin-import/config/errors.js' { 234 | declare module.exports: $Exports<'eslint-plugin-import/config/errors'>; 235 | } 236 | declare module 'eslint-plugin-import/config/react-native.js' { 237 | declare module.exports: $Exports<'eslint-plugin-import/config/react-native'>; 238 | } 239 | declare module 'eslint-plugin-import/config/react.js' { 240 | declare module.exports: $Exports<'eslint-plugin-import/config/react'>; 241 | } 242 | declare module 'eslint-plugin-import/config/recommended.js' { 243 | declare module.exports: $Exports<'eslint-plugin-import/config/recommended'>; 244 | } 245 | declare module 'eslint-plugin-import/config/stage-0.js' { 246 | declare module.exports: $Exports<'eslint-plugin-import/config/stage-0'>; 247 | } 248 | declare module 'eslint-plugin-import/config/warnings.js' { 249 | declare module.exports: $Exports<'eslint-plugin-import/config/warnings'>; 250 | } 251 | declare module 'eslint-plugin-import/lib/core/importType.js' { 252 | declare module.exports: $Exports<'eslint-plugin-import/lib/core/importType'>; 253 | } 254 | declare module 'eslint-plugin-import/lib/core/staticRequire.js' { 255 | declare module.exports: $Exports<'eslint-plugin-import/lib/core/staticRequire'>; 256 | } 257 | declare module 'eslint-plugin-import/lib/docsUrl.js' { 258 | declare module.exports: $Exports<'eslint-plugin-import/lib/docsUrl'>; 259 | } 260 | declare module 'eslint-plugin-import/lib/ExportMap.js' { 261 | declare module.exports: $Exports<'eslint-plugin-import/lib/ExportMap'>; 262 | } 263 | declare module 'eslint-plugin-import/lib/importDeclaration.js' { 264 | declare module.exports: $Exports<'eslint-plugin-import/lib/importDeclaration'>; 265 | } 266 | declare module 'eslint-plugin-import/lib/index.js' { 267 | declare module.exports: $Exports<'eslint-plugin-import/lib/index'>; 268 | } 269 | declare module 'eslint-plugin-import/lib/rules/default.js' { 270 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/default'>; 271 | } 272 | declare module 'eslint-plugin-import/lib/rules/export.js' { 273 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/export'>; 274 | } 275 | declare module 'eslint-plugin-import/lib/rules/exports-last.js' { 276 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/exports-last'>; 277 | } 278 | declare module 'eslint-plugin-import/lib/rules/extensions.js' { 279 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/extensions'>; 280 | } 281 | declare module 'eslint-plugin-import/lib/rules/first.js' { 282 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/first'>; 283 | } 284 | declare module 'eslint-plugin-import/lib/rules/group-exports.js' { 285 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/group-exports'>; 286 | } 287 | declare module 'eslint-plugin-import/lib/rules/imports-first.js' { 288 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/imports-first'>; 289 | } 290 | declare module 'eslint-plugin-import/lib/rules/max-dependencies.js' { 291 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/max-dependencies'>; 292 | } 293 | declare module 'eslint-plugin-import/lib/rules/named.js' { 294 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/named'>; 295 | } 296 | declare module 'eslint-plugin-import/lib/rules/namespace.js' { 297 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/namespace'>; 298 | } 299 | declare module 'eslint-plugin-import/lib/rules/newline-after-import.js' { 300 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/newline-after-import'>; 301 | } 302 | declare module 'eslint-plugin-import/lib/rules/no-absolute-path.js' { 303 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-absolute-path'>; 304 | } 305 | declare module 'eslint-plugin-import/lib/rules/no-amd.js' { 306 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-amd'>; 307 | } 308 | declare module 'eslint-plugin-import/lib/rules/no-anonymous-default-export.js' { 309 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-anonymous-default-export'>; 310 | } 311 | declare module 'eslint-plugin-import/lib/rules/no-commonjs.js' { 312 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-commonjs'>; 313 | } 314 | declare module 'eslint-plugin-import/lib/rules/no-cycle.js' { 315 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-cycle'>; 316 | } 317 | declare module 'eslint-plugin-import/lib/rules/no-default-export.js' { 318 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-default-export'>; 319 | } 320 | declare module 'eslint-plugin-import/lib/rules/no-deprecated.js' { 321 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-deprecated'>; 322 | } 323 | declare module 'eslint-plugin-import/lib/rules/no-duplicates.js' { 324 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-duplicates'>; 325 | } 326 | declare module 'eslint-plugin-import/lib/rules/no-dynamic-require.js' { 327 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-dynamic-require'>; 328 | } 329 | declare module 'eslint-plugin-import/lib/rules/no-extraneous-dependencies.js' { 330 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-extraneous-dependencies'>; 331 | } 332 | declare module 'eslint-plugin-import/lib/rules/no-internal-modules.js' { 333 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-internal-modules'>; 334 | } 335 | declare module 'eslint-plugin-import/lib/rules/no-mutable-exports.js' { 336 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-mutable-exports'>; 337 | } 338 | declare module 'eslint-plugin-import/lib/rules/no-named-as-default-member.js' { 339 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-named-as-default-member'>; 340 | } 341 | declare module 'eslint-plugin-import/lib/rules/no-named-as-default.js' { 342 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-named-as-default'>; 343 | } 344 | declare module 'eslint-plugin-import/lib/rules/no-named-default.js' { 345 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-named-default'>; 346 | } 347 | declare module 'eslint-plugin-import/lib/rules/no-namespace.js' { 348 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-namespace'>; 349 | } 350 | declare module 'eslint-plugin-import/lib/rules/no-nodejs-modules.js' { 351 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-nodejs-modules'>; 352 | } 353 | declare module 'eslint-plugin-import/lib/rules/no-restricted-paths.js' { 354 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-restricted-paths'>; 355 | } 356 | declare module 'eslint-plugin-import/lib/rules/no-self-import.js' { 357 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-self-import'>; 358 | } 359 | declare module 'eslint-plugin-import/lib/rules/no-unassigned-import.js' { 360 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-unassigned-import'>; 361 | } 362 | declare module 'eslint-plugin-import/lib/rules/no-unresolved.js' { 363 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-unresolved'>; 364 | } 365 | declare module 'eslint-plugin-import/lib/rules/no-useless-path-segments.js' { 366 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-useless-path-segments'>; 367 | } 368 | declare module 'eslint-plugin-import/lib/rules/no-webpack-loader-syntax.js' { 369 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-webpack-loader-syntax'>; 370 | } 371 | declare module 'eslint-plugin-import/lib/rules/order.js' { 372 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/order'>; 373 | } 374 | declare module 'eslint-plugin-import/lib/rules/prefer-default-export.js' { 375 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/prefer-default-export'>; 376 | } 377 | declare module 'eslint-plugin-import/lib/rules/unambiguous.js' { 378 | declare module.exports: $Exports<'eslint-plugin-import/lib/rules/unambiguous'>; 379 | } 380 | declare module 'eslint-plugin-import/memo-parser/index.js' { 381 | declare module.exports: $Exports<'eslint-plugin-import/memo-parser/index'>; 382 | } 383 | -------------------------------------------------------------------------------- /flow-typed/npm/express_v4.16.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cc24a4e737d9dfb8e1381c3bd4ebaa65 2 | // flow-typed version: d11eab7bb5/express_v4.16.x/flow_>=v0.32.x 3 | 4 | import type { Server } from "http"; 5 | import type { Socket } from "net"; 6 | 7 | declare type express$RouterOptions = { 8 | caseSensitive?: boolean, 9 | mergeParams?: boolean, 10 | strict?: boolean 11 | }; 12 | 13 | declare class express$RequestResponseBase { 14 | app: express$Application; 15 | get(field: string): string | void; 16 | } 17 | 18 | declare type express$RequestParams = { 19 | [param: string]: string 20 | }; 21 | 22 | declare class express$Request extends http$IncomingMessage mixins express$RequestResponseBase { 23 | baseUrl: string; 24 | body: mixed; 25 | cookies: { [cookie: string]: string }; 26 | connection: Socket; 27 | fresh: boolean; 28 | hostname: string; 29 | ip: string; 30 | ips: Array; 31 | method: string; 32 | originalUrl: string; 33 | params: express$RequestParams; 34 | path: string; 35 | protocol: "https" | "http"; 36 | query: { [name: string]: string | Array }; 37 | route: string; 38 | secure: boolean; 39 | signedCookies: { [signedCookie: string]: string }; 40 | stale: boolean; 41 | subdomains: Array; 42 | xhr: boolean; 43 | accepts(types: string): string | false; 44 | accepts(types: Array): string | false; 45 | acceptsCharsets(...charsets: Array): string | false; 46 | acceptsEncodings(...encoding: Array): string | false; 47 | acceptsLanguages(...lang: Array): string | false; 48 | header(field: string): string | void; 49 | is(type: string): boolean; 50 | param(name: string, defaultValue?: string): string | void; 51 | } 52 | 53 | declare type express$CookieOptions = { 54 | domain?: string, 55 | encode?: (value: string) => string, 56 | expires?: Date, 57 | httpOnly?: boolean, 58 | maxAge?: number, 59 | path?: string, 60 | secure?: boolean, 61 | signed?: boolean 62 | }; 63 | 64 | declare type express$Path = string | RegExp; 65 | 66 | declare type express$RenderCallback = ( 67 | err: Error | null, 68 | html?: string 69 | ) => mixed; 70 | 71 | declare type express$SendFileOptions = { 72 | maxAge?: number, 73 | root?: string, 74 | lastModified?: boolean, 75 | headers?: { [name: string]: string }, 76 | dotfiles?: "allow" | "deny" | "ignore" 77 | }; 78 | 79 | declare class express$Response extends http$ServerResponse mixins express$RequestResponseBase { 80 | headersSent: boolean; 81 | locals: { [name: string]: mixed }; 82 | append(field: string, value?: string): this; 83 | attachment(filename?: string): this; 84 | cookie(name: string, value: string, options?: express$CookieOptions): this; 85 | clearCookie(name: string, options?: express$CookieOptions): this; 86 | download( 87 | path: string, 88 | filename?: string, 89 | callback?: (err?: ?Error) => void 90 | ): this; 91 | format(typesObject: { [type: string]: Function }): this; 92 | json(body?: mixed): this; 93 | jsonp(body?: mixed): this; 94 | links(links: { [name: string]: string }): this; 95 | location(path: string): this; 96 | redirect(url: string, ...args: Array): this; 97 | redirect(status: number, url: string, ...args: Array): this; 98 | render( 99 | view: string, 100 | locals?: { [name: string]: mixed }, 101 | callback?: express$RenderCallback 102 | ): this; 103 | send(body?: mixed): this; 104 | sendFile( 105 | path: string, 106 | options?: express$SendFileOptions, 107 | callback?: (err?: ?Error) => mixed 108 | ): this; 109 | sendStatus(statusCode: number): this; 110 | header(field: string, value?: string): this; 111 | header(headers: { [name: string]: string }): this; 112 | set(field: string, value?: string | string[]): this; 113 | set(headers: { [name: string]: string }): this; 114 | status(statusCode: number): this; 115 | type(type: string): this; 116 | vary(field: string): this; 117 | req: express$Request; 118 | } 119 | 120 | declare type express$NextFunction = (err?: ?Error | "route") => mixed; 121 | declare type express$Middleware = 122 | | (( 123 | req: $Subtype, 124 | res: express$Response, 125 | next: express$NextFunction 126 | ) => mixed) 127 | | (( 128 | error: Error, 129 | req: $Subtype, 130 | res: express$Response, 131 | next: express$NextFunction 132 | ) => mixed); 133 | declare interface express$RouteMethodType { 134 | (middleware: express$Middleware): T; 135 | (...middleware: Array): T; 136 | ( 137 | path: express$Path | express$Path[], 138 | ...middleware: Array 139 | ): T; 140 | } 141 | declare class express$Route { 142 | all: express$RouteMethodType; 143 | get: express$RouteMethodType; 144 | post: express$RouteMethodType; 145 | put: express$RouteMethodType; 146 | head: express$RouteMethodType; 147 | delete: express$RouteMethodType; 148 | options: express$RouteMethodType; 149 | trace: express$RouteMethodType; 150 | copy: express$RouteMethodType; 151 | lock: express$RouteMethodType; 152 | mkcol: express$RouteMethodType; 153 | move: express$RouteMethodType; 154 | purge: express$RouteMethodType; 155 | propfind: express$RouteMethodType; 156 | proppatch: express$RouteMethodType; 157 | unlock: express$RouteMethodType; 158 | report: express$RouteMethodType; 159 | mkactivity: express$RouteMethodType; 160 | checkout: express$RouteMethodType; 161 | merge: express$RouteMethodType; 162 | 163 | // @TODO Missing 'm-search' but get flow illegal name error. 164 | 165 | notify: express$RouteMethodType; 166 | subscribe: express$RouteMethodType; 167 | unsubscribe: express$RouteMethodType; 168 | patch: express$RouteMethodType; 169 | search: express$RouteMethodType; 170 | connect: express$RouteMethodType; 171 | } 172 | 173 | declare class express$Router extends express$Route { 174 | constructor(options?: express$RouterOptions): void; 175 | route(path: string): express$Route; 176 | static (options?: express$RouterOptions): express$Router; 177 | use(middleware: express$Middleware): this; 178 | use(...middleware: Array): this; 179 | use( 180 | path: express$Path | express$Path[], 181 | ...middleware: Array 182 | ): this; 183 | use(path: string, router: express$Router): this; 184 | handle( 185 | req: http$IncomingMessage, 186 | res: http$ServerResponse, 187 | next: express$NextFunction 188 | ): void; 189 | param( 190 | param: string, 191 | callback: ( 192 | req: $Subtype, 193 | res: express$Response, 194 | next: express$NextFunction, 195 | id: string 196 | ) => mixed 197 | ): void; 198 | ( 199 | req: http$IncomingMessage, 200 | res: http$ServerResponse, 201 | next?: ?express$NextFunction 202 | ): void; 203 | } 204 | 205 | /* 206 | With flow-bin ^0.59, express app.listen() is deemed to return any and fails flow type coverage. 207 | Which is ironic because https://github.com/facebook/flow/blob/master/Changelog.md#misc-2 (release notes for 0.59) 208 | says "Improves typings for Node.js HTTP server listen() function." See that? IMPROVES! 209 | To work around this issue, we changed Server to ?Server here, so that our invocations of express.listen() will 210 | not be deemed to lack type coverage. 211 | */ 212 | 213 | declare class express$Application extends express$Router mixins events$EventEmitter { 214 | constructor(): void; 215 | locals: { [name: string]: mixed }; 216 | mountpath: string; 217 | listen( 218 | port: number, 219 | hostname?: string, 220 | backlog?: number, 221 | callback?: (err?: ?Error) => mixed 222 | ): ?Server; 223 | listen( 224 | port: number, 225 | hostname?: string, 226 | callback?: (err?: ?Error) => mixed 227 | ): ?Server; 228 | listen(port: number, callback?: (err?: ?Error) => mixed): ?Server; 229 | listen(path: string, callback?: (err?: ?Error) => mixed): ?Server; 230 | listen(handle: Object, callback?: (err?: ?Error) => mixed): ?Server; 231 | disable(name: string): void; 232 | disabled(name: string): boolean; 233 | enable(name: string): express$Application; 234 | enabled(name: string): boolean; 235 | engine(name: string, callback: Function): void; 236 | /** 237 | * Mixed will not be taken as a value option. Issue around using the GET http method name and the get for settings. 238 | */ 239 | // get(name: string): mixed; 240 | set(name: string, value: mixed): mixed; 241 | render( 242 | name: string, 243 | optionsOrFunction: { [name: string]: mixed }, 244 | callback: express$RenderCallback 245 | ): void; 246 | handle( 247 | req: http$IncomingMessage, 248 | res: http$ServerResponse, 249 | next?: ?express$NextFunction 250 | ): void; 251 | // callable signature is not inherited 252 | ( 253 | req: http$IncomingMessage, 254 | res: http$ServerResponse, 255 | next?: ?express$NextFunction 256 | ): void; 257 | } 258 | 259 | declare type JsonOptions = { 260 | inflate?: boolean, 261 | limit?: string | number, 262 | reviver?: (key: string, value: mixed) => mixed, 263 | strict?: boolean, 264 | type?: string | Array | ((req: express$Request) => boolean), 265 | verify?: ( 266 | req: express$Request, 267 | res: express$Response, 268 | buf: Buffer, 269 | encoding: string 270 | ) => mixed 271 | }; 272 | 273 | declare type express$UrlEncodedOptions = { 274 | extended?: boolean, 275 | inflate?: boolean, 276 | limit?: string | number, 277 | parameterLimit?: number, 278 | type?: string | Array | ((req: express$Request) => boolean), 279 | verify?: ( 280 | req: express$Request, 281 | res: express$Response, 282 | buf: Buffer, 283 | encoding: string 284 | ) => mixed, 285 | } 286 | 287 | declare module "express" { 288 | declare export type RouterOptions = express$RouterOptions; 289 | declare export type CookieOptions = express$CookieOptions; 290 | declare export type Middleware = express$Middleware; 291 | declare export type NextFunction = express$NextFunction; 292 | declare export type RequestParams = express$RequestParams; 293 | declare export type $Response = express$Response; 294 | declare export type $Request = express$Request; 295 | declare export type $Application = express$Application; 296 | 297 | declare module.exports: { 298 | (): express$Application, // If you try to call like a function, it will use this signature 299 | json: (opts: ?JsonOptions) => express$Middleware, 300 | static: (root: string, options?: Object) => express$Middleware, // `static` property on the function 301 | Router: typeof express$Router, // `Router` property on the function 302 | urlencoded: (opts: ?express$UrlEncodedOptions) => express$Middleware, 303 | }; 304 | } 305 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-bin_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 2 | // flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x 3 | 4 | declare module "flow-bin" { 5 | declare module.exports: string; 6 | } 7 | -------------------------------------------------------------------------------- /flow-typed/npm/flow-typed_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 9c2bcfd860718c5ee3da1e3e4a74c941 2 | // flow-typed version: <>/flow-typed_v^2.5.1/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'flow-typed' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'flow-typed' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'flow-typed/dist/cli' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'flow-typed/dist/commands/create-stub' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'flow-typed/dist/commands/install' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'flow-typed/dist/commands/runTests' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'flow-typed/dist/commands/search' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'flow-typed/dist/commands/update-cache' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'flow-typed/dist/commands/update' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'flow-typed/dist/commands/validateDefs' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'flow-typed/dist/commands/version' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'flow-typed/dist/lib/cacheRepoUtils' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'flow-typed/dist/lib/codeSign' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'flow-typed/dist/lib/fileUtils' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'flow-typed/dist/lib/flowProjectUtils' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'flow-typed/dist/lib/flowVersion' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'flow-typed/dist/lib/git' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'flow-typed/dist/lib/github' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'flow-typed/dist/lib/isInFlowTypedRepo' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'flow-typed/dist/lib/libDefs' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'flow-typed/dist/lib/node' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'flow-typed/dist/lib/npm/npmLibDefs' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'flow-typed/dist/lib/npm/npmProjectUtils' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'flow-typed/dist/lib/semver' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'flow-typed/dist/lib/stubUtils' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'flow-typed/dist/lib/validationErrors' { 118 | declare module.exports: any; 119 | } 120 | 121 | // Filename aliases 122 | declare module 'flow-typed/dist/cli.js' { 123 | declare module.exports: $Exports<'flow-typed/dist/cli'>; 124 | } 125 | declare module 'flow-typed/dist/commands/create-stub.js' { 126 | declare module.exports: $Exports<'flow-typed/dist/commands/create-stub'>; 127 | } 128 | declare module 'flow-typed/dist/commands/install.js' { 129 | declare module.exports: $Exports<'flow-typed/dist/commands/install'>; 130 | } 131 | declare module 'flow-typed/dist/commands/runTests.js' { 132 | declare module.exports: $Exports<'flow-typed/dist/commands/runTests'>; 133 | } 134 | declare module 'flow-typed/dist/commands/search.js' { 135 | declare module.exports: $Exports<'flow-typed/dist/commands/search'>; 136 | } 137 | declare module 'flow-typed/dist/commands/update-cache.js' { 138 | declare module.exports: $Exports<'flow-typed/dist/commands/update-cache'>; 139 | } 140 | declare module 'flow-typed/dist/commands/update.js' { 141 | declare module.exports: $Exports<'flow-typed/dist/commands/update'>; 142 | } 143 | declare module 'flow-typed/dist/commands/validateDefs.js' { 144 | declare module.exports: $Exports<'flow-typed/dist/commands/validateDefs'>; 145 | } 146 | declare module 'flow-typed/dist/commands/version.js' { 147 | declare module.exports: $Exports<'flow-typed/dist/commands/version'>; 148 | } 149 | declare module 'flow-typed/dist/lib/cacheRepoUtils.js' { 150 | declare module.exports: $Exports<'flow-typed/dist/lib/cacheRepoUtils'>; 151 | } 152 | declare module 'flow-typed/dist/lib/codeSign.js' { 153 | declare module.exports: $Exports<'flow-typed/dist/lib/codeSign'>; 154 | } 155 | declare module 'flow-typed/dist/lib/fileUtils.js' { 156 | declare module.exports: $Exports<'flow-typed/dist/lib/fileUtils'>; 157 | } 158 | declare module 'flow-typed/dist/lib/flowProjectUtils.js' { 159 | declare module.exports: $Exports<'flow-typed/dist/lib/flowProjectUtils'>; 160 | } 161 | declare module 'flow-typed/dist/lib/flowVersion.js' { 162 | declare module.exports: $Exports<'flow-typed/dist/lib/flowVersion'>; 163 | } 164 | declare module 'flow-typed/dist/lib/git.js' { 165 | declare module.exports: $Exports<'flow-typed/dist/lib/git'>; 166 | } 167 | declare module 'flow-typed/dist/lib/github.js' { 168 | declare module.exports: $Exports<'flow-typed/dist/lib/github'>; 169 | } 170 | declare module 'flow-typed/dist/lib/isInFlowTypedRepo.js' { 171 | declare module.exports: $Exports<'flow-typed/dist/lib/isInFlowTypedRepo'>; 172 | } 173 | declare module 'flow-typed/dist/lib/libDefs.js' { 174 | declare module.exports: $Exports<'flow-typed/dist/lib/libDefs'>; 175 | } 176 | declare module 'flow-typed/dist/lib/node.js' { 177 | declare module.exports: $Exports<'flow-typed/dist/lib/node'>; 178 | } 179 | declare module 'flow-typed/dist/lib/npm/npmLibDefs.js' { 180 | declare module.exports: $Exports<'flow-typed/dist/lib/npm/npmLibDefs'>; 181 | } 182 | declare module 'flow-typed/dist/lib/npm/npmProjectUtils.js' { 183 | declare module.exports: $Exports<'flow-typed/dist/lib/npm/npmProjectUtils'>; 184 | } 185 | declare module 'flow-typed/dist/lib/semver.js' { 186 | declare module.exports: $Exports<'flow-typed/dist/lib/semver'>; 187 | } 188 | declare module 'flow-typed/dist/lib/stubUtils.js' { 189 | declare module.exports: $Exports<'flow-typed/dist/lib/stubUtils'>; 190 | } 191 | declare module 'flow-typed/dist/lib/validationErrors.js' { 192 | declare module.exports: $Exports<'flow-typed/dist/lib/validationErrors'>; 193 | } 194 | -------------------------------------------------------------------------------- /flow-typed/npm/github-app_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: e67c986695eba857dd9fc08249ec9f7f 2 | // flow-typed version: <>/github-app_v^3.2.0/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'github-app' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'github-app' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'github-app/docs/example' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'github-app/docs/example.js' { 31 | declare module.exports: $Exports<'github-app/docs/example'>; 32 | } 33 | declare module 'github-app/index' { 34 | declare module.exports: $Exports<'github-app'>; 35 | } 36 | declare module 'github-app/index.js' { 37 | declare module.exports: $Exports<'github-app'>; 38 | } 39 | -------------------------------------------------------------------------------- /flow-typed/npm/github-webhook-handler_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 3608db34a399bcf896f655d7266300f7 2 | // flow-typed version: <>/github-webhook-handler_v^0.7.1/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'github-webhook-handler' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'github-webhook-handler' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'github-webhook-handler/github-webhook-handler' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'github-webhook-handler/test' { 30 | declare module.exports: any; 31 | } 32 | 33 | // Filename aliases 34 | declare module 'github-webhook-handler/github-webhook-handler.js' { 35 | declare module.exports: $Exports<'github-webhook-handler/github-webhook-handler'>; 36 | } 37 | declare module 'github-webhook-handler/test.js' { 38 | declare module.exports: $Exports<'github-webhook-handler/test'>; 39 | } 40 | -------------------------------------------------------------------------------- /flow-typed/npm/memory-fs_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 3d5599719a6495dec143f3a35f668696 2 | // flow-typed version: <>/memory-fs_v^0.4.1/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'memory-fs' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'memory-fs' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'memory-fs/lib/join' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'memory-fs/lib/MemoryFileSystem' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'memory-fs/lib/normalize' { 34 | declare module.exports: any; 35 | } 36 | 37 | // Filename aliases 38 | declare module 'memory-fs/lib/join.js' { 39 | declare module.exports: $Exports<'memory-fs/lib/join'>; 40 | } 41 | declare module 'memory-fs/lib/MemoryFileSystem.js' { 42 | declare module.exports: $Exports<'memory-fs/lib/MemoryFileSystem'>; 43 | } 44 | declare module 'memory-fs/lib/normalize.js' { 45 | declare module.exports: $Exports<'memory-fs/lib/normalize'>; 46 | } 47 | -------------------------------------------------------------------------------- /flow-typed/npm/nodemon_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: cabbe890582e8c6bd14872e55bbba8b9 2 | // flow-typed version: <>/nodemon_v^1.17.3/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'nodemon' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'nodemon' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'nodemon/bin/nodemon' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'nodemon/commitlint.config' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'nodemon/lib/cli/index' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'nodemon/lib/cli/parse' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'nodemon/lib/config/command' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'nodemon/lib/config/defaults' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'nodemon/lib/config/exec' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'nodemon/lib/config/index' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'nodemon/lib/config/load' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'nodemon/lib/help/index' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'nodemon/lib/index' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'nodemon/lib/monitor/index' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'nodemon/lib/monitor/match' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'nodemon/lib/monitor/run' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'nodemon/lib/monitor/signals' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'nodemon/lib/monitor/watch' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'nodemon/lib/nodemon' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'nodemon/lib/rules/add' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'nodemon/lib/rules/index' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'nodemon/lib/rules/parse' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'nodemon/lib/spawn' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'nodemon/lib/utils/bus' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'nodemon/lib/utils/clone' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'nodemon/lib/utils/colour' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'nodemon/lib/utils/index' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'nodemon/lib/utils/log' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'nodemon/lib/utils/merge' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'nodemon/lib/version' { 134 | declare module.exports: any; 135 | } 136 | 137 | // Filename aliases 138 | declare module 'nodemon/bin/nodemon.js' { 139 | declare module.exports: $Exports<'nodemon/bin/nodemon'>; 140 | } 141 | declare module 'nodemon/commitlint.config.js' { 142 | declare module.exports: $Exports<'nodemon/commitlint.config'>; 143 | } 144 | declare module 'nodemon/lib/cli/index.js' { 145 | declare module.exports: $Exports<'nodemon/lib/cli/index'>; 146 | } 147 | declare module 'nodemon/lib/cli/parse.js' { 148 | declare module.exports: $Exports<'nodemon/lib/cli/parse'>; 149 | } 150 | declare module 'nodemon/lib/config/command.js' { 151 | declare module.exports: $Exports<'nodemon/lib/config/command'>; 152 | } 153 | declare module 'nodemon/lib/config/defaults.js' { 154 | declare module.exports: $Exports<'nodemon/lib/config/defaults'>; 155 | } 156 | declare module 'nodemon/lib/config/exec.js' { 157 | declare module.exports: $Exports<'nodemon/lib/config/exec'>; 158 | } 159 | declare module 'nodemon/lib/config/index.js' { 160 | declare module.exports: $Exports<'nodemon/lib/config/index'>; 161 | } 162 | declare module 'nodemon/lib/config/load.js' { 163 | declare module.exports: $Exports<'nodemon/lib/config/load'>; 164 | } 165 | declare module 'nodemon/lib/help/index.js' { 166 | declare module.exports: $Exports<'nodemon/lib/help/index'>; 167 | } 168 | declare module 'nodemon/lib/index.js' { 169 | declare module.exports: $Exports<'nodemon/lib/index'>; 170 | } 171 | declare module 'nodemon/lib/monitor/index.js' { 172 | declare module.exports: $Exports<'nodemon/lib/monitor/index'>; 173 | } 174 | declare module 'nodemon/lib/monitor/match.js' { 175 | declare module.exports: $Exports<'nodemon/lib/monitor/match'>; 176 | } 177 | declare module 'nodemon/lib/monitor/run.js' { 178 | declare module.exports: $Exports<'nodemon/lib/monitor/run'>; 179 | } 180 | declare module 'nodemon/lib/monitor/signals.js' { 181 | declare module.exports: $Exports<'nodemon/lib/monitor/signals'>; 182 | } 183 | declare module 'nodemon/lib/monitor/watch.js' { 184 | declare module.exports: $Exports<'nodemon/lib/monitor/watch'>; 185 | } 186 | declare module 'nodemon/lib/nodemon.js' { 187 | declare module.exports: $Exports<'nodemon/lib/nodemon'>; 188 | } 189 | declare module 'nodemon/lib/rules/add.js' { 190 | declare module.exports: $Exports<'nodemon/lib/rules/add'>; 191 | } 192 | declare module 'nodemon/lib/rules/index.js' { 193 | declare module.exports: $Exports<'nodemon/lib/rules/index'>; 194 | } 195 | declare module 'nodemon/lib/rules/parse.js' { 196 | declare module.exports: $Exports<'nodemon/lib/rules/parse'>; 197 | } 198 | declare module 'nodemon/lib/spawn.js' { 199 | declare module.exports: $Exports<'nodemon/lib/spawn'>; 200 | } 201 | declare module 'nodemon/lib/utils/bus.js' { 202 | declare module.exports: $Exports<'nodemon/lib/utils/bus'>; 203 | } 204 | declare module 'nodemon/lib/utils/clone.js' { 205 | declare module.exports: $Exports<'nodemon/lib/utils/clone'>; 206 | } 207 | declare module 'nodemon/lib/utils/colour.js' { 208 | declare module.exports: $Exports<'nodemon/lib/utils/colour'>; 209 | } 210 | declare module 'nodemon/lib/utils/index.js' { 211 | declare module.exports: $Exports<'nodemon/lib/utils/index'>; 212 | } 213 | declare module 'nodemon/lib/utils/log.js' { 214 | declare module.exports: $Exports<'nodemon/lib/utils/log'>; 215 | } 216 | declare module 'nodemon/lib/utils/merge.js' { 217 | declare module.exports: $Exports<'nodemon/lib/utils/merge'>; 218 | } 219 | declare module 'nodemon/lib/version.js' { 220 | declare module.exports: $Exports<'nodemon/lib/version'>; 221 | } 222 | -------------------------------------------------------------------------------- /flow-typed/npm/prettier_v1.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 4eed8da2dc730dc33e7710b465eaa44b 2 | // flow-typed version: cc7a557b34/prettier_v1.x.x/flow_>=v0.56.x 3 | 4 | declare module "prettier" { 5 | declare type AST = Object; 6 | declare type Doc = Object; 7 | declare type FastPath = Object; 8 | 9 | declare type PrettierParserName = 10 | | "babylon" 11 | | "flow" 12 | | "typescript" 13 | | "postcss" 14 | | "css" 15 | | "less" 16 | | "scss" 17 | | "json" 18 | | "graphql" 19 | | "markdown" 20 | | "vue"; 21 | 22 | declare type PrettierParser = { 23 | [name: PrettierParserName]: (text: string, options?: Object) => AST 24 | }; 25 | 26 | declare type CustomParser = ( 27 | text: string, 28 | parsers: PrettierParser, 29 | options: Options 30 | ) => AST; 31 | 32 | declare type Options = {| 33 | printWidth?: number, 34 | tabWidth?: number, 35 | useTabs?: boolean, 36 | semi?: boolean, 37 | singleQuote?: boolean, 38 | trailingComma?: "none" | "es5" | "all", 39 | bracketSpacing?: boolean, 40 | jsxBracketSameLine?: boolean, 41 | arrowParens?: "avoid" | "always", 42 | rangeStart?: number, 43 | rangeEnd?: number, 44 | parser?: PrettierParserName | CustomParser, 45 | filepath?: string, 46 | requirePragma?: boolean, 47 | insertPragma?: boolean, 48 | proseWrap?: "always" | "never" | "preserve", 49 | plugins?: Array 50 | |}; 51 | 52 | declare type Plugin = { 53 | languages: SupportLanguage, 54 | parsers: { [parserName: string]: Parser }, 55 | printers: { [astFormat: string]: Printer } 56 | }; 57 | 58 | declare type Parser = { 59 | parse: ( 60 | text: string, 61 | parsers: { [parserName: string]: Parser }, 62 | options: Object 63 | ) => AST, 64 | astFormat: string 65 | }; 66 | 67 | declare type Printer = { 68 | print: ( 69 | path: FastPath, 70 | options: Object, 71 | print: (path: FastPath) => Doc 72 | ) => Doc, 73 | embed: ( 74 | path: FastPath, 75 | print: (path: FastPath) => Doc, 76 | textToDoc: (text: string, options: Object) => Doc, 77 | options: Object 78 | ) => ?Doc 79 | }; 80 | 81 | declare type CursorOptions = {| 82 | cursorOffset: number, 83 | printWidth?: $PropertyType, 84 | tabWidth?: $PropertyType, 85 | useTabs?: $PropertyType, 86 | semi?: $PropertyType, 87 | singleQuote?: $PropertyType, 88 | trailingComma?: $PropertyType, 89 | bracketSpacing?: $PropertyType, 90 | jsxBracketSameLine?: $PropertyType, 91 | arrowParens?: $PropertyType, 92 | parser?: $PropertyType, 93 | filepath?: $PropertyType, 94 | requirePragma?: $PropertyType, 95 | insertPragma?: $PropertyType, 96 | proseWrap?: $PropertyType, 97 | plugins?: $PropertyType 98 | |}; 99 | 100 | declare type CursorResult = {| 101 | formatted: string, 102 | cursorOffset: number 103 | |}; 104 | 105 | declare type ResolveConfigOptions = {| 106 | useCache?: boolean, 107 | config?: string, 108 | editorconfig?: boolean 109 | |}; 110 | 111 | declare type SupportLanguage = { 112 | name: string, 113 | since: string, 114 | parsers: Array, 115 | group?: string, 116 | tmScope: string, 117 | aceMode: string, 118 | codemirrorMode: string, 119 | codemirrorMimeType: string, 120 | aliases?: Array, 121 | extensions: Array, 122 | filenames?: Array, 123 | linguistLanguageId: number, 124 | vscodeLanguageIds: Array 125 | }; 126 | 127 | declare type SupportOption = {| 128 | since: string, 129 | type: "int" | "boolean" | "choice" | "path", 130 | deprecated?: string, 131 | redirect?: SupportOptionRedirect, 132 | description: string, 133 | oppositeDescription?: string, 134 | default: SupportOptionValue, 135 | range?: SupportOptionRange, 136 | choices?: SupportOptionChoice 137 | |}; 138 | 139 | declare type SupportOptionRedirect = {| 140 | options: string, 141 | value: SupportOptionValue 142 | |}; 143 | 144 | declare type SupportOptionRange = {| 145 | start: number, 146 | end: number, 147 | step: number 148 | |}; 149 | 150 | declare type SupportOptionChoice = {| 151 | value: boolean | string, 152 | description?: string, 153 | since?: string, 154 | deprecated?: string, 155 | redirect?: SupportOptionValue 156 | |}; 157 | 158 | declare type SupportOptionValue = number | boolean | string; 159 | 160 | declare type SupportInfo = {| 161 | languages: Array, 162 | options: Array 163 | |}; 164 | 165 | declare type Prettier = {| 166 | format: (source: string, options?: Options) => string, 167 | check: (source: string, options?: Options) => boolean, 168 | formatWithCursor: (source: string, options: CursorOptions) => CursorResult, 169 | resolveConfig: { 170 | (filePath: string, options?: ResolveConfigOptions): Promise, 171 | sync(filePath: string, options?: ResolveConfigOptions): Promise 172 | }, 173 | clearConfigCache: () => void, 174 | getSupportInfo: (version?: string) => SupportInfo 175 | |}; 176 | 177 | declare export default Prettier; 178 | } 179 | -------------------------------------------------------------------------------- /flow-typed/npm/promise-queue_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: b87bb1eca2dd559d3f3c58c0377f3a6f 2 | // flow-typed version: <>/promise-queue_v^2.2.5/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'promise-queue' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'promise-queue' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'promise-queue/lib-cov/index' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'promise-queue/lib/index' { 30 | declare module.exports: any; 31 | } 32 | 33 | // Filename aliases 34 | declare module 'promise-queue/index' { 35 | declare module.exports: $Exports<'promise-queue'>; 36 | } 37 | declare module 'promise-queue/index.js' { 38 | declare module.exports: $Exports<'promise-queue'>; 39 | } 40 | declare module 'promise-queue/lib-cov/index.js' { 41 | declare module.exports: $Exports<'promise-queue/lib-cov/index'>; 42 | } 43 | declare module 'promise-queue/lib/index.js' { 44 | declare module.exports: $Exports<'promise-queue/lib/index'>; 45 | } 46 | -------------------------------------------------------------------------------- /flow-typed/npm/react-helmet_v5.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: afa3502910d5b2aef93707cc683f52b8 2 | // flow-typed version: 492c298a82/react-helmet_v5.x.x/flow_>=v0.53.x 3 | 4 | declare module 'react-helmet' { 5 | declare type Props = { 6 | base?: Object, 7 | bodyAttributes?: Object, 8 | children?: React$Node, 9 | defaultTitle?: string, 10 | defer?: boolean, 11 | encodeSpecialCharacters?: boolean, 12 | htmlAttributes?: Object, 13 | link?: Array, 14 | meta?: Array, 15 | noscript?: Array, 16 | onChangeClientState?: ( 17 | newState?: Object, 18 | addedTags?: Object, 19 | removeTags?: Object 20 | ) => any, 21 | script?: Array, 22 | style?: Array, 23 | title?: string, 24 | titleAttributes?: Object, 25 | titleTemplate?: string, 26 | } 27 | 28 | declare interface TagMethods { 29 | toString(): string; 30 | toComponent(): [React$Element<*>] | React$Element<*> | Array; 31 | } 32 | 33 | declare interface AttributeTagMethods { 34 | toString(): string; 35 | toComponent(): {[string]: *}; 36 | } 37 | 38 | declare interface StateOnServer { 39 | base: TagMethods; 40 | bodyAttributes: AttributeTagMethods, 41 | htmlAttributes: AttributeTagMethods; 42 | link: TagMethods; 43 | meta: TagMethods; 44 | noscript: TagMethods; 45 | script: TagMethods; 46 | style: TagMethods; 47 | title: TagMethods; 48 | } 49 | 50 | declare class Helmet extends React$Component { 51 | static rewind(): StateOnServer; 52 | static renderStatic(): StateOnServer; 53 | static canUseDom(canUseDOM: boolean): void; 54 | } 55 | 56 | declare export default typeof Helmet 57 | declare export var Helmet: typeof Helmet 58 | } 59 | 60 | -------------------------------------------------------------------------------- /flow-typed/npm/rimraf_v2.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 1dff23447d5e18f5ac2b05aaec7cfb74 2 | // flow-typed version: a453e98ea2/rimraf_v2.x.x/flow_>=v0.25.0 3 | 4 | declare module 'rimraf' { 5 | declare type Options = { 6 | maxBusyTries?: number, 7 | emfileWait?: number, 8 | glob?: boolean, 9 | disableGlob?: boolean 10 | }; 11 | 12 | declare type Callback = (err: ?Error, path: ?string) => void; 13 | 14 | declare module.exports: { 15 | (f: string, opts?: Options | Callback, callback?: Callback): void; 16 | sync(path: string, opts?: Options): void; 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /flow-typed/npm/shelljs_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 206f84d6c43290897e78261cb72a32c3 2 | // flow-typed version: <>/shelljs_v^0.8.1/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'shelljs' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'shelljs' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'shelljs/commands' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'shelljs/global' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'shelljs/make' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'shelljs/plugin' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'shelljs/shell' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'shelljs/src/cat' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'shelljs/src/cd' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'shelljs/src/chmod' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'shelljs/src/common' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'shelljs/src/cp' { 62 | declare module.exports: any; 63 | } 64 | 65 | declare module 'shelljs/src/dirs' { 66 | declare module.exports: any; 67 | } 68 | 69 | declare module 'shelljs/src/echo' { 70 | declare module.exports: any; 71 | } 72 | 73 | declare module 'shelljs/src/error' { 74 | declare module.exports: any; 75 | } 76 | 77 | declare module 'shelljs/src/exec-child' { 78 | declare module.exports: any; 79 | } 80 | 81 | declare module 'shelljs/src/exec' { 82 | declare module.exports: any; 83 | } 84 | 85 | declare module 'shelljs/src/find' { 86 | declare module.exports: any; 87 | } 88 | 89 | declare module 'shelljs/src/grep' { 90 | declare module.exports: any; 91 | } 92 | 93 | declare module 'shelljs/src/head' { 94 | declare module.exports: any; 95 | } 96 | 97 | declare module 'shelljs/src/ln' { 98 | declare module.exports: any; 99 | } 100 | 101 | declare module 'shelljs/src/ls' { 102 | declare module.exports: any; 103 | } 104 | 105 | declare module 'shelljs/src/mkdir' { 106 | declare module.exports: any; 107 | } 108 | 109 | declare module 'shelljs/src/mv' { 110 | declare module.exports: any; 111 | } 112 | 113 | declare module 'shelljs/src/popd' { 114 | declare module.exports: any; 115 | } 116 | 117 | declare module 'shelljs/src/pushd' { 118 | declare module.exports: any; 119 | } 120 | 121 | declare module 'shelljs/src/pwd' { 122 | declare module.exports: any; 123 | } 124 | 125 | declare module 'shelljs/src/rm' { 126 | declare module.exports: any; 127 | } 128 | 129 | declare module 'shelljs/src/sed' { 130 | declare module.exports: any; 131 | } 132 | 133 | declare module 'shelljs/src/set' { 134 | declare module.exports: any; 135 | } 136 | 137 | declare module 'shelljs/src/sort' { 138 | declare module.exports: any; 139 | } 140 | 141 | declare module 'shelljs/src/tail' { 142 | declare module.exports: any; 143 | } 144 | 145 | declare module 'shelljs/src/tempdir' { 146 | declare module.exports: any; 147 | } 148 | 149 | declare module 'shelljs/src/test' { 150 | declare module.exports: any; 151 | } 152 | 153 | declare module 'shelljs/src/to' { 154 | declare module.exports: any; 155 | } 156 | 157 | declare module 'shelljs/src/toEnd' { 158 | declare module.exports: any; 159 | } 160 | 161 | declare module 'shelljs/src/touch' { 162 | declare module.exports: any; 163 | } 164 | 165 | declare module 'shelljs/src/uniq' { 166 | declare module.exports: any; 167 | } 168 | 169 | declare module 'shelljs/src/which' { 170 | declare module.exports: any; 171 | } 172 | 173 | // Filename aliases 174 | declare module 'shelljs/commands.js' { 175 | declare module.exports: $Exports<'shelljs/commands'>; 176 | } 177 | declare module 'shelljs/global.js' { 178 | declare module.exports: $Exports<'shelljs/global'>; 179 | } 180 | declare module 'shelljs/make.js' { 181 | declare module.exports: $Exports<'shelljs/make'>; 182 | } 183 | declare module 'shelljs/plugin.js' { 184 | declare module.exports: $Exports<'shelljs/plugin'>; 185 | } 186 | declare module 'shelljs/shell.js' { 187 | declare module.exports: $Exports<'shelljs/shell'>; 188 | } 189 | declare module 'shelljs/src/cat.js' { 190 | declare module.exports: $Exports<'shelljs/src/cat'>; 191 | } 192 | declare module 'shelljs/src/cd.js' { 193 | declare module.exports: $Exports<'shelljs/src/cd'>; 194 | } 195 | declare module 'shelljs/src/chmod.js' { 196 | declare module.exports: $Exports<'shelljs/src/chmod'>; 197 | } 198 | declare module 'shelljs/src/common.js' { 199 | declare module.exports: $Exports<'shelljs/src/common'>; 200 | } 201 | declare module 'shelljs/src/cp.js' { 202 | declare module.exports: $Exports<'shelljs/src/cp'>; 203 | } 204 | declare module 'shelljs/src/dirs.js' { 205 | declare module.exports: $Exports<'shelljs/src/dirs'>; 206 | } 207 | declare module 'shelljs/src/echo.js' { 208 | declare module.exports: $Exports<'shelljs/src/echo'>; 209 | } 210 | declare module 'shelljs/src/error.js' { 211 | declare module.exports: $Exports<'shelljs/src/error'>; 212 | } 213 | declare module 'shelljs/src/exec-child.js' { 214 | declare module.exports: $Exports<'shelljs/src/exec-child'>; 215 | } 216 | declare module 'shelljs/src/exec.js' { 217 | declare module.exports: $Exports<'shelljs/src/exec'>; 218 | } 219 | declare module 'shelljs/src/find.js' { 220 | declare module.exports: $Exports<'shelljs/src/find'>; 221 | } 222 | declare module 'shelljs/src/grep.js' { 223 | declare module.exports: $Exports<'shelljs/src/grep'>; 224 | } 225 | declare module 'shelljs/src/head.js' { 226 | declare module.exports: $Exports<'shelljs/src/head'>; 227 | } 228 | declare module 'shelljs/src/ln.js' { 229 | declare module.exports: $Exports<'shelljs/src/ln'>; 230 | } 231 | declare module 'shelljs/src/ls.js' { 232 | declare module.exports: $Exports<'shelljs/src/ls'>; 233 | } 234 | declare module 'shelljs/src/mkdir.js' { 235 | declare module.exports: $Exports<'shelljs/src/mkdir'>; 236 | } 237 | declare module 'shelljs/src/mv.js' { 238 | declare module.exports: $Exports<'shelljs/src/mv'>; 239 | } 240 | declare module 'shelljs/src/popd.js' { 241 | declare module.exports: $Exports<'shelljs/src/popd'>; 242 | } 243 | declare module 'shelljs/src/pushd.js' { 244 | declare module.exports: $Exports<'shelljs/src/pushd'>; 245 | } 246 | declare module 'shelljs/src/pwd.js' { 247 | declare module.exports: $Exports<'shelljs/src/pwd'>; 248 | } 249 | declare module 'shelljs/src/rm.js' { 250 | declare module.exports: $Exports<'shelljs/src/rm'>; 251 | } 252 | declare module 'shelljs/src/sed.js' { 253 | declare module.exports: $Exports<'shelljs/src/sed'>; 254 | } 255 | declare module 'shelljs/src/set.js' { 256 | declare module.exports: $Exports<'shelljs/src/set'>; 257 | } 258 | declare module 'shelljs/src/sort.js' { 259 | declare module.exports: $Exports<'shelljs/src/sort'>; 260 | } 261 | declare module 'shelljs/src/tail.js' { 262 | declare module.exports: $Exports<'shelljs/src/tail'>; 263 | } 264 | declare module 'shelljs/src/tempdir.js' { 265 | declare module.exports: $Exports<'shelljs/src/tempdir'>; 266 | } 267 | declare module 'shelljs/src/test.js' { 268 | declare module.exports: $Exports<'shelljs/src/test'>; 269 | } 270 | declare module 'shelljs/src/to.js' { 271 | declare module.exports: $Exports<'shelljs/src/to'>; 272 | } 273 | declare module 'shelljs/src/toEnd.js' { 274 | declare module.exports: $Exports<'shelljs/src/toEnd'>; 275 | } 276 | declare module 'shelljs/src/touch.js' { 277 | declare module.exports: $Exports<'shelljs/src/touch'>; 278 | } 279 | declare module 'shelljs/src/uniq.js' { 280 | declare module.exports: $Exports<'shelljs/src/uniq'>; 281 | } 282 | declare module 'shelljs/src/which.js' { 283 | declare module.exports: $Exports<'shelljs/src/which'>; 284 | } 285 | -------------------------------------------------------------------------------- /flow-typed/npm/signal-exit_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: d694e308159d24db1dca132843d6caf1 2 | // flow-typed version: <>/signal-exit_v^3.0.2/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'signal-exit' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'signal-exit' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'signal-exit/signals' { 26 | declare module.exports: any; 27 | } 28 | 29 | // Filename aliases 30 | declare module 'signal-exit/index' { 31 | declare module.exports: $Exports<'signal-exit'>; 32 | } 33 | declare module 'signal-exit/index.js' { 34 | declare module.exports: $Exports<'signal-exit'>; 35 | } 36 | declare module 'signal-exit/signals.js' { 37 | declare module.exports: $Exports<'signal-exit/signals'>; 38 | } 39 | -------------------------------------------------------------------------------- /flow-typed/npm/strip-ansi_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 1c8b6f77d7abda08fae61e1b5134ab05 2 | // flow-typed version: <>/strip-ansi_v^4.0.0/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'strip-ansi' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'strip-ansi' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'strip-ansi/index' { 29 | declare module.exports: $Exports<'strip-ansi'>; 30 | } 31 | declare module 'strip-ansi/index.js' { 32 | declare module.exports: $Exports<'strip-ansi'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/uid_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 8681272fc246528b5918e7013fdf8d04 2 | // flow-typed version: <>/uid_v^0.0.2/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'uid' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'uid' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | 26 | 27 | // Filename aliases 28 | declare module 'uid/index' { 29 | declare module.exports: $Exports<'uid'>; 30 | } 31 | declare module 'uid/index.js' { 32 | declare module.exports: $Exports<'uid'>; 33 | } 34 | -------------------------------------------------------------------------------- /flow-typed/npm/yargs_vx.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 6841cfdbd700d042a3525a4117818b10 2 | // flow-typed version: <>/yargs_v^11.0.0/flow_v0.72.0 3 | 4 | /** 5 | * This is an autogenerated libdef stub for: 6 | * 7 | * 'yargs' 8 | * 9 | * Fill this stub out by replacing all the `any` types. 10 | * 11 | * Once filled out, we encourage you to share your work with the 12 | * community by sending a pull request to: 13 | * https://github.com/flowtype/flow-typed 14 | */ 15 | 16 | declare module 'yargs' { 17 | declare module.exports: any; 18 | } 19 | 20 | /** 21 | * We include stubs for each file inside this npm package in case you need to 22 | * require those files directly. Feel free to delete any files that aren't 23 | * needed. 24 | */ 25 | declare module 'yargs/lib/apply-extends' { 26 | declare module.exports: any; 27 | } 28 | 29 | declare module 'yargs/lib/argsert' { 30 | declare module.exports: any; 31 | } 32 | 33 | declare module 'yargs/lib/command' { 34 | declare module.exports: any; 35 | } 36 | 37 | declare module 'yargs/lib/completion' { 38 | declare module.exports: any; 39 | } 40 | 41 | declare module 'yargs/lib/levenshtein' { 42 | declare module.exports: any; 43 | } 44 | 45 | declare module 'yargs/lib/obj-filter' { 46 | declare module.exports: any; 47 | } 48 | 49 | declare module 'yargs/lib/usage' { 50 | declare module.exports: any; 51 | } 52 | 53 | declare module 'yargs/lib/validation' { 54 | declare module.exports: any; 55 | } 56 | 57 | declare module 'yargs/lib/yerror' { 58 | declare module.exports: any; 59 | } 60 | 61 | declare module 'yargs/yargs' { 62 | declare module.exports: any; 63 | } 64 | 65 | // Filename aliases 66 | declare module 'yargs/index' { 67 | declare module.exports: $Exports<'yargs'>; 68 | } 69 | declare module 'yargs/index.js' { 70 | declare module.exports: $Exports<'yargs'>; 71 | } 72 | declare module 'yargs/lib/apply-extends.js' { 73 | declare module.exports: $Exports<'yargs/lib/apply-extends'>; 74 | } 75 | declare module 'yargs/lib/argsert.js' { 76 | declare module.exports: $Exports<'yargs/lib/argsert'>; 77 | } 78 | declare module 'yargs/lib/command.js' { 79 | declare module.exports: $Exports<'yargs/lib/command'>; 80 | } 81 | declare module 'yargs/lib/completion.js' { 82 | declare module.exports: $Exports<'yargs/lib/completion'>; 83 | } 84 | declare module 'yargs/lib/levenshtein.js' { 85 | declare module.exports: $Exports<'yargs/lib/levenshtein'>; 86 | } 87 | declare module 'yargs/lib/obj-filter.js' { 88 | declare module.exports: $Exports<'yargs/lib/obj-filter'>; 89 | } 90 | declare module 'yargs/lib/usage.js' { 91 | declare module.exports: $Exports<'yargs/lib/usage'>; 92 | } 93 | declare module 'yargs/lib/validation.js' { 94 | declare module.exports: $Exports<'yargs/lib/validation'>; 95 | } 96 | declare module 'yargs/lib/yerror.js' { 97 | declare module.exports: $Exports<'yargs/lib/yerror'>; 98 | } 99 | declare module 'yargs/yargs.js' { 100 | declare module.exports: $Exports<'yargs/yargs'>; 101 | } 102 | -------------------------------------------------------------------------------- /github-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suchipi/quinci/c7b3ff707d77bad5246a4c8712026362d2ad9af6/github-screenshot.png -------------------------------------------------------------------------------- /logo/README.md: -------------------------------------------------------------------------------- 1 | quinCI logo created by [Maki](https://maki.cat) 2 | -------------------------------------------------------------------------------- /logo/quinCI.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suchipi/quinci/c7b3ff707d77bad5246a4c8712026362d2ad9af6/logo/quinCI.ai -------------------------------------------------------------------------------- /logo/quinCI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suchipi/quinci/c7b3ff707d77bad5246a4c8712026362d2ad9af6/logo/quinCI.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quinci", 3 | "description": "Self-hosted, minimal GitHub CI server", 4 | "version": "0.9.6", 5 | "bin": "dist/cli.js", 6 | "main": "dist/index.js", 7 | "license": "MIT", 8 | "repository": "suchipi/quinci", 9 | "bugs": "https://github.com/suchipi/quinci/issues", 10 | "author": "Suchipi ", 11 | "keywords": [ 12 | "CI", 13 | "quincy", 14 | "jenkins", 15 | "teamcity", 16 | "travis", 17 | "circleci", 18 | "continuous", 19 | "integration", 20 | "self-hosted", 21 | "tests", 22 | "lint", 23 | "verify", 24 | "github", 25 | "app" 26 | ], 27 | "dependencies": { 28 | "ansi_up": "^3.0.0", 29 | "cross-spawn": "^6.0.5", 30 | "debug": "^3.1.0", 31 | "express": "^4.16.3", 32 | "github-app": "^4.0.1", 33 | "github-webhook-handler": "^0.7.1", 34 | "moment": "^2.22.2", 35 | "promise-queue": "^2.2.5", 36 | "react": "^16.4.1", 37 | "react-dom": "^16.4.1", 38 | "react-helmet-async": "^0.1.0-alpha", 39 | "react-octicons": "^0.2.0", 40 | "shelljs": "^0.8.1", 41 | "signal-exit": "^3.0.2", 42 | "strip-ansi": "^4.0.0", 43 | "uid": "^0.0.2", 44 | "yargs": "^11.0.0" 45 | }, 46 | "devDependencies": { 47 | "@babel/cli": "^7.0.0-beta.54", 48 | "@babel/core": "^7.0.0-beta.54", 49 | "@babel/plugin-proposal-class-properties": "^7.0.0-beta.54", 50 | "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-beta.54", 51 | "@babel/plugin-proposal-object-rest-spread": "^7.0.0-beta.54", 52 | "@babel/plugin-transform-flow-strip-types": "^7.0.0-beta.54", 53 | "@babel/preset-react": "^7.0.0-beta.54", 54 | "@storybook/addon-actions": "^3.4.8", 55 | "@storybook/addon-links": "^3.4.8", 56 | "@storybook/addons": "^3.4.8", 57 | "@storybook/react": "^3.4.8", 58 | "babel-core": "^7.0.0-0", 59 | "babel-eslint": "^8.2.6", 60 | "babel-runtime": "^6.26.0", 61 | "eslint": "^5.2.0", 62 | "eslint-config-unobtrusive": "^1.2.2", 63 | "eslint-plugin-flowtype": "^2.50.0", 64 | "eslint-plugin-import": "^2.13.0", 65 | "eslint-plugin-react": "^7.10.0", 66 | "flow-bin": "^0.77.0", 67 | "flow-typed": "^2.5.1", 68 | "nodemon": "^1.18.3", 69 | "prettier": "^1.13.7", 70 | "rimraf": "^2.6.2" 71 | }, 72 | "scripts": { 73 | "build": "rimraf dist/* && babel src --out-dir dist && chmod +x dist/cli.js", 74 | "build:watch": "babel --watch src --out-dir dist", 75 | "start": "env DEBUG='quinci:*' nodemon --watch ./dist dist/cli.js -- --app-id 12403 --app-cert secrets/quinci.pem --webhook-secret-file secrets/webhook-secret.txt --web-url http://example.com", 76 | "storybook": "start-storybook -p 6006 -s ./.storybook/public", 77 | "build-storybook": "build-storybook" 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/app-context.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { GithubApp } from "./create-github-app"; 3 | import type { NormalizedConfig } from "./normalize-config"; 4 | const createGithubApp = require("./create-github-app"); 5 | const Queues = require("./queues"); 6 | 7 | module.exports = class AppContext { 8 | githubApp: GithubApp; 9 | queues: Queues; 10 | config: NormalizedConfig; 11 | 12 | constructor(config: NormalizedConfig) { 13 | this.config = config; 14 | this.githubApp = createGithubApp(config); 15 | this.queues = new Queues(config); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* @flow */ 3 | const argv = require("yargs") 4 | .option("port", { 5 | describe: "Port to run the HTTP server on", 6 | default: 7777, 7 | }) 8 | .option("app-id", { 9 | describe: "GitHub App ID", 10 | }) 11 | .option("app-cert", { 12 | describe: "Path to the GitHub App's private key pem file", 13 | }) 14 | .option("webhook-secret-file", { 15 | describe: "Path to a text file containing your Webhook secret", 16 | }) 17 | .option("queue-concurrency", { 18 | describe: 19 | "How many instances of a job are allowed to run at once. Use 'Infinity' for no limit.", 20 | default: "master=1,main=1,pull-request=3", 21 | }) 22 | .option("web-url", { 23 | describe: "URL at which the web UI can be accessed", 24 | }) 25 | .option("named-branches", { 26 | describe: 27 | "Comma-separated list of branch names that have corresponding jobs in the 'quinci' folder in the repo root, that should be run when commits are pushed to that branch.", 28 | default: "master,main", 29 | }) 30 | .demandOption([ 31 | "port", 32 | "app-id", 33 | "app-cert", 34 | "webhook-secret-file", 35 | "web-url", 36 | ]).argv; 37 | 38 | const debug = require("debug")("quinci:cli"); 39 | const normalizeConfig = require("./normalize-config"); 40 | const runQuinCI = require("./index"); 41 | 42 | const config = normalizeConfig(argv); 43 | 44 | debug("Config: " + JSON.stringify(config, null, 2)); 45 | 46 | runQuinCI(config).then(() => { 47 | const version = require("../package.json").version; 48 | console.log(`quinCI ${version} is running`); 49 | }); 50 | -------------------------------------------------------------------------------- /src/comment-templates.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const stripAnsi = require("strip-ansi"); 3 | const Job = require("./job"); 4 | 5 | const MAX_COMMENT_SIZE = 65536; 6 | 7 | module.exports = { 8 | waiting(job: Job): string { 9 | return `🕑 quinCI will run '${job.taskName}' once other '${ 10 | job.taskName 11 | }' jobs finish.\n`; 12 | }, 13 | running(job: Job): string { 14 | return `🕑 quinCI is running '${job.taskName}'...\n`; 15 | }, 16 | success(job: Job): string { 17 | const output = stripAnsi(job.runResult.output); 18 | 19 | const header = 20 | `✅ quinCI run of '${job.taskName}' passed.\n` + 21 | "
\n" + 22 | "Log output:\n" + 23 | "\n``````\n"; 24 | const body = output.trim(); 25 | const footer = "\n``````\n" + "
"; 26 | 27 | return ( 28 | header + 29 | body.slice(-(MAX_COMMENT_SIZE - header.length - footer.length)) + 30 | footer 31 | ); 32 | }, 33 | failure(job: Job): string { 34 | const output = stripAnsi(job.runResult.output); 35 | 36 | const header = 37 | `❌ quinCI run of '${job.taskName}' failed. Exit code was ${ 38 | job.runResult.code 39 | }.\n` + 40 | "
\n" + 41 | "Log output:\n" + 42 | "\n``````\n"; 43 | const body = output.trim(); 44 | const footer = "\n``````\n" + "
"; 45 | 46 | return ( 47 | header + 48 | body.slice(-(MAX_COMMENT_SIZE - header.length - footer.length)) + 49 | footer 50 | ); 51 | }, 52 | error(taskName: string, error: ?Error): string { 53 | const header = 54 | `❌ quinCI run of '${taskName}' errored.\n` + "Error:\n" + "\n``````\n"; 55 | const body = error ? error.stack.trim() : "(no error)"; 56 | const footer = "\n``````\n" + ""; 57 | 58 | return ( 59 | header + 60 | body.slice(0, MAX_COMMENT_SIZE - header.length - footer.length) + 61 | footer 62 | ); 63 | }, 64 | canceled(job: Job) { 65 | return `🚫 quinCI run of '${job.taskName}' was canceled.`; 66 | }, 67 | }; 68 | -------------------------------------------------------------------------------- /src/create-github-app.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { NormalizedConfig } from "./normalize-config"; 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const githubApp = require("github-app"); 6 | 7 | export type GithubApp = any; 8 | 9 | module.exports = function createGithubApp(config: NormalizedConfig): GithubApp { 10 | return githubApp({ 11 | id: config.appId, 12 | cert: fs.readFileSync(path.resolve(process.cwd(), config.appCert)), 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /src/create-github-app.shim.js: -------------------------------------------------------------------------------- 1 | module.exports = function createGithubAppShim(config) { 2 | return {}; 3 | }; 4 | -------------------------------------------------------------------------------- /src/create-http-middleware.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { $Request, $Response } from "express"; 3 | import type { IncomingMessage, ServerResponse } from "http"; 4 | const debug = require("debug")("quinci:http"); 5 | const AppContext = require("./app-context"); 6 | const webUI = require("./web-ui"); 7 | const createWebhookHandler = require("./create-webhook-handler"); 8 | 9 | export type HTTPRequest = $Request & { appContext: AppContext }; 10 | export type HTTPResponse = $Response; 11 | 12 | module.exports = function createHttpMiddleware(appContext: AppContext) { 13 | const webhookHandler = createWebhookHandler(appContext); 14 | 15 | return (req: IncomingMessage, res: ServerResponse) => { 16 | try { 17 | webhookHandler(req, res, () => { 18 | // $FlowFixMe 19 | req.appContext = appContext; 20 | webUI(req, res); 21 | }); 22 | } catch (err) { 23 | debug( 24 | "Error in HTTP request handler: " + (err && err.stack) ? err.stack : err 25 | ); 26 | res.statusCode = 500; 27 | res.end("500 Internal Server Error"); 28 | } 29 | }; 30 | }; 31 | -------------------------------------------------------------------------------- /src/create-webhook-handler.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { IncomingMessage, ServerResponse } from "http"; 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const githubWebhookHandler = require("github-webhook-handler"); 6 | const makeDebug = require("debug"); 7 | const AppContext = require("./app-context"); 8 | 9 | export type WebhookHandler = (( 10 | req: IncomingMessage, 11 | res: ServerResponse, 12 | next: (err: ?Error) => void 13 | ) => void) & { 14 | on: ( 15 | eventType: string, 16 | callback: (event: { payload: Object }) => ?mixed 17 | ) => void, 18 | }; 19 | 20 | export type SetupEventFunction = ({ 21 | webhookHandler: WebhookHandler, 22 | appContext: AppContext, 23 | makeLogger: (prefix: string) => (message: string) => void, 24 | }) => void; 25 | 26 | module.exports = function createWebhookHandler( 27 | appContext: AppContext 28 | ): WebhookHandler { 29 | const webhookHandler = githubWebhookHandler({ 30 | path: "/", 31 | secret: fs 32 | .readFileSync( 33 | path.resolve(process.cwd(), appContext.config.webhookSecretFile), 34 | "utf-8" 35 | ) 36 | .trim(), 37 | }); 38 | 39 | [ 40 | { 41 | loggerName: "commit-comment", 42 | setupEvent: require("./events/commit-comment"), 43 | }, 44 | { 45 | loggerName: "pull-request-comment", 46 | setupEvent: require("./events/pull-request-comment"), 47 | }, 48 | { 49 | loggerName: "pull-request", 50 | setupEvent: require("./events/pull-request"), 51 | }, 52 | ...appContext.config.namedBranches.map((branchName) => ({ 53 | loggerName: `push-to-${branchName}`, 54 | setupEvent: require("./events/push-to-named-branch")(branchName), 55 | })), 56 | ].forEach(({ loggerName, setupEvent }) => { 57 | const debug = makeDebug(`quinci:${loggerName}`); 58 | const makeLogger = (prefix) => (msg) => debug(`${prefix}${msg}`); 59 | setupEvent({ webhookHandler, appContext, makeLogger }); 60 | }); 61 | 62 | return webhookHandler; 63 | }; 64 | -------------------------------------------------------------------------------- /src/events/commit-comment.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { SetupEventFunction } from "../create-webhook-handler"; 3 | const Job = require("../job"); 4 | const GithubReporter = require("../github-reporter"); 5 | 6 | module.exports = (function setupEvent({ 7 | webhookHandler, 8 | appContext, 9 | makeLogger, 10 | }) { 11 | webhookHandler.on("commit_comment", async ({ payload }) => { 12 | const { githubApp, queues } = appContext; 13 | // $FlowFixMe 14 | let log: (msg: string) => void; 15 | // $FlowFixMe 16 | let reporter: GithubReporter; 17 | 18 | try { 19 | const [owner, repo] = payload.repository.full_name.split("/"); 20 | const sha = payload.comment.commit_id; 21 | log = makeLogger(`${repo}/${owner} ${sha}: `); 22 | 23 | log("Received a commit_comment event"); 24 | 25 | if (payload.action !== "created") { 26 | log("Aborting because action was not 'created'"); 27 | return; 28 | } 29 | if (payload.comment.user.type === "Bot") { 30 | log("Aborting because user was a bot"); 31 | return; 32 | } 33 | 34 | const matches = payload.comment.body.match( 35 | /quin+c[eyi]+.* run ([\w.-]+)/i 36 | ); 37 | if (!matches) { 38 | log("Aborting because comment body did not request a CI run"); 39 | return; 40 | } 41 | const taskName = matches[1]; 42 | 43 | const github = await githubApp.asInstallation(payload.installation.id); 44 | const username = payload.comment.user.login; 45 | 46 | log(`Checking if ${username} has write access`); 47 | const authLevelResponse = await github.repos.reviewUserPermissionLevel({ 48 | owner, 49 | repo, 50 | username, 51 | }); 52 | 53 | const permission = authLevelResponse.data.permission; 54 | if (permission !== "admin" && permission !== "write") { 55 | log("Aborting because user does not have write access"); 56 | return; 57 | } 58 | 59 | const job = new Job({ 60 | taskName, 61 | commitSha: sha, 62 | remote: payload.repository.ssh_url, 63 | }); 64 | 65 | reporter = new GithubReporter({ 66 | appContext, 67 | githubApp, 68 | installationId: payload.installation.id, 69 | owner, 70 | repo, 71 | sha, 72 | job, 73 | }); 74 | 75 | const queue = queues.getQueueForTaskName(taskName); 76 | log(`Queue concurrency for '${taskName}' is ${queue.getConcurrency()}.`); 77 | log( 78 | `There are ${queue.getRunning()} job(s) running in the '${taskName}' queue.` 79 | ); 80 | log( 81 | `There are ${queue.getWaiting()} job(s) waiting in the '${taskName}' queue.` 82 | ); 83 | 84 | if (!queue.canRunNow()) { 85 | log("Setting status to waiting"); 86 | await reporter.setStatus("waiting"); 87 | 88 | log("Posting waiting comment"); 89 | await reporter.commitComment("waiting"); 90 | } 91 | 92 | job.on("running", async () => { 93 | log(`Running job for '${taskName}'`); 94 | log("Setting status to running"); 95 | await reporter.setStatus("running"); 96 | 97 | log("Posting running comment"); 98 | await reporter.commitComment("running"); 99 | }); 100 | 101 | job.on("success", async () => { 102 | log(`Job for '${taskName}' succeeded`); 103 | log("Setting status to success"); 104 | await reporter.setStatus("success"); 105 | 106 | log("Posting success comment"); 107 | await reporter.commitComment("success"); 108 | }); 109 | 110 | job.on("failure", async () => { 111 | log(`Job for '${taskName}' failed`); 112 | log("Setting status to failure"); 113 | await reporter.setStatus("failure"); 114 | 115 | log("Posting failure comment"); 116 | await reporter.commitComment("failure"); 117 | }); 118 | 119 | job.on("error", async (error) => { 120 | log( 121 | `Job for '${taskName}' errored: ${ 122 | error && error.stack ? error.stack : error 123 | }` 124 | ); 125 | log("Setting status to error"); 126 | await reporter.setStatus("error"); 127 | 128 | log("Posting error comment"); 129 | await reporter.commitComment("error", error); 130 | }); 131 | 132 | job.on("canceled", async () => { 133 | log(`Job for '${taskName}' was canceled`); 134 | log("Setting status to canceled"); 135 | await reporter.setStatus("canceled"); 136 | 137 | log("Posting canceled comment"); 138 | await reporter.commitComment("canceled"); 139 | }); 140 | 141 | const { code } = await queue.add(job); 142 | log(`Job for '${taskName}' finished with status code ${code}`); 143 | } catch (error) { 144 | if (log == null) { 145 | log = makeLogger(`Failed event handler: `); 146 | } 147 | log( 148 | "Error in event handler: " + (error && error.stack) 149 | ? error.stack 150 | : error 151 | ); 152 | if (reporter != null) { 153 | log("Setting status to error"); 154 | await reporter.setStatus("error"); 155 | 156 | log("Posting error comment"); 157 | await reporter.commitComment("error", error); 158 | } else { 159 | log("Could not set status and post comment because reporter was null."); 160 | } 161 | } 162 | }); 163 | }: SetupEventFunction); 164 | -------------------------------------------------------------------------------- /src/events/pull-request-comment.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { SetupEventFunction } from "../create-webhook-handler"; 3 | const Job = require("../job"); 4 | const GithubReporter = require("../github-reporter"); 5 | 6 | module.exports = (function setupEvent({ 7 | webhookHandler, 8 | appContext, 9 | makeLogger, 10 | }) { 11 | webhookHandler.on("issue_comment", async ({ payload }) => { 12 | const { githubApp, queues } = appContext; 13 | // $FlowFixMe 14 | let log: (msg: string) => void; 15 | // $FlowFixMe 16 | let reporter: GithubReporter; 17 | 18 | try { 19 | const [owner, repo] = payload.repository.full_name.split("/"); 20 | const number = payload.issue.number; 21 | log = makeLogger(`${repo}/${owner} #${number}: `); 22 | 23 | const taskName = "pull-request"; 24 | 25 | log("Received a issue_comment event"); 26 | 27 | const github = await githubApp.asInstallation(payload.installation.id); 28 | const username = payload.comment.user.login; 29 | 30 | log(`Checking if ${username} has write access`); 31 | const authLevelResponse = await github.repos.reviewUserPermissionLevel({ 32 | owner, 33 | repo, 34 | username, 35 | }); 36 | 37 | const permission = authLevelResponse.data.permission; 38 | if (permission !== "admin" && permission !== "write") { 39 | log("Aborting because user does not have write access"); 40 | return; 41 | } 42 | 43 | const prResponse = await github.pullRequests.get({ 44 | owner, 45 | repo, 46 | number, 47 | }); 48 | const sha = prResponse.data.head.sha; 49 | log = makeLogger(`${repo}/${owner} #${number} ${sha}: `); 50 | 51 | if (payload.action !== "created") { 52 | log("Aborting because action was not 'created'"); 53 | return; 54 | } 55 | if (payload.comment.user.type === "Bot") { 56 | log("Aborting because user was a bot"); 57 | return; 58 | } 59 | 60 | const matches = payload.comment.body.match( 61 | /quin+c[eyi]+.* (?:re)?(?:run|test)/i 62 | ); 63 | if (!matches) { 64 | log("Aborting because comment body did not request a CI run"); 65 | return; 66 | } 67 | 68 | const job = new Job({ 69 | taskName, 70 | commitSha: sha, 71 | remote: prResponse.data.head.repo.ssh_url, 72 | }); 73 | 74 | reporter = new GithubReporter({ 75 | appContext, 76 | githubApp, 77 | installationId: payload.installation.id, 78 | owner, 79 | repo, 80 | sha, 81 | number, 82 | job, 83 | }); 84 | 85 | const queue = queues.getQueueForTaskName(taskName); 86 | log(`Queue concurrency for '${taskName}' is ${queue.getConcurrency()}.`); 87 | log( 88 | `There are ${queue.getRunning()} job(s) running in the '${taskName}' queue.` 89 | ); 90 | log( 91 | `There are ${queue.getWaiting()} job(s) waiting in the '${taskName}' queue.` 92 | ); 93 | 94 | if (!queue.canRunNow()) { 95 | log("Setting status to waiting"); 96 | await reporter.setStatus("waiting"); 97 | 98 | log("Posting waiting comment"); 99 | await reporter.issueComment("waiting"); 100 | } 101 | 102 | job.on("running", async () => { 103 | log(`Running job for '${taskName}'`); 104 | log("Setting status to running"); 105 | await reporter.setStatus("running"); 106 | 107 | log("Posting running comment"); 108 | await reporter.issueComment("running"); 109 | }); 110 | 111 | job.on("success", async () => { 112 | log(`Job for '${taskName}' succeeded`); 113 | log("Setting status to success"); 114 | await reporter.setStatus("success"); 115 | 116 | log("Posting success comment"); 117 | await reporter.issueComment("success"); 118 | }); 119 | 120 | job.on("failure", async () => { 121 | log(`Job for '${taskName}' failed`); 122 | log("Setting status to failure"); 123 | await reporter.setStatus("failure"); 124 | 125 | log("Posting failure comment"); 126 | await reporter.issueComment("failure"); 127 | }); 128 | 129 | job.on("error", async (error) => { 130 | log( 131 | `Job for '${taskName}' errored: ${ 132 | error && error.stack ? error.stack : error 133 | }` 134 | ); 135 | log("Setting status to error"); 136 | await reporter.setStatus("error"); 137 | 138 | log("Posting error comment"); 139 | await reporter.issueComment("error", error); 140 | }); 141 | 142 | job.on("canceled", async () => { 143 | log(`Job for '${taskName}' was canceled`); 144 | log("Setting status to canceled"); 145 | await reporter.setStatus("canceled"); 146 | 147 | log("Posting canceled comment"); 148 | await reporter.issueComment("canceled"); 149 | }); 150 | 151 | const { code } = await queue.add(job); 152 | log(`Job for '${taskName}' finished with status code ${code}`); 153 | } catch (error) { 154 | if (log == null) { 155 | log = makeLogger(`Failed event handler: `); 156 | } 157 | log( 158 | "Error in event handler: " + (error && error.stack) 159 | ? error.stack 160 | : error 161 | ); 162 | if (reporter != null) { 163 | log("Setting status to error"); 164 | await reporter.setStatus("error"); 165 | 166 | log("Posting error comment"); 167 | await reporter.issueComment("error", error); 168 | } else { 169 | log("Could not set status and post comment because reporter was null."); 170 | } 171 | } 172 | }); 173 | }: SetupEventFunction); 174 | -------------------------------------------------------------------------------- /src/events/pull-request.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { SetupEventFunction } from "../create-webhook-handler"; 3 | const Job = require("../job"); 4 | const GithubReporter = require("../github-reporter"); 5 | 6 | module.exports = (function setupEvent({ 7 | webhookHandler, 8 | appContext, 9 | makeLogger, 10 | }) { 11 | webhookHandler.on("pull_request", async ({ payload }) => { 12 | const { githubApp, queues } = appContext; 13 | // $FlowFixMe 14 | let log: (msg: string) => void; 15 | // $FlowFixMe 16 | let reporter: GithubReporter; 17 | 18 | try { 19 | const [owner, repo] = payload.repository.full_name.split("/"); 20 | const sha = payload.pull_request.head.sha; 21 | const number = payload.number; 22 | log = makeLogger(`${repo}/${owner} #${number} ${sha}: `); 23 | const taskName = "pull-request"; 24 | 25 | log("Received a pull_request event"); 26 | 27 | if (payload.action !== "synchronize" && payload.action !== "opened") { 28 | log("Aborting because action was not 'synchronize' or 'opened'"); 29 | return; 30 | } 31 | 32 | const github = await githubApp.asInstallation(payload.installation.id); 33 | 34 | const username = payload.sender.login; 35 | log(`Checking if ${username} has write access`); 36 | const authLevelResponse = await github.repos.reviewUserPermissionLevel({ 37 | owner, 38 | repo, 39 | username, 40 | }); 41 | 42 | const permission = authLevelResponse.data.permission; 43 | if (permission !== "admin" && permission !== "write") { 44 | log("Aborting because user does not have write access"); 45 | return; 46 | } 47 | 48 | const job = new Job({ 49 | taskName, 50 | commitSha: sha, 51 | remote: payload.pull_request.head.repo.ssh_url, 52 | }); 53 | 54 | reporter = new GithubReporter({ 55 | appContext, 56 | githubApp, 57 | installationId: payload.installation.id, 58 | owner, 59 | repo, 60 | sha, 61 | number, 62 | job, 63 | }); 64 | 65 | const queue = queues.getQueueForTaskName(taskName); 66 | log(`Queue concurrency for '${taskName}' is ${queue.getConcurrency()}.`); 67 | log( 68 | `There are ${queue.getRunning()} job(s) running in the '${taskName}' queue.` 69 | ); 70 | log( 71 | `There are ${queue.getWaiting()} job(s) waiting in the '${taskName}' queue.` 72 | ); 73 | 74 | if (!queue.canRunNow()) { 75 | log("Setting status to waiting"); 76 | await reporter.setStatus("waiting"); 77 | 78 | log("Posting waiting comment"); 79 | await reporter.issueComment("waiting"); 80 | } 81 | 82 | job.on("running", async () => { 83 | log(`Running job for '${taskName}'`); 84 | log("Setting status to running"); 85 | await reporter.setStatus("running"); 86 | 87 | log("Posting running comment"); 88 | await reporter.issueComment("running"); 89 | }); 90 | 91 | job.on("success", async () => { 92 | log(`Job for '${taskName}' succeeded`); 93 | log("Setting status to success"); 94 | await reporter.setStatus("success"); 95 | 96 | log("Posting success comment"); 97 | await reporter.issueComment("success"); 98 | }); 99 | 100 | job.on("failure", async () => { 101 | log(`Job for '${taskName}' failed`); 102 | log("Setting status to failure"); 103 | await reporter.setStatus("failure"); 104 | 105 | log("Posting failure comment"); 106 | await reporter.issueComment("failure"); 107 | }); 108 | 109 | job.on("error", async (error) => { 110 | log( 111 | `Job for '${taskName}' errored: ${ 112 | error && error.stack ? error.stack : error 113 | }` 114 | ); 115 | log("Setting status to error"); 116 | await reporter.setStatus("error"); 117 | 118 | await log("Posting error comment"); 119 | await reporter.issueComment("error", error); 120 | }); 121 | 122 | job.on("canceled", async () => { 123 | log(`Job for '${taskName}' was canceled`); 124 | log("Setting status to canceled"); 125 | await reporter.setStatus("canceled"); 126 | 127 | log("Posting canceled comment"); 128 | await reporter.issueComment("canceled"); 129 | }); 130 | 131 | const { code } = await queue.add(job); 132 | log(`Job for '${taskName}' finished with status code ${code}`); 133 | } catch (error) { 134 | if (log == null) { 135 | log = makeLogger(`Failed event handler: `); 136 | } 137 | log( 138 | "Error in event handler: " + (error && error.stack) 139 | ? error.stack 140 | : error 141 | ); 142 | if (reporter != null) { 143 | log("Setting status to error"); 144 | await reporter.setStatus("error"); 145 | 146 | log("Posting error comment"); 147 | await reporter.issueComment("error", error); 148 | } else { 149 | log("Could not set status and post comment because reporter was null."); 150 | } 151 | } 152 | }); 153 | }: SetupEventFunction); 154 | -------------------------------------------------------------------------------- /src/events/push-to-named-branch.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { SetupEventFunction } from "../create-webhook-handler"; 3 | const Job = require("../job"); 4 | const GithubReporter = require("../github-reporter"); 5 | 6 | module.exports = (branchName: string) => 7 | (function setupEvent({ webhookHandler, appContext, makeLogger }) { 8 | webhookHandler.on("push", async (event) => { 9 | const { githubApp, queues } = appContext; 10 | // $FlowFixMe 11 | let log: (msg: string) => void; 12 | // $FlowFixMe 13 | let reporter: GithubReporter; 14 | 15 | try { 16 | const { payload } = event; 17 | const [owner, repo] = payload.repository.full_name.split("/"); 18 | const sha = payload.after; 19 | log = makeLogger(`${repo}/${owner} ${sha}: `); 20 | 21 | const taskName = branchName; 22 | 23 | log("Received a push event"); 24 | 25 | if (payload.ref !== `refs/heads/${branchName}`) { 26 | log(`Aborting because the push was not to ${branchName}`); 27 | return; 28 | } 29 | 30 | const job = new Job({ 31 | taskName, 32 | commitSha: sha, 33 | remote: payload.repository.ssh_url, 34 | }); 35 | 36 | reporter = new GithubReporter({ 37 | appContext, 38 | githubApp, 39 | installationId: payload.installation.id, 40 | owner, 41 | repo, 42 | sha, 43 | job, 44 | }); 45 | 46 | const queue = queues.getQueueForTaskName(taskName); 47 | log( 48 | `Queue concurrency for '${taskName}' is ${queue.getConcurrency()}.` 49 | ); 50 | log( 51 | `There are ${queue.getRunning()} job(s) running in the '${taskName}' queue.` 52 | ); 53 | log( 54 | `There are ${queue.getWaiting()} job(s) waiting in the '${taskName}' queue.` 55 | ); 56 | 57 | if (!queue.canRunNow()) { 58 | log("Setting status to waiting"); 59 | await reporter.setStatus("waiting"); 60 | } 61 | 62 | job.on("running", async () => { 63 | log(`Running job for '${taskName}'`); 64 | log("Setting status to running"); 65 | await reporter.setStatus("running"); 66 | }); 67 | 68 | job.on("success", async () => { 69 | log(`Job for '${taskName}' succeeded`); 70 | log("Setting status to success"); 71 | await reporter.setStatus("success"); 72 | }); 73 | 74 | job.on("failure", async () => { 75 | log(`Job for '${taskName}' failed`); 76 | log("Setting status to failure"); 77 | await reporter.setStatus("failure"); 78 | 79 | log("Posting failure comment"); 80 | await reporter.commitComment("failure"); 81 | }); 82 | 83 | job.on("error", async (error) => { 84 | log( 85 | `Job for '${taskName}' errored: ${ 86 | error && error.stack ? error.stack : error 87 | }` 88 | ); 89 | log("Setting status to error"); 90 | await reporter.setStatus("error"); 91 | 92 | log("Posting error comment"); 93 | await reporter.commitComment("error", error); 94 | }); 95 | 96 | job.on("canceled", async () => { 97 | log(`Job for '${taskName}' was canceled`); 98 | log("Setting status to canceled"); 99 | await reporter.setStatus("canceled"); 100 | 101 | log("Posting canceled comment"); 102 | await reporter.commitComment("canceled"); 103 | }); 104 | 105 | const { code } = await queue.add(job); 106 | log(`Job ${taskName} finished with status code ${code}`); 107 | } catch (error) { 108 | if (log == null) { 109 | log = makeLogger(`Failed event handler: `); 110 | } 111 | log( 112 | "Error in event handler: " + (error && error.stack) 113 | ? error.stack 114 | : error 115 | ); 116 | if (reporter != null) { 117 | log("Setting status to error"); 118 | await reporter.setStatus("error"); 119 | 120 | log("Posting error comment"); 121 | await reporter.commitComment("error", error); 122 | } else { 123 | log( 124 | "Could not set status and post comment because reporter was null." 125 | ); 126 | } 127 | } 128 | }); 129 | }: SetupEventFunction); 130 | -------------------------------------------------------------------------------- /src/github-reporter.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { GithubApp } from "./create-github-app"; 3 | const commentTemplates = require("./comment-templates"); 4 | const Job = require("./job"); 5 | const AppContext = require("./app-context"); 6 | const routeHelpers = require("./web-ui/route-helpers"); 7 | 8 | type ResultStatus = 9 | | "waiting" 10 | | "running" 11 | | "success" 12 | | "failure" 13 | | "error" 14 | | "canceled"; 15 | 16 | module.exports = class GithubReporter { 17 | appContext: AppContext; 18 | githubApp: GithubApp; 19 | installationId: string; 20 | owner: string; 21 | repo: string; 22 | sha: string; 23 | number: ?string; 24 | job: Job; 25 | 26 | constructor({ 27 | appContext, 28 | githubApp, 29 | installationId, 30 | owner, 31 | repo, 32 | sha, 33 | number, 34 | job, 35 | }: { 36 | appContext: AppContext, 37 | githubApp: GithubApp, 38 | installationId: string, 39 | owner: string, 40 | repo: string, 41 | sha: string, 42 | number?: ?string, 43 | job: Job, 44 | }) { 45 | this.appContext = appContext; 46 | this.githubApp = githubApp; 47 | this.installationId = installationId; 48 | this.owner = owner; 49 | this.repo = repo; 50 | this.sha = sha; 51 | this.number = number; 52 | this.job = job; 53 | } 54 | 55 | async setStatus(status: ResultStatus): Promise { 56 | const { 57 | appContext, 58 | githubApp, 59 | installationId, 60 | owner, 61 | repo, 62 | sha, 63 | job, 64 | } = this; 65 | 66 | const stateForStatus = { 67 | waiting: "pending", 68 | running: "pending", 69 | success: "success", 70 | failure: "failure", 71 | error: "error", 72 | canceled: "failure", 73 | }[status]; 74 | const descriptionForStatus = { 75 | waiting: `quinCI - '${job.taskName}' waiting in queue`, 76 | running: `quinCI - '${job.taskName}' running`, 77 | success: `quinCI - '${job.taskName}' ran successfully`, 78 | failure: `quinCI - '${job.taskName}' failed`, 79 | error: `quinCI - '${job.taskName}' errored`, 80 | canceled: `quinCI - '${job.taskName}' was canceled`, 81 | }[status]; 82 | 83 | if (stateForStatus == null || descriptionForStatus == null) { 84 | return Promise.reject(new Error("Invalid status provided: " + status)); 85 | } 86 | 87 | const github = await githubApp.asInstallation(installationId); 88 | return github.repos.createStatus({ 89 | owner, 90 | repo, 91 | sha, 92 | state: stateForStatus, 93 | description: descriptionForStatus, 94 | context: `quinci:${job.taskName}`, 95 | target_url: routeHelpers.urlFor.jobStatus(appContext.config, job), 96 | }); 97 | } 98 | 99 | _commentContent(result: ResultStatus, error?: Error): string { 100 | const { job } = this; 101 | if (result === "error") { 102 | return commentTemplates.error(job.taskName, error || job.error); 103 | } else { 104 | return commentTemplates[result](job); 105 | } 106 | } 107 | 108 | async commitComment(result: ResultStatus, error?: Error): Promise { 109 | const { githubApp, installationId, owner, repo, sha } = this; 110 | const body = this._commentContent(result, error); 111 | const github = await githubApp.asInstallation(installationId); 112 | await github.repos.createCommitComment({ 113 | owner, 114 | repo, 115 | sha, 116 | body, 117 | }); 118 | } 119 | 120 | async issueComment(result: ResultStatus, error?: Error): Promise { 121 | const { githubApp, installationId, owner, repo, number } = this; 122 | const body = this._commentContent(result, error); 123 | const github = await githubApp.asInstallation(installationId); 124 | await github.issues.createComment({ 125 | owner, 126 | repo, 127 | number, 128 | body, 129 | }); 130 | } 131 | }; 132 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { NormalizedConfig } from "./normalize-config"; 3 | 4 | const http = require("http"); 5 | const AppContext = require("./app-context"); 6 | const createHttpMiddleware = require("./create-http-middleware"); 7 | 8 | module.exports = function runQuinCI(config: NormalizedConfig): Promise { 9 | const appContext = new AppContext(config); 10 | const httpMiddleware = createHttpMiddleware(appContext); 11 | 12 | return new Promise((resolve) => { 13 | const server = http.createServer(httpMiddleware); 14 | // $FlowFixMe 15 | server.listen(config.port, resolve); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /src/job.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const EventEmitter = require("events"); 3 | const onExit = require("signal-exit"); 4 | const spawn = require("cross-spawn"); 5 | const shell = require("shelljs"); 6 | const uid = require("uid"); 7 | 8 | type JobStatus = 9 | | "waiting" 10 | | "running" 11 | | "success" 12 | | "failure" 13 | | "error" 14 | | "canceled"; 15 | 16 | export type JobRunResult = { 17 | code: number, 18 | stdout: string, 19 | stderr: string, 20 | output: string, 21 | }; 22 | 23 | const runningChildren = new Set(); 24 | 25 | onExit(() => { 26 | for (let child of runningChildren) { 27 | child.kill("SIGTERM"); 28 | } 29 | }); 30 | 31 | // A Job represents a task to be run for a given git commit. 32 | // 33 | // It is constructed with a Git remote URL, a commit sha, and the name of a job 34 | // to execute. When you call its `run` method, it will clone the repo at that 35 | // URL, cd into the repo, check out the commit sha, and then execute 36 | // `./quinci/`. 37 | // 38 | // A Job is also an EventEmitter; it emits the following events when its status 39 | // changes: 40 | // 41 | // `running` - emitted when the job starts running 42 | // `success` - emitted when the job finishes running and it ran successfully 43 | // (zero exit code). 44 | // `failure` - emitted when the job finishes running and it failed 45 | // (nonzero exit code). 46 | // `error` - emitted when a JavaScript exception is thrown during job execution. 47 | // The error is passed to the event listener callback. 48 | // `canceled` - emitted when someone calls the `cancel()` method on the job. 49 | // 50 | // At any time, you can check a job's `runResult` property for information 51 | // about the job. 52 | module.exports = class Job extends EventEmitter { 53 | // Every job has a uid, which is universally unique and can be used to find 54 | // the job (See `Queues#getAllJobsByUid()`). 55 | uid: string; 56 | 57 | // The git remote url that should be cloned. 58 | remote: string; 59 | 60 | // The git commit sha that should be checked out. 61 | commitSha: string; 62 | 63 | // The name of the binary in the `quinci` folder in the repo that should be 64 | // executed. 65 | taskName: string; 66 | 67 | status: JobStatus; 68 | runResult: JobRunResult; 69 | createdAt: Date; 70 | startedAt: ?Date; 71 | finishedAt: ?Date; 72 | +error: ?Error; 73 | 74 | // Call this to cancel the job. 75 | cancel: () => void; 76 | _canceled: boolean; 77 | 78 | constructor({ 79 | remote, 80 | commitSha, 81 | taskName, 82 | }: { 83 | remote: string, 84 | commitSha: string, 85 | taskName: string, 86 | }) { 87 | super(); 88 | this.uid = uid(); 89 | this.remote = remote; 90 | this.commitSha = commitSha; 91 | this.taskName = taskName; 92 | this.status = "waiting"; 93 | this.runResult = { 94 | code: -1, 95 | stdout: "", 96 | stderr: "", 97 | output: "", 98 | }; 99 | this.createdAt = new Date(); 100 | this.startedAt = null; 101 | this.finishedAt = null; 102 | this.error = null; 103 | 104 | this.cancel = () => { 105 | this._canceled = true; 106 | this._setStatus("canceled"); 107 | }; 108 | this._canceled = false; 109 | } 110 | 111 | _setStatus(newStatus: JobStatus, maybeError?: Error) { 112 | this.status = newStatus; 113 | this.emit(newStatus, maybeError); 114 | } 115 | 116 | on(event: string, callback: Function) { 117 | super.on(event, async () => { 118 | try { 119 | await callback(); 120 | } catch (error) { 121 | console.error( 122 | `Error thrown from job event handler for '${event}': ${ 123 | error && error.stack ? error.stack : error 124 | }` 125 | ); 126 | } 127 | }); 128 | // $FlowFixMe: Doesn't like this and I dunno why and I don't care why 129 | return this; 130 | } 131 | 132 | run(): Promise { 133 | if (this._canceled) { 134 | return Promise.resolve(this.runResult); 135 | } 136 | 137 | const { remote, commitSha, taskName } = this; 138 | const now = Date.now(); 139 | const jobDir = `jobs/${taskName}/${commitSha}`; 140 | const runDir = `${jobDir}/${now}`; 141 | const logFile = `${runDir}/quinci-log.txt`; 142 | 143 | shell.mkdir("-p", runDir); 144 | this.startedAt = new Date(); 145 | const child: child_process$ChildProcess = spawn( 146 | "sh", 147 | [ 148 | "-c", 149 | `git clone --quiet ${remote} ${commitSha} && ` + 150 | `cd ${commitSha} && ` + 151 | `git checkout --quiet ${commitSha} && ` + 152 | `./quinci/${taskName}`, 153 | ], 154 | { 155 | cwd: jobDir, 156 | env: { 157 | ...process.env, 158 | CI: "true", 159 | QUINCI_REMOTE: remote, 160 | QUINCI_TASK_NAME: taskName, 161 | QUINCI_COMMIT_SHA: commitSha, 162 | QUINCI_RUN_DIR: runDir, 163 | QUINCI_LOG_FILE: logFile, 164 | QUINCI_JOB_UID: this.uid, 165 | }, 166 | } 167 | ); 168 | runningChildren.add(child); 169 | this._setStatus("running"); 170 | 171 | return new Promise((resolve, reject) => { 172 | this.cancel = () => { 173 | this._canceled = true; 174 | child.kill("SIGKILL"); 175 | shell.rm("-rf", jobDir); 176 | this._setStatus("canceled"); 177 | resolve(this.runResult); 178 | }; 179 | 180 | child.stdout.on("data", (data) => { 181 | if (this._canceled) { 182 | return; 183 | } 184 | const dataAsString = data.toString("utf-8"); 185 | this.runResult.stdout += dataAsString; 186 | this.runResult.output += dataAsString; 187 | shell.echo(dataAsString).toEnd(logFile); 188 | }); 189 | child.stderr.on("data", (data) => { 190 | if (this._canceled) { 191 | return; 192 | } 193 | const dataAsString = data.toString("utf-8"); 194 | this.runResult.stderr += dataAsString; 195 | this.runResult.output += dataAsString; 196 | shell.echo(dataAsString).toEnd(logFile); 197 | }); 198 | 199 | child.on("error", (err) => { 200 | // $FlowFixMe 201 | this.error = err; 202 | if (this._canceled) { 203 | return; 204 | } 205 | runningChildren.delete(child); 206 | this.finishedAt = new Date(); 207 | reject(err); 208 | }); 209 | 210 | child.on("close", (code) => { 211 | if (this._canceled) { 212 | return; 213 | } 214 | runningChildren.delete(child); 215 | this.finishedAt = new Date(); 216 | this.runResult.code = code; 217 | if (code === 0) { 218 | this._setStatus("success"); 219 | } else { 220 | this._setStatus("failure"); 221 | } 222 | shell.rm("-rf", jobDir); 223 | resolve(this.runResult); 224 | }); 225 | }).catch((err) => { 226 | this._setStatus("error", err); 227 | throw err; 228 | }); 229 | } 230 | }; 231 | -------------------------------------------------------------------------------- /src/job.shim.js: -------------------------------------------------------------------------------- 1 | const EventEmitter = require("events"); 2 | const uid = require("uid"); 3 | 4 | function makeSha() { 5 | let str = ""; 6 | while (str.length < 40) { 7 | str += Math.random() 8 | .toString(16) 9 | .replace(/[^a-z0-9]+/g, ""); 10 | } 11 | return str.slice(0, 40); 12 | } 13 | 14 | module.exports = class JobShim extends EventEmitter { 15 | constructor(attrs) { 16 | super(); 17 | this.uid = uid(); 18 | this.remote = attrs.remote || "git@github.com:user/repo.git"; 19 | this.commitSha = attrs.commitSha || makeSha(); 20 | this.taskName = attrs.taskName || ""; 21 | this.status = "waiting"; 22 | const defaultRunResult = { 23 | code: -1, 24 | stdout: "", 25 | stderr: "", 26 | output: "", 27 | }; 28 | this.createdAt = new Date(); 29 | 30 | Object.assign(this, attrs); 31 | if (attrs.runResult != null) { 32 | this.runResult = { ...defaultRunResult, ...attrs.runResult }; 33 | } else { 34 | this.runResult = defaultRunResult; 35 | } 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /src/normalize-config.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export type InputConfig = { 3 | appId: number, 4 | appCert: string, 5 | webhookSecretFile: string, 6 | port: number, 7 | queueConcurrency: ?(string | { [taskName: string]: number }), 8 | ["webURL" | "webUrl"]: string, 9 | namedBranches: string | Array, 10 | }; 11 | 12 | export type NormalizedConfig = {| 13 | appId: number, 14 | appCert: string, 15 | webhookSecretFile: string, 16 | port: number, 17 | queueConcurrency: { [taskName: string]: number }, 18 | webURL: string, 19 | namedBranches: Array, 20 | |}; 21 | 22 | function invalidFormatError() { 23 | return new Error( 24 | "Invalid queue concurrency string format. Valid format is eg. master=1,pull-request=3" 25 | ); 26 | } 27 | 28 | const defaultQueueConcurrency = { 29 | master: 1, 30 | main: 1, 31 | "pull-request": 3, 32 | }; 33 | 34 | function parseQueueConcurrencyString(configStr: string) { 35 | let queueConcurrencyObject = { ...defaultQueueConcurrency }; 36 | 37 | if (configStr) { 38 | try { 39 | configStr.split(",").forEach((entry) => { 40 | const [taskName, concurrency] = entry.split("="); 41 | let parsedConcurrency; 42 | if (concurrency === "Infinity") { 43 | parsedConcurrency = Infinity; 44 | } else { 45 | parsedConcurrency = parseInt(concurrency); 46 | } 47 | if (Number.isNaN(parsedConcurrency)) { 48 | throw invalidFormatError(); 49 | } else { 50 | queueConcurrencyObject[taskName] = parsedConcurrency; 51 | } 52 | }); 53 | } catch (err) { 54 | throw invalidFormatError(); 55 | } 56 | } 57 | 58 | return queueConcurrencyObject; 59 | } 60 | 61 | const defaultNamedBranches = ["master", "main"]; 62 | 63 | module.exports = function normalizeConfig( 64 | config: InputConfig 65 | ): NormalizedConfig { 66 | let queueConcurrency = defaultQueueConcurrency; 67 | if (typeof config.queueConcurrency === "string") { 68 | queueConcurrency = parseQueueConcurrencyString(config.queueConcurrency); 69 | } else if ( 70 | typeof config.queueConcurrency === "object" && 71 | config.queueConcurrency != null 72 | ) { 73 | queueConcurrency = config.queueConcurrency; 74 | } 75 | 76 | let namedBranches = defaultNamedBranches; 77 | if (typeof config.namedBranches === "string") { 78 | namedBranches = config.namedBranches.split(","); 79 | } else if (Array.isArray(config.namedBranches)) { 80 | namedBranches = config.namedBranches; 81 | } 82 | 83 | return { 84 | appId: config.appId, 85 | appCert: config.appCert, 86 | webhookSecretFile: config.webhookSecretFile, 87 | port: config.port, 88 | queueConcurrency, 89 | webURL: config.webURL || config.webUrl, 90 | namedBranches, 91 | }; 92 | }; 93 | -------------------------------------------------------------------------------- /src/queue.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { JobRunResult } from "./job"; 3 | const PromiseQueue = require("promise-queue"); 4 | const Job = require("./job"); 5 | 6 | const JOBS_TO_RETAIN = 100; 7 | 8 | // A single job queue; for instance, the 'pull-request' queue 9 | module.exports = class Queue { 10 | _concurrency: number; 11 | _promiseQueue: PromiseQueue; 12 | _jobs: Array; 13 | 14 | constructor(concurrency: number) { 15 | this._concurrency = concurrency; 16 | this._promiseQueue = new PromiseQueue(concurrency, Infinity); 17 | this._jobs = []; 18 | } 19 | 20 | // The max number of jobs that can run concurrently in this queue. 21 | getConcurrency(): number { 22 | return this._concurrency; 23 | } 24 | 25 | // The number of jobs that are currently running in this queue. 26 | getRunning(): number { 27 | const promiseQueue = this._promiseQueue; 28 | return promiseQueue.getPendingLength(); 29 | } 30 | 31 | // The number of jobs that are currently waiting to run in this queue. 32 | getWaiting(): number { 33 | const promiseQueue = this._promiseQueue; 34 | return promiseQueue.getQueueLength(); 35 | } 36 | 37 | // Whether a job could run immediately if it was pushed onto this queue. 38 | canRunNow(): boolean { 39 | return this.getWaiting() === 0 && this.getRunning() < this.getConcurrency(); 40 | } 41 | 42 | // All the jobs associated with this queue, whether finished, running, or unstarted. 43 | // Only the last `JOBS_TO_RETAIN` are kept. 44 | getJobs(): Array { 45 | return this._jobs; 46 | } 47 | 48 | // Add a job to the queue. It may run now, or may run at some point in the 49 | // future; use `canRunNow()` to check. 50 | add(job: Job): Promise { 51 | this._jobs.push(job); 52 | this._jobs.slice(-JOBS_TO_RETAIN); 53 | 54 | const promiseQueue = this._promiseQueue; 55 | return promiseQueue.add(() => job.run()); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /src/queue.shim.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const Job = require("./job"); 3 | 4 | // A single job queue; for instance, the 'pull-request' queue 5 | module.exports = class QueueShim { 6 | _concurrency: number; 7 | _jobs: Array; 8 | 9 | constructor(concurrency: number) { 10 | this._concurrency = concurrency; 11 | this._jobs = []; 12 | } 13 | 14 | // The max number of jobs that can run concurrently in this queue. 15 | getConcurrency(): number { 16 | return this._concurrency; 17 | } 18 | 19 | // The number of jobs that are currently running in this queue. 20 | getRunning(): number { 21 | return this._jobs.filter((job) => job.status === "running").length; 22 | } 23 | 24 | // The number of jobs that are currently waiting to run in this queue. 25 | getWaiting(): number { 26 | return this._jobs.filter((job) => job.status === "waiting").length; 27 | } 28 | 29 | // Whether a job could run immediately if it was pushed onto this queue. 30 | canRunNow(): boolean { 31 | return this.getWaiting() === 0 && this.getRunning() < this.getConcurrency(); 32 | } 33 | 34 | // All the jobs associated with this queue, whether finished, running, or unstarted. 35 | // Only the last `JOBS_TO_RETAIN` are kept. 36 | getJobs(): Array { 37 | return this._jobs; 38 | } 39 | 40 | // Add a job to the queue. It may run now, or may run at some point in the 41 | // future; use `canRunNow()` to check. 42 | add(job: Job) { 43 | this._jobs.push(job); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/queues.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { NormalizedConfig } from "./normalize-config"; 3 | const Queue = require("./queue"); 4 | const Job = require("./job"); 5 | 6 | // An object which contains all the queues in the app. 7 | module.exports = class Queues { 8 | _queuesMap: Map; 9 | 10 | constructor(config: NormalizedConfig) { 11 | this._queuesMap = new Map(); 12 | 13 | // Named branches have a default queue concurrency of 1. 14 | config.namedBranches.forEach((branchName) => { 15 | this._queuesMap.set(branchName, new Queue(1)); 16 | }); 17 | 18 | // But, they can be overridden via the queue concurrency config option. 19 | ((Object.entries(config.queueConcurrency): any): Array< 20 | [string, number] 21 | >).forEach(([taskName, concurrency]) => { 22 | // If this._queuesMap already has a queue associated with that task 23 | // (from the namedBranches default queue concurrency of 1), that 24 | // Queue object is replaced with one using the correct concurrency 25 | // value. 26 | this._queuesMap.set(taskName, new Queue(concurrency)); 27 | }); 28 | } 29 | 30 | getQueueForTaskName(taskName: string): Queue { 31 | const queue = this._queuesMap.get(taskName); 32 | if (queue) { 33 | return queue; 34 | } else { 35 | // Custom tasks (which weren't specified in the named branches) have a 36 | // queue concurrency of Infinity by default. This is a little confusing, 37 | // since named branch tasks have a concurrency of 1 by default, but 38 | // before named branches were added, the behavior was that custom tasks 39 | // had Infinity concurrency, so this preserves that behavior so we 40 | // don't need to do a breaking change. 41 | const newQueue = new Queue(Infinity); 42 | this._queuesMap.set(taskName, newQueue); 43 | return newQueue; 44 | } 45 | } 46 | 47 | getAllQueues(): Array<[string, Queue]> { 48 | return Array.from(this._queuesMap); 49 | } 50 | 51 | getAllJobsForQueues(): Array<{ taskName: string, jobs: Array }> { 52 | return Array.from(this._queuesMap).map(([taskName, queue]) => ({ 53 | taskName, 54 | jobs: queue.getJobs(), 55 | })); 56 | } 57 | 58 | getAllJobsByUid(): { [uid: string]: Job } { 59 | const jobs = {}; 60 | this._queuesMap.forEach((queue, taskName) => { 61 | queue.getJobs().forEach((job) => { 62 | jobs[job.uid] = job; 63 | }); 64 | }); 65 | return jobs; 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /src/web-ui/components/AppBar.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | 4 | type Props = { 5 | titleHref?: string, 6 | }; 7 | 8 | module.exports = class AppBar extends React.Component { 9 | render() { 10 | const { titleHref } = this.props; 11 | return ( 12 |
18 | 19 | 23 | 24 |
25 | ); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/web-ui/components/JobRunOutput.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const { TriangleRightIcon } = require("react-octicons"); 4 | const ansiUp = require("ansi_up").default; 5 | const Job = require("../../job"); 6 | const Padding = require("./Padding"); 7 | const LabelWithIcon = require("./LabelWithIcon"); 8 | 9 | const ansiUpInstance = new ansiUp(); 10 | 11 | type Props = { 12 | job: Job, 13 | isSelected: boolean, 14 | }; 15 | 16 | module.exports = class JobRunOutput extends React.Component { 17 | render() { 18 | const { job, isSelected } = this.props; 19 | 20 | const hasContent = Boolean( 21 | isSelected || job.runResult.output.trim().length > 0 || job.error 22 | ); 23 | if (!hasContent) { 24 | return null; 25 | } 26 | 27 | return ( 28 |
29 | 30 | } 34 | /> 35 | 36 | 37 |
46 |             {job.error ? (
47 |               {job.error.stack}
48 |             ) : job.runResult.output.trim().length > 0 ? (
49 |               
54 |             ) : (
55 |               {"(No output yet)"}
56 |             )}
57 |           
58 |
59 |
60 | ); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /src/web-ui/components/JobStatusItem.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const { 4 | GitCommitIcon, 5 | ClockIcon, 6 | PrimitiveDotIcon, 7 | CheckIcon, 8 | XIcon, 9 | CircleSlashIcon, 10 | WatchIcon, 11 | } = require("react-octicons"); 12 | const moment = require("moment"); 13 | const Job = require("../../job"); 14 | const Padding = require("./Padding"); 15 | const LabelWithIcon = require("./LabelWithIcon"); 16 | const JobRunOutput = require("./JobRunOutput"); 17 | const routeHelpers = require("../route-helpers"); 18 | 19 | type Props = { 20 | job: Job, 21 | isSelected: boolean, 22 | withDivider: boolean, 23 | }; 24 | 25 | const Divider = () => ( 26 |
36 | ); 37 | 38 | const capitalize = (str: string) => str[0].toUpperCase() + str.slice(1); 39 | 40 | module.exports = class JobStatusItem extends React.Component { 41 | render() { 42 | const { job, isSelected, withDivider } = this.props; 43 | 44 | const jobStatusBorderColor = { 45 | waiting: "rgb(231, 231, 231)", 46 | canceled: "rgb(231, 231, 231)", 47 | running: "rgb(255, 243, 128)", 48 | success: "rgb(135, 255, 135)", 49 | failure: "rgb(255, 151, 151)", 50 | error: "rgb(255, 151, 151)", 51 | }[job.status]; 52 | 53 | const jobStatusIconColor = { 54 | waiting: "rgb(119, 119, 119)", 55 | canceled: "rgb(119, 119, 119)", 56 | running: "rgb(227, 205, 0)", 57 | success: "rgb(0, 171, 0)", 58 | failure: "rgb(198, 0, 0)", 59 | error: "rgb(198, 0, 0)", 60 | }[job.status]; 61 | 62 | const JobStatusIcon = { 63 | waiting: ClockIcon, 64 | canceled: CircleSlashIcon, 65 | running: PrimitiveDotIcon, 66 | success: CheckIcon, 67 | failure: XIcon, 68 | error: XIcon, 69 | }[job.status]; 70 | 71 | const jobStatusLabel = { 72 | waiting: ( 73 | 74 | Waiting - Cancel 75 | 76 | ), 77 | canceled: "Canceled", 78 | running: ( 79 | 80 | Running - Cancel 81 | 82 | ), 83 | success: "Success", 84 | failure: `Failure - Exit Code: ${job.runResult.code}`, 85 | error: "Error", 86 | }[job.status]; 87 | 88 | const createdAtRelative = capitalize(moment(job.createdAt).fromNow()); 89 | let runDuration = null; 90 | if (job.startedAt != null) { 91 | const endTime = job.finishedAt ?? new Date(); 92 | runDuration = capitalize( 93 | moment.duration(job.startedAt - endTime).humanize() 94 | ); 95 | } 96 | 97 | return ( 98 |
  • 106 | 107 | 108 |

    {createdAtRelative}

    109 |
    110 | } 114 | /> 115 | } 119 | /> 120 | {runDuration ? ( 121 | } 125 | /> 126 | ) : null} 127 | 128 | 129 |
    130 | {withDivider ? : null} 131 |
  • 132 | ); 133 | } 134 | }; 135 | -------------------------------------------------------------------------------- /src/web-ui/components/LabelWithIcon.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const Padding = require("./Padding"); 4 | 5 | const LabelWithIcon = ({ 6 | label, 7 | icon, 8 | title, 9 | noMargin, 10 | }: { 11 | label: React.Node, 12 | icon: React.Node, 13 | title?: string, 14 | noMargin?: boolean, 15 | }) => ( 16 |
    23 |
    33 | {icon} 34 |
    35 | {label} 36 |
    37 | ); 38 | 39 | module.exports = LabelWithIcon; 40 | -------------------------------------------------------------------------------- /src/web-ui/components/Material.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | 4 | type Props = { 5 | children?: React.Node, 6 | style?: ?Object, 7 | tagName: string, 8 | elevation: number, 9 | }; 10 | 11 | module.exports = class Material extends React.Component { 12 | static defaultProps = { 13 | tagName: "div", 14 | elevation: 5, 15 | }; 16 | 17 | render() { 18 | const { children, style, tagName, elevation, ...attrs } = this.props; 19 | 20 | return React.createElement(tagName, { 21 | style: { 22 | borderRadius: "8px", 23 | backgroundColor: "white", 24 | boxShadow: `0 2px ${elevation}px rgba(0, 0, 0, 0.25)`, 25 | ...style, 26 | }, 27 | children, 28 | ...attrs, 29 | }); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/web-ui/components/Padding.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | 4 | type Props = { 5 | top?: number | string, 6 | right?: number | string, 7 | bottom?: number | string, 8 | left?: number | string, 9 | x?: number | string, 10 | y?: number | string, 11 | size?: number | string, 12 | children?: React.Node, 13 | tagName: string, 14 | }; 15 | 16 | module.exports = class Padding extends React.Component { 17 | static defaultProps = { 18 | tagName: "div", 19 | }; 20 | 21 | static asStyle(props: Props) {} 22 | 23 | render() { 24 | const { 25 | top, 26 | right, 27 | bottom, 28 | left, 29 | x, 30 | y, 31 | size, 32 | children, 33 | tagName: TagName, 34 | } = this.props; 35 | 36 | return ( 37 | 45 | {children} 46 | 47 | ); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /src/web-ui/components/Page.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const { default: Helmet } = require("react-helmet-async"); 4 | const AppBar = require("./AppBar"); 5 | 6 | type Props = { 7 | title?: string, 8 | children?: React.Node, 9 | }; 10 | 11 | module.exports = class Page extends React.Component { 12 | render() { 13 | const { title, children } = this.props; 14 | 15 | return ( 16 | <> 17 | 18 | {title ? {title} : null} 19 | 20 | 24 | 25 | 26 | 27 | 28 |
    34 | {children} 35 |
    36 | 37 | ); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/web-ui/components/StatusPage.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const AppContext = require("../../app-context"); 4 | const Page = require("./Page"); 5 | const JobStatusItem = require("./JobStatusItem"); 6 | const Material = require("./Material"); 7 | const Padding = require("./Padding"); 8 | const routeHelpers = require("../route-helpers"); 9 | 10 | type Props = { 11 | appContext: AppContext, 12 | selectedJobUid: ?string, 13 | }; 14 | 15 | module.exports = class StatusPage extends React.Component { 16 | render() { 17 | const { appContext, selectedJobUid } = this.props; 18 | 19 | return ( 20 | 21 | {appContext.queues.getAllQueues().map(([taskName, _]) => ( 22 | 33 | {taskName} 34 | 35 | ))} 36 | {appContext.queues.getAllJobsForQueues().map(({ taskName, jobs }) => ( 37 | 46 | 54 | 55 |

    {taskName}

    56 |
    57 |
    58 | {jobs.length > 0 ? ( 59 |
      65 | {[...jobs] 66 | .sort((job1, job2) => job2.createdAt - job1.createdAt) 67 | .map((job, index) => ( 68 | 74 | ))} 75 |
    76 | ) : ( 77 | 78 | No jobs have run in this queue yet. 79 | 80 | )} 81 |
    82 | ))} 83 |
    84 | ); 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /src/web-ui/components/StatusPage.stories.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from "react"; 3 | import { storiesOf } from "@storybook/react"; 4 | // import { action } from "@storybook/addon-actions"; 5 | // import { linkTo } from "@storybook/addon-links"; 6 | const { HelmetProvider } = require("react-helmet-async"); 7 | 8 | import StatusPage from "./StatusPage"; 9 | const AppContext = require("../../app-context"); 10 | const Job: any = require("../../job"); 11 | 12 | storiesOf("StatusPage", module).add("default", () => { 13 | const appContext = new AppContext({ 14 | appId: 12345, 15 | appCert: "/app-cert", 16 | webhookSecretFile: "/webhook-secret-file", 17 | port: 8080, 18 | queueConcurrency: { 19 | master: 1, 20 | main: 1, 21 | "pull-request": 3, 22 | }, 23 | webURL: "/", 24 | namedBranches: ["master", "main", "dev"], 25 | }); 26 | 27 | const masterQueue = appContext.queues.getQueueForTaskName("master"); 28 | masterQueue.add( 29 | new Job({ 30 | taskName: "master", 31 | status: "waiting", 32 | }) 33 | ); 34 | masterQueue.add( 35 | new Job({ 36 | taskName: "master", 37 | status: "running", 38 | runResult: { 39 | output: `[0m 40 |  Some test[0m 41 | 42 |  ✓ it works[0m (8257ms) 43 | 44 | 45 |   1 passing (8s) 46 | 47 | 48 |  (Results) 49 | 50 |  ┌────────────────────────────────────────────────┐ 51 |  │ Tests: 1 │ 52 |  │ Passing: 1 │ 53 |  │ Failing: 0 │ 54 |  │ Pending: 0 │ 55 |  │ Skipped: 0 │ 56 |  │ Screenshots: 0 │ 57 |  │ Video: false │ 58 |  │ Duration: 8 seconds │ 59 |  │ Spec Ran: some_test.js │ 60 |  └────────────────────────────────────────────────┘ 61 | 62 | 63 | ==================================================================================================== 64 | 65 |  (Run Finished) 66 | `.repeat(4), 67 | }, 68 | createdAt: new Date(Date.now() - 5 * 60 * 1000), 69 | startedAt: new Date(Date.now() - 5 * 60 * 1000), 70 | }) 71 | ); 72 | masterQueue.add( 73 | new Job({ 74 | taskName: "master", 75 | status: "canceled", 76 | createdAt: new Date(Date.now() - 6 * 60 * 1000), 77 | startedAt: new Date(Date.now() - 6 * 60 * 1000), 78 | finishedAt: new Date(Date.now() - 5.5 * 60 * 1000), 79 | runResult: { 80 | output: "Running............", 81 | }, 82 | }) 83 | ); 84 | masterQueue.add( 85 | new Job({ 86 | taskName: "master", 87 | status: "success", 88 | runResult: { 89 | code: 0, 90 | output: 91 | "\n\n\u001B[1;33;40m 33;40 \u001B[1;33;41m 33;41 \u001B[1;33;42m 33;42 \u001B[1;33;43m 33;43 \u001B[1;33;44m 33;44 \u001B[1;33;45m 33;45 \u001B[1;33;46m 33;46 \u001B[1m\u001B[0\n\n\u001B[1;33;42m >> Tests OK\n\n", 92 | }, 93 | createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000), 94 | startedAt: new Date(Date.now() - 2 * 60 * 60 * 1000), 95 | finishedAt: new Date(Date.now() - 1.78 * 60 * 60 * 1000), 96 | }) 97 | ); 98 | masterQueue.add( 99 | new Job({ 100 | taskName: "master", 101 | status: "failure", 102 | runResult: { 103 | code: 1, 104 | output: "Process was killed (Out of memory)", 105 | }, 106 | createdAt: new Date(Date.now() - 7.23 * 60 * 60 * 1000), 107 | startedAt: new Date(Date.now() - 7.23 * 60 * 60 * 1000), 108 | finishedAt: new Date(Date.now() - 7 * 60 * 60 * 1000), 109 | }) 110 | ); 111 | masterQueue.add( 112 | new Job({ 113 | taskName: "master", 114 | status: "error", 115 | runResult: { 116 | code: -1, 117 | output: "", 118 | }, 119 | error: new Error("storybook demo error"), 120 | createdAt: new Date(Date.now() - 26 * 60 * 60 * 1000), 121 | startedAt: new Date(Date.now() - 25 * 60 * 60 * 1000), 122 | finishedAt: new Date(Date.now() - 24.9 * 60 * 60 * 1000), 123 | }) 124 | ); 125 | 126 | return ( 127 | 128 | 129 | 130 | ); 131 | }); 132 | -------------------------------------------------------------------------------- /src/web-ui/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const path = require("path"); 3 | const express = require("express"); 4 | const statusPage = require("./routes/status-page"); 5 | const cancelJob = require("./routes/cancel-job"); 6 | 7 | const app = express(); 8 | 9 | app.get("/", statusPage); 10 | app.get("/cancel", cancelJob); 11 | app.use( 12 | "/assets", 13 | express.static(path.resolve(__dirname, "..", "..", "assets")) 14 | ); 15 | 16 | module.exports = app; 17 | -------------------------------------------------------------------------------- /src/web-ui/render-react.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const React = require("react"); 3 | const ReactDOMServer = require("react-dom/server"); 4 | const { HelmetProvider } = require("react-helmet-async"); 5 | 6 | module.exports = function renderReact(element: React.Element): string { 7 | const helmetContext = {}; 8 | const reactMarkup = ReactDOMServer.renderToString( 9 | {element} 10 | ); 11 | const { helmet } = helmetContext; 12 | 13 | return ` 14 | 15 | 16 | 17 | ${helmet.title.toString()} 18 | ${helmet.meta.toString()} 19 | ${helmet.link.toString()} 20 | 21 | 22 |
    23 | ${reactMarkup} 24 |
    25 | 26 | 27 | `; 28 | }; 29 | -------------------------------------------------------------------------------- /src/web-ui/route-helpers.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { NormalizedConfig } from "../normalize-config"; 3 | 4 | const Job = require("../job"); 5 | 6 | const pathFor = { 7 | jobStatus(job: Job): string { 8 | return `/?${job.uid}#job-${job.uid}`; 9 | }, 10 | cancelJob(job: Job): string { 11 | return `/cancel?jobId=${job.uid}`; 12 | }, 13 | queue(taskName: string): string { 14 | return `/#queue-${taskName}`; 15 | }, 16 | }; 17 | 18 | const urlFor = { 19 | jobStatus(config: NormalizedConfig, job: Job): string { 20 | return `${config.webURL}${pathFor.jobStatus(job)}`; 21 | }, 22 | cancelJob(config: NormalizedConfig, job: Job): string { 23 | return `${config.webURL}${pathFor.cancelJob(job)}`; 24 | }, 25 | queue(config: NormalizedConfig, taskName: string): string { 26 | return `${config.webURL}${pathFor.queue(taskName)}`; 27 | }, 28 | }; 29 | 30 | module.exports = { pathFor, urlFor }; 31 | -------------------------------------------------------------------------------- /src/web-ui/routes/cancel-job.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { HTTPRequest, HTTPResponse } from "../../create-http-middleware"; 3 | 4 | module.exports = function cancelJob(req: HTTPRequest, res: HTTPResponse) { 5 | const jobId = req.query.jobId; 6 | 7 | if (jobId == null) { 8 | res.statusCode = 400; 9 | res.write("Cancel job failed: missing jobId query param"); 10 | res.end(); 11 | return; 12 | } 13 | 14 | if (Array.isArray(jobId)) { 15 | res.statusCode = 400; 16 | res.write("Cancel job failed: Invalid jobId"); 17 | res.end(); 18 | return; 19 | } 20 | 21 | const jobs = req.appContext.queues.getAllJobsByUid(); 22 | const job = jobs[jobId]; 23 | 24 | if (job == null) { 25 | res.statusCode = 400; 26 | res.write("Cancel job failed: Invalid jobId"); 27 | res.end(); 28 | return; 29 | } 30 | 31 | try { 32 | job.cancel(); 33 | res.writeHead(302, { 34 | Location: "/", 35 | }); 36 | res.end(); 37 | } catch (err) { 38 | res.statusCode = 500; 39 | res.write("Cancel job failed: Internal server error"); 40 | res.end(); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /src/web-ui/routes/status-page.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { HTTPRequest, HTTPResponse } from "../../create-http-middleware"; 3 | const url = require("url"); 4 | const React = require("react"); 5 | const renderReact = require("../render-react"); 6 | const StatusPage = require("./../components/StatusPage"); 7 | 8 | module.exports = function statusPage(req: HTTPRequest, res: HTTPResponse) { 9 | const urlObj = url.parse(req.url); 10 | const selectedJobUid = urlObj.query; 11 | 12 | res.statusCode = 200; 13 | const html = renderReact( 14 | 15 | ); 16 | res.write(html); 17 | res.end(); 18 | }; 19 | -------------------------------------------------------------------------------- /web-ui-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suchipi/quinci/c7b3ff707d77bad5246a4c8712026362d2ad9af6/web-ui-screenshot.png --------------------------------------------------------------------------------