├── .env.example ├── .eslintignore ├── .eslintrc.yml ├── .flowconfig ├── .github ├── ReplyRef.md └── duplicate.md ├── .gitignore ├── .prettierrc.yml ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── __tests__ └── index.test.js ├── app.json ├── docs ├── deploy.md ├── logo.png └── logo.svg ├── flow-typed ├── npm │ ├── jest_v21.x.x.js │ ├── minimist_v1.x.x.js │ └── ramda_v0.x.x.js └── src │ └── index.flow.js ├── jobs └── deploy-heroku.sh ├── package.json ├── src ├── index.js ├── templates │ ├── dialog.md │ ├── duplicate.md │ ├── feature.md │ ├── issue.md │ └── pr.md ├── utils │ ├── __tests__ │ │ └── template.test.js │ ├── ghAPI.js │ ├── handlebars.js │ └── template.js └── webhookHandler.js └── yarn.lock /.env.example: -------------------------------------------------------------------------------- 1 | # The ID of your GitHub App 2 | APP_ID= 3 | WEBHOOK_SECRET=development 4 | # PRIVATE_KEY_PATH= 5 | 6 | # Uncomment this to get verbose logging 7 | # LOG_LEVEL=trace # or `info` to show less 8 | 9 | # Subdomain to use for localtunnel server. Defaults to your local username. 10 | # SUBDOMAIN= 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /flow-typed 4 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | --- 2 | root: true 3 | env: 4 | browser: true 5 | commonjs: true 6 | es6: true 7 | node: true 8 | globals: 9 | describe: true # jest 10 | test: true # jest 11 | expect: true # jest 12 | extends: 13 | - 'eslint:recommended' 14 | plugins: 15 | - prettier 16 | parserOptions: 17 | ecmaVersion: 8 18 | sourceType: module 19 | ecmaFeatures: 20 | experimentalObjectRestSpread: true 21 | rules: 22 | prettier/prettier: 23 | - off 24 | no-console: off 25 | no-unused-vars: 26 | - warn 27 | - vars: all 28 | args: after-used 29 | comma-dangle: 30 | - error 31 | - arrays: always-multiline 32 | objects: always-multiline 33 | functions: never 34 | indent: 35 | - error 36 | - 2 37 | linebreak-style: 38 | - error 39 | - unix 40 | quotes: 41 | - warn 42 | - single 43 | semi: 44 | - error 45 | - never 46 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | 11 | [strict] 12 | -------------------------------------------------------------------------------- /.github/ReplyRef.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | This is related to #{{ n }} 4 | -------------------------------------------------------------------------------- /.github/duplicate.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 😢 This is duplicate of #{{ num }}. 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | *.pem 4 | .env 5 | package-lock.json 6 | yarn.lock 7 | coverage 8 | -------------------------------------------------------------------------------- /.prettierrc.yml: -------------------------------------------------------------------------------- 1 | semi: false 2 | singleQuote: true 3 | trailingComma: es5 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | 5 | node_js: 6 | - "10" 7 | 8 | branches: 9 | only: 10 | - master 11 | 12 | script: 13 | - yarn run lint 14 | - yarn run test 15 | 16 | notifications: 17 | email: 18 | recipients: 19 | - liuderchi@gmail.com 20 | on_success: never 21 | on_failure: change 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## CHANGELOG 2 | 3 | ### upcoming (2018/02/22 09:23 +00:00) 4 | - [#14](https://github.com/liuderchi/gh-template-bot/pull/14) chore(packageJson): yarn add request@latest (@liuderchi) 5 | - [0251fc1](https://github.com/liuderchi/gh-template-bot/commit/0251fc1d3daf0b404ebdffeb36c83a817f6064be) chore(packageJson): yarn add request@latest (@liuderchi) 6 | - [#13](https://github.com/liuderchi/gh-template-bot/pull/13) Update Changelog (@liuderchi) 7 | - [79bf37b](https://github.com/liuderchi/gh-template-bot/commit/79bf37b55ece72050719eee42def772e526c721e) docs(changelog): update changelog (@liuderchi) 8 | - [#12](https://github.com/liuderchi/gh-template-bot/pull/12) Introduce codecov (@liuderchi) 9 | - [61fc75f](https://github.com/liuderchi/gh-template-bot/commit/61fc75f29a3bd7e0e36bb4f8a37f63c895b8edb1) chore(codecov, packagejson): introduce codecov (@liuderchi) 10 | - [#11](https://github.com/liuderchi/gh-template-bot/pull/11) Introduce Flow and Flowtype (@liuderchi) 11 | - [954f860](https://github.com/liuderchi/gh-template-bot/commit/954f860cb5f044ec37398c1dc9707eabe0898632) chore(flow): add flow type for utils/template .js (@liuderchi) 12 | - [3eb9334](https://github.com/liuderchi/gh-template-bot/commit/3eb93342368d95acad10b5e5a1838803a6dcd680) chore(flowtyped): add flow type for npm dependencies (@liuderchi) 13 | - [ee88b48](https://github.com/liuderchi/gh-template-bot/commit/ee88b4816fdb711cf85912701b4b6879c85911c8) chore(flow): add flow type for webhookHandler.js (@liuderchi) 14 | - [2808942](https://github.com/liuderchi/gh-template-bot/commit/2808942a7fe2ab5af4f61469693b065dc3575354) chore(flow): add flow notation (@liuderchi) 15 | - [207a5c2](https://github.com/liuderchi/gh-template-bot/commit/207a5c21ddd7fb3f0af1db281beefbcd283851b0) chore(flow): move type def in flow-typed/index.flow.js (@liuderchi) 16 | - [5e1b846](https://github.com/liuderchi/gh-template-bot/commit/5e1b84639aa239aa129a1bc98b8b0dbc9f70881a) chore(packagejson, travis): add flow, lint scripts, update travis config (@liuderchi) 17 | - [a97e08b](https://github.com/liuderchi/gh-template-bot/commit/a97e08ba7f5cb2dd7b5001ba3d2509f02b8abc2e) chore(packagejson): install flow-bin and init flow project (@liuderchi) 18 | - [f77333f](https://github.com/liuderchi/gh-template-bot/commit/f77333fd09109139be02827a79f5172adae66773) docs(github): create duplicate.md for Demo (@liuderchi) 19 | - [a580b0c](https://github.com/liuderchi/gh-template-bot/commit/a580b0c2c838329f85e3bce4ac83bbd9932e2b93) doc(github): add ReplyRef.md for demo (@liuderchi) 20 | 21 | ### v0.2.0 (2017/11/22 18:18 +00:00) 22 | - [#9](https://github.com/liuderchi/gh-template-bot/pull/9) Custom Templates (@liuderchi) 23 | - [1cf1483](https://github.com/liuderchi/gh-template-bot/commit/1cf1483ba205c55dcd0daad26defc3bf5a76031f) doc(dialog, readme): update dialog.md, README.md for better illustration (@liuderchi) 24 | - [fbde97e](https://github.com/liuderchi/gh-template-bot/commit/fbde97e6f5d716f0395c3d3fc1affc3e1aeace76) feat(handler): add handleIssueCommentWH() (@liuderchi) 25 | - [23bc74d](https://github.com/liuderchi/gh-template-bot/commit/23bc74d99761b76390888e211ad9400708c2c388) feat(utils): validate command action before get markdown content (@liuderchi) 26 | - [200a309](https://github.com/liuderchi/gh-template-bot/commit/200a3098e82cc3d7ffc5af0e2b40e01274a018a3) feat(handler, utils, packagejson): Fetch Custom Template from `.github/` (@liuderchi) 27 | - [3e771b1](https://github.com/liuderchi/gh-template-bot/commit/3e771b160aa9b4ec3c54937943d541201876172f) chores(packagejson): install npm `handlebars`, `minimist` (@liuderchi) 28 | - [e8cfdf1](https://github.com/liuderchi/gh-template-bot/commit/e8cfdf19cfb3ae06ebe1bfb90ed6f730de84523d) feat(utils): support custom markdown template with handlebar syntax (@liuderchi) 29 | - [c67ea2a](https://github.com/liuderchi/gh-template-bot/commit/c67ea2a27ca4078eb31dc36e5e59c113fb484ce3) feat(utils): refine getCommmand() in template.js (@liuderchi) 30 | - [05ed9d2](https://github.com/liuderchi/gh-template-bot/commit/05ed9d2d7cf42e2f87d9c3820030d6b144160896) refactor(templates): templates/*.js -> templates/*.md (@liuderchi) 31 | - [#8](https://github.com/liuderchi/gh-template-bot/pull/8) Refine docs and Config (@liuderchi) 32 | - [20f3988](https://github.com/liuderchi/gh-template-bot/commit/20f39882e36885fb1800affd2d90aac0b33c722f) turn off prettier in eslintrc (@liuderchi) 33 | - [88af984](https://github.com/liuderchi/gh-template-bot/commit/88af984d933d4847c1a48053202aaeded3bca11e) fix travis.yml to build on master branches rather than feature branches (@liuderchi) 34 | - [db25731](https://github.com/liuderchi/gh-template-bot/commit/db25731b7488eecfe43fda04b52e9675cc45b36a) refine usage, add installation guide in README (@liuderchi) 35 | - [#7](https://github.com/liuderchi/gh-template-bot/pull/7) Chores for CI and Enhance DX (@liuderchi) 36 | - [7c34250](https://github.com/liuderchi/gh-template-bot/commit/7c342504f61d213ef0ff5a711559812f1a414cf1) move js codes to create src/ folder (@liuderchi) 37 | - [361780c](https://github.com/liuderchi/gh-template-bot/commit/361780c06ca06592cd18f9e7e045e544ee8445b2) refine README, add badges (@liuderchi) 38 | - [62e0d5b](https://github.com/liuderchi/gh-template-bot/commit/62e0d5bc6c7bd33809d060f37c2c211e82d79b9f) introduce prettier (@liuderchi) 39 | - [d5a06d1](https://github.com/liuderchi/gh-template-bot/commit/d5a06d16fe8cd92b00d64be5f9b6abe5c3c5db3d) introduce eslint, fix lint error (@liuderchi) 40 | - [15a8926](https://github.com/liuderchi/gh-template-bot/commit/15a89264427f95bb5a33bad71c25e02b230f3476) add CHANGELOG.md, introduce github-changes (@liuderchi) 41 | 42 | ### v0.1.0-alpha (2017/11/11 18:23 +00:00) 43 | - [#4](https://github.com/liuderchi/gh-template-bot/pull/4) Doc for alpha release (@liuderchi) 44 | - [a459619](https://github.com/liuderchi/gh-template-bot/commit/a45961914fea06edd2c0dccf8cc3f8565a82bb5c) refine README, description in package.json (@liuderchi) 45 | - [09a35e2](https://github.com/liuderchi/gh-template-bot/commit/09a35e213c9eff257ca9b7eff8e7a0e2b7453441) update .env.example to fix local run failure (@liuderchi) 46 | - [c372ae1](https://github.com/liuderchi/gh-template-bot/commit/c372ae1f89d17279d199d7bcf311de74aa9cb78e) add logo.svg, logo.png (300 dpi) (@liuderchi) 47 | - [#3](https://github.com/liuderchi/gh-template-bot/pull/3) Deploy to Heroku Manually (@liuderchi) 48 | - [770c3be](https://github.com/liuderchi/gh-template-bot/commit/770c3bede4da512be12aa200fdd8ffc9ea7369f3) add jobs/deploy-heroku.sh (@liuderchi) 49 | - [58bf04b](https://github.com/liuderchi/gh-template-bot/commit/58bf04bf0d4ae281bbc4a8cc9671dba8905ae2ef) fix node version in package.json (@liuderchi) 50 | - [#2](https://github.com/liuderchi/gh-template-bot/pull/2) Handle Issue and PR Webhook (@liuderchi) 51 | - [ff3b44e](https://github.com/liuderchi/gh-template-bot/commit/ff3b44e645ca57cfd161ecddec75d2e72ccab82a) handle PR webhook (@liuderchi) 52 | - [254ebec](https://github.com/liuderchi/gh-template-bot/commit/254ebec545e5ebedf81a2c71240566a1654ffbce) handle issue webhook (@liuderchi) 53 | - [ad95050](https://github.com/liuderchi/gh-template-bot/commit/ad95050c78ff11e898ef4e73ecd2ba7638ea63fa) add simple templates (@liuderchi) 54 | - [140ca20](https://github.com/liuderchi/gh-template-bot/commit/140ca20c9074bef4530dedfcccf1a137e4337325) update `APP_ID`, `PRIVATE_KEY` in .env.example (@liuderchi) 55 | - [cd9fee9](https://github.com/liuderchi/gh-template-bot/commit/cd9fee91d0fb206e0ae470e0bb1a3132123ba3aa) install ramda, add `jest` to `scripts` in package.json (@liuderchi) 56 | - [#1](https://github.com/liuderchi/gh-template-bot/pull/1) Create Probot App (@liuderchi) 57 | - [8675418](https://github.com/liuderchi/gh-template-bot/commit/86754183613e1475e126b5ad9504956aca1f12ca) install nodemon, add `start:nodemon` to `scripts` in package.json (@liuderchi) 58 | - [34dc7b5](https://github.com/liuderchi/gh-template-bot/commit/34dc7b5df47e71f9c04a0a41bf57e4bbee98f6ca) add yarn.lock to .gitignore (@liuderchi) 59 | - [5e827fe](https://github.com/liuderchi/gh-template-bot/commit/5e827fe3e5601ddb94900a68ea7f1dcd3ae1178b) revert LICENSE changes (@liuderchi) 60 | - [d9b8d0d](https://github.com/liuderchi/gh-template-bot/commit/d9b8d0d7dd9f2b3ce352f4ce7b650fa4e5899c6c) npm install -g create-probot-app && create-probot-app gh-template-bot (@liuderchi) 61 | - [993a6d2](https://github.com/liuderchi/gh-template-bot/commit/993a6d2eb8f211c2313491e604551e765e465da4) Initial commit (@liuderchi) -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at liuderchi@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [fork]: /fork 4 | [pr]: /compare 5 | [style]: https://standardjs.com/ 6 | [code-of-conduct]: CODE_OF_CONDUCT.md 7 | 8 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 9 | 10 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 11 | 12 | ## Submitting a pull request 13 | 14 | 1. [Fork][fork] and clone the repository 15 | 1. Configure and install the dependencies: `npm install` 16 | 1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so no need to lint seperately 17 | 1. Create a new branch: `git checkout -b my-branch-name` 18 | 1. Make your change, add tests, and make sure the tests still pass 19 | 1. Push to your fork and [submit a pull request][pr] 20 | 1. Pat your self on the back and wait for your pull request to be reviewed and merged. 21 | 22 | Here are a few things you can do that will increase the likelihood of your pull request being accepted: 23 | 24 | - Follow the [style guide][style] which is using standard. Any linting errors should be shown when running `npm test` 25 | - Write and update tests. 26 | - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests. 27 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 28 | 29 | Work in Progress pull request are also welcome to get feedback early on, or if there is something blocked you. 30 | 31 | ## Resources 32 | 33 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) 34 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) 35 | - [GitHub Help](https://help.github.com) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Te-Chi Liu 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 |

2 | 3 | 4 | 5 |

6 | 7 | 8 | # GitHub Template Bot 9 | 10 | [![Build Status][travis-status]][travis-project] 11 | [![Dependency Status][david-status]][david-project] 12 | [![DevDependency Status][david-dev-status]][david-dev-project] 13 | [![PeerDependency Status][david-peer-status]][david-peer-project] 14 | [![license][license-badge]][license] 15 | 16 | :robot: Generate *Markdown Templates* for different *Issues*, *Pull Requests* and even *Feature Requests* 17 | 18 | 19 | ## Quick Start 20 | 21 | 1. Install Template Bot at [GitHub Apps Page][gh-app-page] 22 | 23 | 2. Now you can type one of these commands in issue/PR then submit 24 | 25 | - `/template issue` for general issues 26 | - `/template feature` to *Propose a Feature* in issue 27 | - `/template pr` for general pull request 28 | - `/template ReplyDup` to fetch your own `.github/ReplyDup.md` template 29 | - `/template` to ask :robot: for help 30 | 31 | 3. Refresh the page. Template Bot will create Markdown Template for you :tada: 32 | 33 | 34 | ## Demo 35 | 36 | ![demo1][demo1] 37 | 38 | --- 39 | 40 | ![demo2][demo2] 41 | 42 | --- 43 | 44 | Forgot command? Don't worry. Bot will help you :100: 45 | 46 | demo3 47 | 48 | 49 | ## Why 50 | 51 | We *create issues for different purposes*: 52 | 53 | > *Report a Bug, Propose a Feature, Asking for Help ...* 54 | 55 | But we are used to setup [one `ISSUE_TEMPLATE.md`][gh-issue-doc] for our workflow. \ 56 | So **Template Bot** is built to [generate templates for different scenarios][prob-to-solve]. 57 | 58 | 59 | ## Dev Guide 60 | 61 | ### Run on Local Machine 62 | - **Requirements** 63 | - Node >= 10 64 | - Yarn >= 1.3.2 65 | - **Environment** 66 | - create file `.env` from [`.env.example`](.env.example) 67 | - edit `.env` and set [`APP_ID`](.env.example#L2) according to your GitHub App 68 | - download private key to project root according to your GitHub App 69 | - NOTE: to create and config a Github App please follow [this Probot doc][doc-gh-app] 70 | - **Install and Run** 71 | 72 | ```bash 73 | $ yarn --pure-lockfile 74 | $ yarn run start:nodemon 75 | ``` 76 | 77 | ### Test 78 | 79 | ```bash 80 | $ yarn run jest 81 | ``` 82 | 83 | ### Deploy to Heroku 84 | 85 | ```bash 86 | $ sh jobs/deploy-heroku.sh 87 | ``` 88 | 89 | ### Notes 90 | 91 | - Inspired by [evenchange4/gh-polls-bot][gh-polls-bot], a Bot creating polls in your issues 92 | - Built with [probot][probot], an api-friendly nodejs bot framework 93 | - Built with [`create-probot-app`][create-probot-app] boilerplate for quick start 94 | - Deployed on Heroku following [this doc by Probot][doc-deploy] 95 | 96 | 97 | ## [CONTRIBUTING](CONTRIBUTING.md) 98 | 99 | 100 | ## [CHANGELOG](CHANGELOG.md) 101 | 102 | 103 | ## LICENSE 104 | 105 | MIT license https://liuderchi.mit-license.org 106 | 107 | [travis-status]: https://travis-ci.org/liuderchi/gh-template-bot.svg?branch=master "travis-status" 108 | [travis-project]: https://travis-ci.org/liuderchi/gh-template-bot "travis-project" 109 | [david-status]: https://david-dm.org/liuderchi/gh-template-bot/status.svg "david-status" 110 | [david-project]: https://david-dm.org/liuderchi/gh-template-bot "david-project" 111 | [david-dev-status]: https://david-dm.org/liuderchi/gh-template-bot/dev-status.svg "david-dev-status" 112 | [david-dev-project]: https://david-dm.org/liuderchi/gh-template-bot#info=devDependencies "david-dev-project" 113 | [david-peer-status]: https://david-dm.org/liuderchi/gh-template-bot/peer-status.svg "david-peer-status" 114 | [david-peer-project]: https://david-dm.org/liuderchi/gh-template-bot#info=peerDependencies "david-peer-project" 115 | [license-badge]: https://img.shields.io/github/license/liuderchi/gh-template-bot.svg "license-badge" 116 | [license]: http://liuderchi.mit-license.org/ "license" 117 | 118 | [gh-app-page]: https://github.com/apps/template "gh-app-page" 119 | 120 | [gh-issue-doc]: https://help.github.com/articles/creating-an-issue-template-for-your-repository/ "gh-issue-doc" 121 | [prob-to-solve]: https://github.com/RichardLitt/knowledge/issues/9 "prob-to-solve" 122 | 123 | [demo1]: https://user-images.githubusercontent.com/4994705/33142241-588e1f8e-cf7b-11e7-8e6d-73b355ac3a3a.gif "demo1" 124 | [demo2]: https://user-images.githubusercontent.com/4994705/33141626-5dfc957e-cf79-11e7-9c37-42dd15c4d2db.gif "demo2" 125 | [demo3]: https://user-images.githubusercontent.com/4994705/33139825-ff63b434-cf73-11e7-87c3-076007336a95.png "demo3" 126 | 127 | [doc-gh-app]: https://probot.github.io/docs/development/#configure-a-github-app "doc-gh-app" 128 | 129 | [gh-polls-bot]: https://github.com/evenchange4/gh-polls-bot "gh-polls-bot" 130 | [probot]: https://probot.github.io "probot" 131 | [create-probot-app]: https://github.com/probot/create-probot-app "create-probot-app" 132 | [doc-deploy]: https://probot.github.io/docs/deployment/#heroku "doc-deploy" 133 | -------------------------------------------------------------------------------- /__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | // You can import your modules 2 | // const index = require('../index') 3 | 4 | test('that we can run tests', () => { 5 | // your real tests go here 6 | expect(1 + 2 + 3).toBe(6) 7 | }) 8 | 9 | // For more information about testing with Jest see: 10 | // https://facebook.github.io/jest/ 11 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "PRIVATE_KEY": { 4 | "description": "the private key you downloaded when creating the GitHub App" 5 | }, 6 | "APP_ID": { 7 | "description": "the ID of your GitHub App" 8 | }, 9 | "WEBHOOK_SECRET": { 10 | "description": "the secret configured for your GitHub App" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /docs/deploy.md: -------------------------------------------------------------------------------- 1 | # Deploying 2 | 3 | If you would like to run your own instance of this app, see the [docs for deployment](https://probot.github.io/docs/deployment/). 4 | 5 | This app requires these **Permissions & events** for the GitHub App: 6 | 7 | > **TODO**: List permissions required for deployment here. See [probot/stale](https://github.com/probot/stale/blob/master/docs/deploy.md) for an example. 8 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuderchi/gh-template-bot/714bb3e754ce51eb25dbdc4600b5f7e15d063d6a/docs/logo.png -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Created with Sketch. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /flow-typed/npm/jest_v21.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 107cf7068b8835594e97f938e8848244 2 | // flow-typed version: 8b4dd96654/jest_v21.x.x/flow_>=v0.39.x 3 | 4 | type JestMockFn, TReturn> = { 5 | (...args: TArguments): TReturn, 6 | /** 7 | * An object for introspecting mock calls 8 | */ 9 | mock: { 10 | /** 11 | * An array that represents all calls that have been made into this mock 12 | * function. Each call is represented by an array of arguments that were 13 | * passed during the call. 14 | */ 15 | calls: Array, 16 | /** 17 | * An array that contains all the object instances that have been 18 | * instantiated from this mock function. 19 | */ 20 | instances: Array 21 | }, 22 | /** 23 | * Resets all information stored in the mockFn.mock.calls and 24 | * mockFn.mock.instances arrays. Often this is useful when you want to clean 25 | * up a mock's usage data between two assertions. 26 | */ 27 | mockClear(): void, 28 | /** 29 | * Resets all information stored in the mock. This is useful when you want to 30 | * completely restore a mock back to its initial state. 31 | */ 32 | mockReset(): void, 33 | /** 34 | * Removes the mock and restores the initial implementation. This is useful 35 | * when you want to mock functions in certain test cases and restore the 36 | * original implementation in others. Beware that mockFn.mockRestore only 37 | * works when mock was created with jest.spyOn. Thus you have to take care of 38 | * restoration yourself when manually assigning jest.fn(). 39 | */ 40 | mockRestore(): void, 41 | /** 42 | * Accepts a function that should be used as the implementation of the mock. 43 | * The mock itself will still record all calls that go into and instances 44 | * that come from itself -- the only difference is that the implementation 45 | * will also be executed when the mock is called. 46 | */ 47 | mockImplementation( 48 | fn: (...args: TArguments) => TReturn 49 | ): JestMockFn, 50 | /** 51 | * Accepts a function that will be used as an implementation of the mock for 52 | * one call to the mocked function. Can be chained so that multiple function 53 | * calls produce different results. 54 | */ 55 | mockImplementationOnce( 56 | fn: (...args: TArguments) => TReturn 57 | ): JestMockFn, 58 | /** 59 | * Just a simple sugar function for returning `this` 60 | */ 61 | mockReturnThis(): void, 62 | /** 63 | * Deprecated: use jest.fn(() => value) instead 64 | */ 65 | mockReturnValue(value: TReturn): JestMockFn, 66 | /** 67 | * Sugar for only returning a value once inside your mock 68 | */ 69 | mockReturnValueOnce(value: TReturn): JestMockFn 70 | }; 71 | 72 | type JestAsymmetricEqualityType = { 73 | /** 74 | * A custom Jasmine equality tester 75 | */ 76 | asymmetricMatch(value: mixed): boolean 77 | }; 78 | 79 | type JestCallsType = { 80 | allArgs(): mixed, 81 | all(): mixed, 82 | any(): boolean, 83 | count(): number, 84 | first(): mixed, 85 | mostRecent(): mixed, 86 | reset(): void 87 | }; 88 | 89 | type JestClockType = { 90 | install(): void, 91 | mockDate(date: Date): void, 92 | tick(milliseconds?: number): void, 93 | uninstall(): void 94 | }; 95 | 96 | type JestMatcherResult = { 97 | message?: string | (() => string), 98 | pass: boolean 99 | }; 100 | 101 | type JestMatcher = (actual: any, expected: any) => JestMatcherResult; 102 | 103 | type JestPromiseType = { 104 | /** 105 | * Use rejects to unwrap the reason of a rejected promise so any other 106 | * matcher can be chained. If the promise is fulfilled the assertion fails. 107 | */ 108 | rejects: JestExpectType, 109 | /** 110 | * Use resolves to unwrap the value of a fulfilled promise so any other 111 | * matcher can be chained. If the promise is rejected the assertion fails. 112 | */ 113 | resolves: JestExpectType 114 | }; 115 | 116 | /** 117 | * Plugin: jest-enzyme 118 | */ 119 | type EnzymeMatchersType = { 120 | toBeChecked(): void, 121 | toBeDisabled(): void, 122 | toBeEmpty(): void, 123 | toBePresent(): void, 124 | toContainReact(element: React$Element): void, 125 | toHaveClassName(className: string): void, 126 | toHaveHTML(html: string): void, 127 | toHaveProp(propKey: string, propValue?: any): void, 128 | toHaveRef(refName: string): void, 129 | toHaveState(stateKey: string, stateValue?: any): void, 130 | toHaveStyle(styleKey: string, styleValue?: any): void, 131 | toHaveTagName(tagName: string): void, 132 | toHaveText(text: string): void, 133 | toIncludeText(text: string): void, 134 | toHaveValue(value: any): void, 135 | toMatchElement(element: React$Element): void, 136 | toMatchSelector(selector: string): void 137 | }; 138 | 139 | type JestExpectType = { 140 | not: JestExpectType & EnzymeMatchersType, 141 | /** 142 | * If you have a mock function, you can use .lastCalledWith to test what 143 | * arguments it was last called with. 144 | */ 145 | lastCalledWith(...args: Array): void, 146 | /** 147 | * toBe just checks that a value is what you expect. It uses === to check 148 | * strict equality. 149 | */ 150 | toBe(value: any): void, 151 | /** 152 | * Use .toHaveBeenCalled to ensure that a mock function got called. 153 | */ 154 | toBeCalled(): void, 155 | /** 156 | * Use .toBeCalledWith to ensure that a mock function was called with 157 | * specific arguments. 158 | */ 159 | toBeCalledWith(...args: Array): void, 160 | /** 161 | * Using exact equality with floating point numbers is a bad idea. Rounding 162 | * means that intuitive things fail. 163 | */ 164 | toBeCloseTo(num: number, delta: any): void, 165 | /** 166 | * Use .toBeDefined to check that a variable is not undefined. 167 | */ 168 | toBeDefined(): void, 169 | /** 170 | * Use .toBeFalsy when you don't care what a value is, you just want to 171 | * ensure a value is false in a boolean context. 172 | */ 173 | toBeFalsy(): void, 174 | /** 175 | * To compare floating point numbers, you can use toBeGreaterThan. 176 | */ 177 | toBeGreaterThan(number: number): void, 178 | /** 179 | * To compare floating point numbers, you can use toBeGreaterThanOrEqual. 180 | */ 181 | toBeGreaterThanOrEqual(number: number): void, 182 | /** 183 | * To compare floating point numbers, you can use toBeLessThan. 184 | */ 185 | toBeLessThan(number: number): void, 186 | /** 187 | * To compare floating point numbers, you can use toBeLessThanOrEqual. 188 | */ 189 | toBeLessThanOrEqual(number: number): void, 190 | /** 191 | * Use .toBeInstanceOf(Class) to check that an object is an instance of a 192 | * class. 193 | */ 194 | toBeInstanceOf(cls: Class<*>): void, 195 | /** 196 | * .toBeNull() is the same as .toBe(null) but the error messages are a bit 197 | * nicer. 198 | */ 199 | toBeNull(): void, 200 | /** 201 | * Use .toBeTruthy when you don't care what a value is, you just want to 202 | * ensure a value is true in a boolean context. 203 | */ 204 | toBeTruthy(): void, 205 | /** 206 | * Use .toBeUndefined to check that a variable is undefined. 207 | */ 208 | toBeUndefined(): void, 209 | /** 210 | * Use .toContain when you want to check that an item is in a list. For 211 | * testing the items in the list, this uses ===, a strict equality check. 212 | */ 213 | toContain(item: any): void, 214 | /** 215 | * Use .toContainEqual when you want to check that an item is in a list. For 216 | * testing the items in the list, this matcher recursively checks the 217 | * equality of all fields, rather than checking for object identity. 218 | */ 219 | toContainEqual(item: any): void, 220 | /** 221 | * Use .toEqual when you want to check that two objects have the same value. 222 | * This matcher recursively checks the equality of all fields, rather than 223 | * checking for object identity. 224 | */ 225 | toEqual(value: any): void, 226 | /** 227 | * Use .toHaveBeenCalled to ensure that a mock function got called. 228 | */ 229 | toHaveBeenCalled(): void, 230 | /** 231 | * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact 232 | * number of times. 233 | */ 234 | toHaveBeenCalledTimes(number: number): void, 235 | /** 236 | * Use .toHaveBeenCalledWith to ensure that a mock function was called with 237 | * specific arguments. 238 | */ 239 | toHaveBeenCalledWith(...args: Array): void, 240 | /** 241 | * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called 242 | * with specific arguments. 243 | */ 244 | toHaveBeenLastCalledWith(...args: Array): void, 245 | /** 246 | * Check that an object has a .length property and it is set to a certain 247 | * numeric value. 248 | */ 249 | toHaveLength(number: number): void, 250 | /** 251 | * 252 | */ 253 | toHaveProperty(propPath: string, value?: any): void, 254 | /** 255 | * Use .toMatch to check that a string matches a regular expression or string. 256 | */ 257 | toMatch(regexpOrString: RegExp | string): void, 258 | /** 259 | * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object. 260 | */ 261 | toMatchObject(object: Object | Array): void, 262 | /** 263 | * This ensures that a React component matches the most recent snapshot. 264 | */ 265 | toMatchSnapshot(name?: string): void, 266 | /** 267 | * Use .toThrow to test that a function throws when it is called. 268 | * If you want to test that a specific error gets thrown, you can provide an 269 | * argument to toThrow. The argument can be a string for the error message, 270 | * a class for the error, or a regex that should match the error. 271 | * 272 | * Alias: .toThrowError 273 | */ 274 | toThrow(message?: string | Error | Class | RegExp): void, 275 | toThrowError(message?: string | Error | Class | RegExp): void, 276 | /** 277 | * Use .toThrowErrorMatchingSnapshot to test that a function throws a error 278 | * matching the most recent snapshot when it is called. 279 | */ 280 | toThrowErrorMatchingSnapshot(): void 281 | }; 282 | 283 | type JestObjectType = { 284 | /** 285 | * Disables automatic mocking in the module loader. 286 | * 287 | * After this method is called, all `require()`s will return the real 288 | * versions of each module (rather than a mocked version). 289 | */ 290 | disableAutomock(): JestObjectType, 291 | /** 292 | * An un-hoisted version of disableAutomock 293 | */ 294 | autoMockOff(): JestObjectType, 295 | /** 296 | * Enables automatic mocking in the module loader. 297 | */ 298 | enableAutomock(): JestObjectType, 299 | /** 300 | * An un-hoisted version of enableAutomock 301 | */ 302 | autoMockOn(): JestObjectType, 303 | /** 304 | * Clears the mock.calls and mock.instances properties of all mocks. 305 | * Equivalent to calling .mockClear() on every mocked function. 306 | */ 307 | clearAllMocks(): JestObjectType, 308 | /** 309 | * Resets the state of all mocks. Equivalent to calling .mockReset() on every 310 | * mocked function. 311 | */ 312 | resetAllMocks(): JestObjectType, 313 | /** 314 | * Removes any pending timers from the timer system. 315 | */ 316 | clearAllTimers(): void, 317 | /** 318 | * The same as `mock` but not moved to the top of the expectation by 319 | * babel-jest. 320 | */ 321 | doMock(moduleName: string, moduleFactory?: any): JestObjectType, 322 | /** 323 | * The same as `unmock` but not moved to the top of the expectation by 324 | * babel-jest. 325 | */ 326 | dontMock(moduleName: string): JestObjectType, 327 | /** 328 | * Returns a new, unused mock function. Optionally takes a mock 329 | * implementation. 330 | */ 331 | fn, TReturn>( 332 | implementation?: (...args: TArguments) => TReturn 333 | ): JestMockFn, 334 | /** 335 | * Determines if the given function is a mocked function. 336 | */ 337 | isMockFunction(fn: Function): boolean, 338 | /** 339 | * Given the name of a module, use the automatic mocking system to generate a 340 | * mocked version of the module for you. 341 | */ 342 | genMockFromModule(moduleName: string): any, 343 | /** 344 | * Mocks a module with an auto-mocked version when it is being required. 345 | * 346 | * The second argument can be used to specify an explicit module factory that 347 | * is being run instead of using Jest's automocking feature. 348 | * 349 | * The third argument can be used to create virtual mocks -- mocks of modules 350 | * that don't exist anywhere in the system. 351 | */ 352 | mock( 353 | moduleName: string, 354 | moduleFactory?: any, 355 | options?: Object 356 | ): JestObjectType, 357 | /** 358 | * Returns the actual module instead of a mock, bypassing all checks on 359 | * whether the module should receive a mock implementation or not. 360 | */ 361 | requireActual(moduleName: string): any, 362 | /** 363 | * Returns a mock module instead of the actual module, bypassing all checks 364 | * on whether the module should be required normally or not. 365 | */ 366 | requireMock(moduleName: string): any, 367 | /** 368 | * Resets the module registry - the cache of all required modules. This is 369 | * useful to isolate modules where local state might conflict between tests. 370 | */ 371 | resetModules(): JestObjectType, 372 | /** 373 | * Exhausts the micro-task queue (usually interfaced in node via 374 | * process.nextTick). 375 | */ 376 | runAllTicks(): void, 377 | /** 378 | * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(), 379 | * setInterval(), and setImmediate()). 380 | */ 381 | runAllTimers(): void, 382 | /** 383 | * Exhausts all tasks queued by setImmediate(). 384 | */ 385 | runAllImmediates(): void, 386 | /** 387 | * Executes only the macro task queue (i.e. all tasks queued by setTimeout() 388 | * or setInterval() and setImmediate()). 389 | */ 390 | runTimersToTime(msToRun: number): void, 391 | /** 392 | * Executes only the macro-tasks that are currently pending (i.e., only the 393 | * tasks that have been queued by setTimeout() or setInterval() up to this 394 | * point) 395 | */ 396 | runOnlyPendingTimers(): void, 397 | /** 398 | * Explicitly supplies the mock object that the module system should return 399 | * for the specified module. Note: It is recommended to use jest.mock() 400 | * instead. 401 | */ 402 | setMock(moduleName: string, moduleExports: any): JestObjectType, 403 | /** 404 | * Indicates that the module system should never return a mocked version of 405 | * the specified module from require() (e.g. that it should always return the 406 | * real module). 407 | */ 408 | unmock(moduleName: string): JestObjectType, 409 | /** 410 | * Instructs Jest to use fake versions of the standard timer functions 411 | * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick, 412 | * setImmediate and clearImmediate). 413 | */ 414 | useFakeTimers(): JestObjectType, 415 | /** 416 | * Instructs Jest to use the real versions of the standard timer functions. 417 | */ 418 | useRealTimers(): JestObjectType, 419 | /** 420 | * Creates a mock function similar to jest.fn but also tracks calls to 421 | * object[methodName]. 422 | */ 423 | spyOn(object: Object, methodName: string): JestMockFn, 424 | /** 425 | * Set the default timeout interval for tests and before/after hooks in milliseconds. 426 | * Note: The default timeout interval is 5 seconds if this method is not called. 427 | */ 428 | setTimeout(timeout: number): JestObjectType 429 | }; 430 | 431 | type JestSpyType = { 432 | calls: JestCallsType 433 | }; 434 | 435 | /** Runs this function after every test inside this context */ 436 | declare function afterEach( 437 | fn: (done: () => void) => ?Promise, 438 | timeout?: number 439 | ): void; 440 | /** Runs this function before every test inside this context */ 441 | declare function beforeEach( 442 | fn: (done: () => void) => ?Promise, 443 | timeout?: number 444 | ): void; 445 | /** Runs this function after all tests have finished inside this context */ 446 | declare function afterAll( 447 | fn: (done: () => void) => ?Promise, 448 | timeout?: number 449 | ): void; 450 | /** Runs this function before any tests have started inside this context */ 451 | declare function beforeAll( 452 | fn: (done: () => void) => ?Promise, 453 | timeout?: number 454 | ): void; 455 | 456 | /** A context for grouping tests together */ 457 | declare var describe: { 458 | /** 459 | * Creates a block that groups together several related tests in one "test suite" 460 | */ 461 | (name: string, fn: () => void): void, 462 | 463 | /** 464 | * Only run this describe block 465 | */ 466 | only(name: string, fn: () => void): void, 467 | 468 | /** 469 | * Skip running this describe block 470 | */ 471 | skip(name: string, fn: () => void): void 472 | }; 473 | 474 | /** An individual test unit */ 475 | declare var it: { 476 | /** 477 | * An individual test unit 478 | * 479 | * @param {string} Name of Test 480 | * @param {Function} Test 481 | * @param {number} Timeout for the test, in milliseconds. 482 | */ 483 | ( 484 | name: string, 485 | fn?: (done: () => void) => ?Promise, 486 | timeout?: number 487 | ): void, 488 | /** 489 | * Only run this test 490 | * 491 | * @param {string} Name of Test 492 | * @param {Function} Test 493 | * @param {number} Timeout for the test, in milliseconds. 494 | */ 495 | only( 496 | name: string, 497 | fn?: (done: () => void) => ?Promise, 498 | timeout?: number 499 | ): void, 500 | /** 501 | * Skip running this test 502 | * 503 | * @param {string} Name of Test 504 | * @param {Function} Test 505 | * @param {number} Timeout for the test, in milliseconds. 506 | */ 507 | skip( 508 | name: string, 509 | fn?: (done: () => void) => ?Promise, 510 | timeout?: number 511 | ): void, 512 | /** 513 | * Run the test concurrently 514 | * 515 | * @param {string} Name of Test 516 | * @param {Function} Test 517 | * @param {number} Timeout for the test, in milliseconds. 518 | */ 519 | concurrent( 520 | name: string, 521 | fn?: (done: () => void) => ?Promise, 522 | timeout?: number 523 | ): void 524 | }; 525 | declare function fit( 526 | name: string, 527 | fn: (done: () => void) => ?Promise, 528 | timeout?: number 529 | ): void; 530 | /** An individual test unit */ 531 | declare var test: typeof it; 532 | /** A disabled group of tests */ 533 | declare var xdescribe: typeof describe; 534 | /** A focused group of tests */ 535 | declare var fdescribe: typeof describe; 536 | /** A disabled individual test */ 537 | declare var xit: typeof it; 538 | /** A disabled individual test */ 539 | declare var xtest: typeof it; 540 | 541 | /** The expect function is used every time you want to test a value */ 542 | declare var expect: { 543 | /** The object that you want to make assertions against */ 544 | (value: any): JestExpectType & JestPromiseType & EnzymeMatchersType, 545 | /** Add additional Jasmine matchers to Jest's roster */ 546 | extend(matchers: { [name: string]: JestMatcher }): void, 547 | /** Add a module that formats application-specific data structures. */ 548 | addSnapshotSerializer(serializer: (input: Object) => string): void, 549 | assertions(expectedAssertions: number): void, 550 | hasAssertions(): void, 551 | any(value: mixed): JestAsymmetricEqualityType, 552 | anything(): void, 553 | arrayContaining(value: Array): void, 554 | objectContaining(value: Object): void, 555 | /** Matches any received string that contains the exact expected string. */ 556 | stringContaining(value: string): void, 557 | stringMatching(value: string | RegExp): void 558 | }; 559 | 560 | // TODO handle return type 561 | // http://jasmine.github.io/2.4/introduction.html#section-Spies 562 | declare function spyOn(value: mixed, method: string): Object; 563 | 564 | /** Holds all functions related to manipulating test runner */ 565 | declare var jest: JestObjectType; 566 | 567 | /** 568 | * The global Jasmine object, this is generally not exposed as the public API, 569 | * using features inside here could break in later versions of Jest. 570 | */ 571 | declare var jasmine: { 572 | DEFAULT_TIMEOUT_INTERVAL: number, 573 | any(value: mixed): JestAsymmetricEqualityType, 574 | anything(): void, 575 | arrayContaining(value: Array): void, 576 | clock(): JestClockType, 577 | createSpy(name: string): JestSpyType, 578 | createSpyObj( 579 | baseName: string, 580 | methodNames: Array 581 | ): { [methodName: string]: JestSpyType }, 582 | objectContaining(value: Object): void, 583 | stringMatching(value: string): void 584 | }; 585 | -------------------------------------------------------------------------------- /flow-typed/npm/minimist_v1.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 50bc453586282fb18e63201750049659 2 | // flow-typed version: e6f7626e10/minimist_v1.x.x/flow_>=v0.28.x 3 | 4 | declare module 'minimist' { 5 | declare type minimistOptions = { 6 | string?: string | Array, 7 | boolean?: boolean | string | Array, 8 | alias?: { [arg: string]: string | Array }, 9 | default?: { [arg: string]: any }, 10 | stopEarly?: boolean, 11 | // TODO: Strings as keys don't work... 12 | // '--'? boolean, 13 | unknown?: (param: string) => boolean 14 | }; 15 | 16 | declare type minimistOutput = { 17 | _: Array, 18 | [flag: string]: string | boolean 19 | }; 20 | 21 | declare module.exports: (argv: Array, opts?: minimistOptions) => minimistOutput; 22 | } 23 | -------------------------------------------------------------------------------- /flow-typed/npm/ramda_v0.x.x.js: -------------------------------------------------------------------------------- 1 | // flow-typed signature: 0c4298604331ed66060f8faf01656da2 2 | // flow-typed version: 426a81c8ee/ramda_v0.x.x/flow_>=v0.49.x 3 | 4 | /* eslint-disable no-unused-vars, no-redeclare */ 5 | 6 | type Transformer = { 7 | "@@transducer/step": (r: A, a: *) => R, 8 | "@@transducer/init": () => A, 9 | "@@transducer/result": (result: *) => B 10 | }; 11 | 12 | declare type $npm$ramda$Placeholder = { "@@functional/placeholder": true }; 13 | 14 | declare module ramda { 15 | declare type UnaryFn = (a: A) => R; 16 | declare type UnaryPromiseFn = UnaryFn>; 17 | declare type BinaryFn = ((a: A, b: B) => R) & 18 | ((a: A) => (b: B) => R); 19 | declare type UnarySameTypeFn = UnaryFn; 20 | declare type BinarySameTypeFn = BinaryFn; 21 | declare type NestedObject = { [k: string]: T | NestedObject }; 22 | declare type UnaryPredicateFn = (x: T) => boolean; 23 | declare type BinaryPredicateFn = (x: T, y: T) => boolean; 24 | declare type BinaryPredicateFn2 = (x: T, y: S) => boolean; 25 | 26 | declare interface ObjPredicate { 27 | (value: any, key: string): boolean; 28 | } 29 | 30 | declare type __CurriedFunction1 = (...r: [AA]) => R; 31 | declare type CurriedFunction1 = __CurriedFunction1; 32 | 33 | declare type __CurriedFunction2 = (( 34 | ...r: [AA] 35 | ) => CurriedFunction1) & 36 | ((...r: [AA, BB]) => R); 37 | declare type CurriedFunction2 = __CurriedFunction2; 38 | 39 | declare type __CurriedFunction3 = (( 40 | ...r: [AA] 41 | ) => CurriedFunction2) & 42 | ((...r: [AA, BB]) => CurriedFunction1) & 43 | ((...r: [AA, BB, CC]) => R); 44 | declare type CurriedFunction3 = __CurriedFunction3< 45 | A, 46 | B, 47 | C, 48 | R, 49 | *, 50 | *, 51 | * 52 | >; 53 | 54 | declare type __CurriedFunction4< 55 | A, 56 | B, 57 | C, 58 | D, 59 | R, 60 | AA: A, 61 | BB: B, 62 | CC: C, 63 | DD: D 64 | > = ((...r: [AA]) => CurriedFunction3) & 65 | ((...r: [AA, BB]) => CurriedFunction2) & 66 | ((...r: [AA, BB, CC]) => CurriedFunction1) & 67 | ((...r: [AA, BB, CC, DD]) => R); 68 | declare type CurriedFunction4 = __CurriedFunction4< 69 | A, 70 | B, 71 | C, 72 | D, 73 | R, 74 | *, 75 | *, 76 | *, 77 | * 78 | >; 79 | 80 | declare type __CurriedFunction5< 81 | A, 82 | B, 83 | C, 84 | D, 85 | E, 86 | R, 87 | AA: A, 88 | BB: B, 89 | CC: C, 90 | DD: D, 91 | EE: E 92 | > = ((...r: [AA]) => CurriedFunction4) & 93 | ((...r: [AA, BB]) => CurriedFunction3) & 94 | ((...r: [AA, BB, CC]) => CurriedFunction2) & 95 | ((...r: [AA, BB, CC, DD]) => CurriedFunction1) & 96 | ((...r: [AA, BB, CC, DD, EE]) => R); 97 | declare type CurriedFunction5 = __CurriedFunction5< 98 | A, 99 | B, 100 | C, 101 | D, 102 | E, 103 | R, 104 | *, 105 | *, 106 | *, 107 | *, 108 | * 109 | >; 110 | 111 | declare type __CurriedFunction6< 112 | A, 113 | B, 114 | C, 115 | D, 116 | E, 117 | F, 118 | R, 119 | AA: A, 120 | BB: B, 121 | CC: C, 122 | DD: D, 123 | EE: E, 124 | FF: F 125 | > = ((...r: [AA]) => CurriedFunction5) & 126 | ((...r: [AA, BB]) => CurriedFunction4) & 127 | ((...r: [AA, BB, CC]) => CurriedFunction3) & 128 | ((...r: [AA, BB, CC, DD]) => CurriedFunction2) & 129 | ((...r: [AA, BB, CC, DD, EE]) => CurriedFunction1) & 130 | ((...r: [AA, BB, CC, DD, EE, FF]) => R); 131 | declare type CurriedFunction6 = __CurriedFunction6< 132 | A, 133 | B, 134 | C, 135 | D, 136 | E, 137 | F, 138 | R, 139 | *, 140 | *, 141 | *, 142 | *, 143 | *, 144 | * 145 | >; 146 | 147 | declare type Curry = (((...r: [A]) => R) => CurriedFunction1) & 148 | (((...r: [A, B]) => R) => CurriedFunction2) & 149 | (((...r: [A, B, C]) => R) => CurriedFunction3) & 150 | (( 151 | (...r: [A, B, C, D]) => R 152 | ) => CurriedFunction4) & 153 | (( 154 | (...r: [A, B, C, D, E]) => R 155 | ) => CurriedFunction5) & 156 | (( 157 | (...r: [A, B, C, D, E, F]) => R 158 | ) => CurriedFunction6); 159 | 160 | declare type Partial = (((...r: [A]) => R, args: [A]) => () => R) & 161 | (((...r: [A, B]) => R, args: [A]) => B => R) & 162 | (((...r: [A, B]) => R, args: [A, B]) => () => R) & 163 | (((...r: [A, B, C]) => R, args: [A]) => (B, C) => R) & 164 | (((...r: [A, B, C]) => R, args: [A, B]) => C => R) & 165 | (((...r: [A, B, C]) => R, args: [A, B, C]) => () => R) & 166 | (((...r: [A, B, C, D]) => R, args: [A]) => (B, C, D) => R) & 167 | (((...r: [A, B, C, D]) => R, args: [A, B]) => (C, D) => R) & 168 | (((...r: [A, B, C, D]) => R, args: [A, B, C]) => D => R) & 169 | (( 170 | (...r: [A, B, C, D]) => R, 171 | args: [A, B, C, D] 172 | ) => () => R) & 173 | (( 174 | (...r: [A, B, C, D, E]) => R, 175 | args: [A] 176 | ) => (B, C, D, E) => R) & 177 | (( 178 | (...r: [A, B, C, D, E]) => R, 179 | args: [A, B] 180 | ) => (C, D, E) => R) & 181 | (( 182 | (...r: [A, B, C, D, E]) => R, 183 | args: [A, B, C] 184 | ) => (D, E) => R) & 185 | (( 186 | (...r: [A, B, C, D, E]) => R, 187 | args: [A, B, C, D] 188 | ) => E => R) & 189 | (( 190 | (...r: [A, B, C, D, E]) => R, 191 | args: [A, B, C, D, E] 192 | ) => () => R) & 193 | (( 194 | (...r: [A, B, C, D, E, F]) => R, 195 | args: [A] 196 | ) => (B, C, D, E, F) => R) & 197 | (( 198 | (...r: [A, B, C, D, E, F]) => R, 199 | args: [A, B] 200 | ) => (C, D, E, F) => R) & 201 | (( 202 | (...r: [A, B, C, D, E, F]) => R, 203 | args: [A, B, C] 204 | ) => (D, E, F) => R) & 205 | (( 206 | (...r: [A, B, C, D, E, F]) => R, 207 | args: [A, B, C, D] 208 | ) => (E, F) => R) & 209 | (( 210 | (...r: [A, B, C, D, E, F]) => R, 211 | args: [A, B, C, D, E] 212 | ) => F => R) & 213 | (( 214 | (...r: [A, B, C, D, E, F]) => R, 215 | args: [A, B, C, D, E, F] 216 | ) => () => R) & 217 | (( 218 | (...r: [A, B, C, D, E, F, G]) => R, 219 | args: [A] 220 | ) => (B, C, D, E, F, G) => R) & 221 | (( 222 | (...r: [A, B, C, D, E, F, G]) => R, 223 | args: [A, B] 224 | ) => (C, D, E, F, G) => R) & 225 | (( 226 | (...r: [A, B, C, D, E, F, G]) => R, 227 | args: [A, B, C] 228 | ) => (D, E, F, G) => R) & 229 | (( 230 | (...r: [A, B, C, D, E, F, G]) => R, 231 | args: [A, B, C, D] 232 | ) => (E, F, G) => R) & 233 | (( 234 | (...r: [A, B, C, D, E, F, G]) => R, 235 | args: [A, B, C, D, E] 236 | ) => (F, G) => R) & 237 | (( 238 | (...r: [A, B, C, D, E, F, G]) => R, 239 | args: [A, B, C, D, E, F] 240 | ) => G => R) & 241 | (( 242 | (...r: [A, B, C, D, E, F, G]) => R, 243 | args: [A, B, C, D, E, F, G] 244 | ) => () => R) & 245 | (( 246 | (...r: [A, B, C, D, E, F, G, H]) => R, 247 | args: [A] 248 | ) => (B, C, D, E, F, G, H) => R) & 249 | (( 250 | (...r: [A, B, C, D, E, F, G, H]) => R, 251 | args: [A, B] 252 | ) => (C, D, E, F, G, H) => R) & 253 | (( 254 | (...r: [A, B, C, D, E, F, G, H]) => R, 255 | args: [A, B, C] 256 | ) => (D, E, F, G, H) => R) & 257 | (( 258 | (...r: [A, B, C, D, E, F, G, H]) => R, 259 | args: [A, B, C, D] 260 | ) => (E, F, G, H) => R) & 261 | (( 262 | (...r: [A, B, C, D, E, F, G, H]) => R, 263 | args: [A, B, C, D, E] 264 | ) => (F, G, H) => R) & 265 | (( 266 | (...r: [A, B, C, D, E, F, G, H]) => R, 267 | args: [A, B, C, D, E, F] 268 | ) => (G, H) => R) & 269 | (( 270 | (...r: [A, B, C, D, E, F, G, H]) => R, 271 | args: [A, B, C, D, E, F, G] 272 | ) => H => R) & 273 | (( 274 | (...r: [A, B, C, D, E, F, G, H]) => R, 275 | args: [A, B, C, D, E, F, G, H] 276 | ) => () => R) & 277 | (( 278 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 279 | args: [A] 280 | ) => (B, C, D, E, F, G, H, I) => R) & 281 | (( 282 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 283 | args: [A, B] 284 | ) => (C, D, E, F, G, H, I) => R) & 285 | (( 286 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 287 | args: [A, B, C] 288 | ) => (D, E, F, G, H, I) => R) & 289 | (( 290 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 291 | args: [A, B, C, D] 292 | ) => (E, F, G, H, I) => R) & 293 | (( 294 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 295 | args: [A, B, C, D, E] 296 | ) => (F, G, H, I) => R) & 297 | (( 298 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 299 | args: [A, B, C, D, E, F] 300 | ) => (G, H, I) => R) & 301 | (( 302 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 303 | args: [A, B, C, D, E, F, G] 304 | ) => (H, I) => R) & 305 | (( 306 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 307 | args: [A, B, C, D, E, F, G, H] 308 | ) => I => R) & 309 | (( 310 | (...r: [A, B, C, D, E, F, G, H, I]) => R, 311 | args: [A, B, C, D, E, F, G, H, I] 312 | ) => () => R); 313 | 314 | declare type Pipe = (( 315 | ab: UnaryFn, 316 | bc: UnaryFn, 317 | cd: UnaryFn, 318 | de: UnaryFn, 319 | ef: UnaryFn, 320 | fg: UnaryFn, 321 | ...rest: Array 322 | ) => UnaryFn) & 323 | (( 324 | ab: UnaryFn, 325 | bc: UnaryFn, 326 | cd: UnaryFn, 327 | de: UnaryFn, 328 | ef: UnaryFn, 329 | ...rest: Array 330 | ) => UnaryFn) & 331 | (( 332 | ab: UnaryFn, 333 | bc: UnaryFn, 334 | de: UnaryFn, 335 | ...rest: Array 336 | ) => UnaryFn) & 337 | (( 338 | ab: UnaryFn, 339 | bc: UnaryFn, 340 | cd: UnaryFn, 341 | ...rest: Array 342 | ) => UnaryFn) & 343 | (( 344 | ab: UnaryFn, 345 | bc: UnaryFn, 346 | ...rest: Array 347 | ) => UnaryFn) & 348 | ((ab: UnaryFn, ...rest: Array) => UnaryFn); 349 | 350 | declare type PipeP = (( 351 | ab: UnaryPromiseFn, 352 | bc: UnaryPromiseFn, 353 | cd: UnaryPromiseFn, 354 | de: UnaryPromiseFn, 355 | ef: UnaryPromiseFn, 356 | fg: UnaryPromiseFn, 357 | ...rest: Array 358 | ) => UnaryPromiseFn) & 359 | (( 360 | ab: UnaryPromiseFn, 361 | bc: UnaryPromiseFn, 362 | cd: UnaryPromiseFn, 363 | de: UnaryPromiseFn, 364 | ef: UnaryPromiseFn, 365 | ...rest: Array 366 | ) => UnaryPromiseFn) & 367 | (( 368 | ab: UnaryPromiseFn, 369 | bc: UnaryPromiseFn, 370 | cd: UnaryPromiseFn, 371 | de: UnaryPromiseFn, 372 | ...rest: Array 373 | ) => UnaryPromiseFn) & 374 | (( 375 | ab: UnaryPromiseFn, 376 | bc: UnaryPromiseFn, 377 | cd: UnaryPromiseFn, 378 | ...rest: Array 379 | ) => UnaryPromiseFn) & 380 | (( 381 | ab: UnaryPromiseFn, 382 | bc: UnaryPromiseFn, 383 | ...rest: Array 384 | ) => UnaryPromiseFn) & 385 | (( 386 | ab: UnaryPromiseFn, 387 | ...rest: Array 388 | ) => UnaryPromiseFn); 389 | 390 | declare type Compose = (( 391 | fg: UnaryFn, 392 | ef: UnaryFn, 393 | de: UnaryFn, 394 | cd: UnaryFn, 395 | bc: UnaryFn, 396 | ab: UnaryFn, 397 | ...rest: Array 398 | ) => UnaryFn) & 399 | (( 400 | ef: UnaryFn, 401 | de: UnaryFn, 402 | cd: UnaryFn, 403 | bc: UnaryFn, 404 | ab: UnaryFn, 405 | ...rest: Array 406 | ) => UnaryFn) & 407 | (( 408 | de: UnaryFn, 409 | cd: UnaryFn, 410 | bc: UnaryFn, 411 | ab: UnaryFn, 412 | ...rest: Array 413 | ) => UnaryFn) & 414 | (( 415 | cd: UnaryFn, 416 | bc: UnaryFn, 417 | ab: UnaryFn, 418 | ...rest: Array 419 | ) => UnaryFn) & 420 | (( 421 | bc: UnaryFn, 422 | ab: UnaryFn, 423 | ...rest: Array 424 | ) => UnaryFn) & 425 | ((ab: UnaryFn, ...rest: Array) => UnaryFn); 426 | 427 | declare type Filter = ( | { [key: K]: V }>( 428 | fn: UnaryPredicateFn, 429 | xs: T 430 | ) => T) & 431 | ( | { [key: K]: V }>( 432 | fn: UnaryPredicateFn 433 | ) => (xs: T) => T); 434 | 435 | declare class Monad { 436 | chain: Function; 437 | } 438 | 439 | declare class Semigroup {} 440 | 441 | declare class Chain { 442 | chain | Array>(fn: (a: T) => V, x: V): V; 443 | chain | Array>(fn: (a: T) => V): (x: V) => V; 444 | } 445 | 446 | declare class GenericContructor { 447 | constructor(x: T): GenericContructor; 448 | } 449 | 450 | declare class GenericContructorMulti { 451 | constructor(...args: Array): GenericContructor; 452 | } 453 | 454 | /** 455 | * DONE: 456 | * Function* 457 | * List* 458 | * Logic 459 | * Math 460 | * Object* 461 | * Relation 462 | * String 463 | * Type 464 | */ 465 | 466 | declare var compose: Compose; 467 | declare var pipe: Pipe; 468 | declare var pipeP: PipeP; 469 | declare var curry: Curry; 470 | declare function curryN( 471 | length: number, 472 | fn: (...args: Array) => any 473 | ): Function; 474 | 475 | // *Math 476 | declare var add: CurriedFunction2; 477 | declare var inc: UnaryFn; 478 | declare var dec: UnaryFn; 479 | declare var mean: UnaryFn, number>; 480 | declare var divide: CurriedFunction2; 481 | declare var mathMod: CurriedFunction2; 482 | declare var median: UnaryFn, number>; 483 | declare var modulo: CurriedFunction2; 484 | declare var multiply: CurriedFunction2; 485 | declare var negate: UnaryFn; 486 | declare var product: UnaryFn, number>; 487 | declare var subtract: CurriedFunction2; 488 | declare var sum: UnaryFn, number>; 489 | 490 | // Filter 491 | declare var filter: Filter; 492 | declare var reject: Filter; 493 | 494 | // *String 495 | declare var match: CurriedFunction2>; 496 | declare var replace: CurriedFunction3< 497 | RegExp | string, 498 | string, 499 | string, 500 | string 501 | >; 502 | declare var split: CurriedFunction2>; 503 | declare var test: CurriedFunction2; 504 | declare function toLower(a: string): string; 505 | declare function toString(a: any): string; 506 | declare function toUpper(a: string): string; 507 | declare function trim(a: string): string; 508 | 509 | // *Type 510 | declare function is(t: T, ...rest: Array): (v: any) => boolean; 511 | declare function is(t: T, v: any): boolean; 512 | declare var propIs: CurriedFunction3; 513 | declare function type(x: ?any): string; 514 | declare function isArrayLike(x: any): boolean; 515 | 516 | declare function isNil(x: mixed): boolean %checks(x === undefined || 517 | x === null); 518 | 519 | // *List 520 | declare function adjust( 521 | fn: (a: T) => T, 522 | ...rest: Array 523 | ): (index: number, ...rest: Array) => (src: Array) => Array; 524 | declare function adjust( 525 | fn: (a: T) => T, 526 | index: number, 527 | ...rest: Array 528 | ): (src: Array) => Array; 529 | declare function adjust( 530 | fn: (a: T) => T, 531 | index: number, 532 | src: Array 533 | ): Array; 534 | 535 | declare function all(fn: UnaryPredicateFn, xs: Array): boolean; 536 | declare function all( 537 | fn: UnaryPredicateFn, 538 | ...rest: Array 539 | ): (xs: Array) => boolean; 540 | 541 | declare function any(fn: UnaryPredicateFn, xs: Array): boolean; 542 | declare function any( 543 | fn: UnaryPredicateFn, 544 | ...rest: Array 545 | ): (xs: Array) => boolean; 546 | 547 | declare function aperture(n: number, xs: Array): Array>; 548 | declare function aperture( 549 | n: number, 550 | ...rest: Array 551 | ): (xs: Array) => Array>; 552 | 553 | declare function append(x: E, xs: Array): Array; 554 | declare function append( 555 | x: E, 556 | ...rest: Array 557 | ): (xs: Array) => Array; 558 | 559 | declare function prepend(x: E, xs: Array): Array; 560 | declare function prepend( 561 | x: E, 562 | ...rest: Array 563 | ): (xs: Array) => Array; 564 | 565 | declare function concat | string>(x: T, y: T): T; 566 | declare function concat | string>(x: T): (y: T) => T; 567 | 568 | declare function contains | string>(x: E, xs: T): boolean; 569 | declare function contains | string>( 570 | x: E, 571 | ...rest: Array 572 | ): (xs: T) => boolean; 573 | 574 | declare function drop | string>( 575 | n: number, 576 | ...rest: Array 577 | ): (xs: T) => T; 578 | declare function drop | string>(n: number, xs: T): T; 579 | 580 | declare function dropLast | string>( 581 | n: number, 582 | ...rest: Array 583 | ): (xs: T) => T; 584 | declare function dropLast | string>(n: number, xs: T): T; 585 | 586 | declare function dropLastWhile>( 587 | fn: UnaryPredicateFn, 588 | ...rest: Array 589 | ): (xs: T) => T; 590 | declare function dropLastWhile>( 591 | fn: UnaryPredicateFn, 592 | xs: T 593 | ): T; 594 | 595 | declare function dropWhile>( 596 | fn: UnaryPredicateFn, 597 | ...rest: Array 598 | ): (xs: T) => T; 599 | declare function dropWhile>(fn: UnaryPredicateFn, xs: T): T; 600 | 601 | declare function dropRepeats>(xs: T): T; 602 | 603 | declare function dropRepeatsWith>( 604 | fn: BinaryPredicateFn, 605 | ...rest: Array 606 | ): (xs: T) => T; 607 | declare function dropRepeatsWith>( 608 | fn: BinaryPredicateFn, 609 | xs: T 610 | ): T; 611 | 612 | declare function groupBy( 613 | fn: (x: T) => string, 614 | xs: Array 615 | ): { [key: string]: Array }; 616 | declare function groupBy( 617 | fn: (x: T) => string, 618 | ...rest: Array 619 | ): (xs: Array) => { [key: string]: Array }; 620 | 621 | declare function groupWith | string>( 622 | fn: BinaryPredicateFn, 623 | xs: V 624 | ): Array; 625 | declare function groupWith | string>( 626 | fn: BinaryPredicateFn, 627 | ...rest: Array 628 | ): (xs: V) => Array; 629 | 630 | declare function head>(xs: V): ?T; 631 | declare function head(xs: V): V; 632 | 633 | declare function into, R: Array<*> | string | Object>( 634 | accum: R, 635 | xf: (a: A) => I, 636 | input: A 637 | ): R; 638 | declare function into, R>( 639 | accum: Transformer, 640 | xf: (a: A) => R, 641 | input: A 642 | ): R; 643 | 644 | declare function indexOf(x: E, xs: Array): number; 645 | declare function indexOf( 646 | x: E, 647 | ...rest: Array 648 | ): (xs: Array) => number; 649 | 650 | declare function indexBy( 651 | fn: (x: T) => string, 652 | ...rest: Array 653 | ): (xs: Array) => { [key: string]: T }; 654 | declare function indexBy( 655 | fn: (x: T) => string, 656 | xs: Array 657 | ): { [key: string]: T }; 658 | 659 | declare function insert( 660 | index: number, 661 | ...rest: Array 662 | ): (elem: T) => (src: Array) => Array; 663 | declare function insert( 664 | index: number, 665 | elem: T, 666 | ...rest: Array 667 | ): (src: Array) => Array; 668 | declare function insert(index: number, elem: T, src: Array): Array; 669 | 670 | declare function insertAll( 671 | index: number, 672 | ...rest: Array 673 | ): (elem: Array) => (src: Array) => Array; 674 | declare function insertAll( 675 | index: number, 676 | elems: Array, 677 | ...rest: Array 678 | ): (src: Array) => Array; 679 | declare function insertAll( 680 | index: number, 681 | elems: Array, 682 | src: Array 683 | ): Array; 684 | 685 | declare function join(x: string, xs: Array): string; 686 | declare function join( 687 | x: string, 688 | ...rest: Array 689 | ): (xs: Array) => string; 690 | 691 | declare function last>(xs: V): ?T; 692 | declare function last(xs: V): V; 693 | 694 | declare function none(fn: UnaryPredicateFn, xs: Array): boolean; 695 | declare function none( 696 | fn: UnaryPredicateFn, 697 | ...rest: Array 698 | ): (xs: Array) => boolean; 699 | 700 | declare function nth>(i: number, xs: T): ?V; 701 | declare function nth | string>( 702 | i: number, 703 | ...rest: Array 704 | ): ((xs: string) => string) & ((xs: T) => ?V); 705 | declare function nth(i: number, xs: T): T; 706 | 707 | declare type Find = (>( 708 | fn: UnaryPredicateFn 709 | ) => (xs: T) => ?V) & 710 | (>(fn: UnaryPredicateFn, xs: T) => ?V); 711 | 712 | declare var find: Find; 713 | 714 | declare function findLast | O>( 715 | fn: UnaryPredicateFn, 716 | ...rest: Array 717 | ): (xs: T | O) => ?V | O; 718 | declare function findLast | O>( 719 | fn: UnaryPredicateFn, 720 | xs: T | O 721 | ): ?V | O; 722 | 723 | declare function findIndex | { [key: K]: V }>( 724 | fn: UnaryPredicateFn, 725 | ...rest: Array 726 | ): (xs: T) => number; 727 | declare function findIndex | { [key: K]: V }>( 728 | fn: UnaryPredicateFn, 729 | xs: T 730 | ): number; 731 | declare function findLastIndex | { [key: K]: V }>( 732 | fn: UnaryPredicateFn, 733 | ...rest: Array 734 | ): (xs: T) => number; 735 | declare function findLastIndex | { [key: K]: V }>( 736 | fn: UnaryPredicateFn, 737 | xs: T 738 | ): number; 739 | 740 | declare function forEach(fn: (x: T) => ?V, xs: Array): Array; 741 | declare function forEach( 742 | fn: (x: T) => ?V, 743 | ...rest: Array 744 | ): (xs: Array) => Array; 745 | 746 | declare function forEachObjIndexed( 747 | fn: (val: A, key: string, o: O) => B, 748 | o: { [key: string]: A } 749 | ): O; 750 | 751 | declare function forEachObjIndexed( 752 | fn: (val: A, key: string, o: O) => B, 753 | ...args: Array 754 | ): (o: { [key: string]: A }) => O; 755 | 756 | declare function lastIndexOf(x: E, xs: Array): number; 757 | declare function lastIndexOf( 758 | x: E, 759 | ...rest: Array 760 | ): (xs: Array) => number; 761 | 762 | declare function map(fn: (x: T) => R, xs: Array): Array; 763 | declare function map(fn: (x: T) => R, xs: S): S; 764 | declare function map( 765 | fn: (x: T) => R, 766 | ...rest: Array 767 | ): ((xs: { [key: string]: T }) => { [key: string]: R }) & 768 | ((xs: Array) => Array); 769 | declare function map( 770 | fn: (x: T) => R, 771 | ...rest: Array 772 | ): ((xs: S) => S) & ((xs: S) => S); 773 | declare function map( 774 | fn: (x: T) => R, 775 | xs: { [key: string]: T } 776 | ): { [key: string]: R }; 777 | 778 | declare type AccumIterator = (acc: R, x: A) => [R, B]; 779 | declare function mapAccum( 780 | fn: AccumIterator, 781 | acc: R, 782 | xs: Array 783 | ): [R, Array]; 784 | declare function mapAccum( 785 | fn: AccumIterator, 786 | ...rest: Array 787 | ): (acc: R, xs: Array) => [R, Array]; 788 | 789 | declare function mapAccumRight( 790 | fn: AccumIterator, 791 | acc: R, 792 | xs: Array 793 | ): [R, Array]; 794 | declare function mapAccumRight( 795 | fn: AccumIterator, 796 | ...rest: Array 797 | ): (acc: R, xs: Array) => [R, Array]; 798 | 799 | declare function intersperse(x: E, xs: Array): Array; 800 | declare function intersperse( 801 | x: E, 802 | ...rest: Array 803 | ): (xs: Array) => Array; 804 | 805 | declare function pair(a: A, b: B): [A, B]; 806 | declare function pair(a: A, ...rest: Array): (b: B) => [A, B]; 807 | 808 | declare function partition | { [key: K]: V }>( 809 | fn: UnaryPredicateFn, 810 | xs: T 811 | ): [T, T]; 812 | declare function partition | { [key: K]: V }>( 813 | fn: UnaryPredicateFn, 814 | ...rest: Array 815 | ): (xs: T) => [T, T]; 816 | 817 | declare function pluck< 818 | V, 819 | K: string | number, 820 | T: Array | { [key: string]: V }> 821 | >( 822 | k: K, 823 | xs: T 824 | ): Array; 825 | declare function pluck< 826 | V, 827 | K: string | number, 828 | T: Array | { [key: string]: V }> 829 | >( 830 | k: K, 831 | ...rest: Array 832 | ): (xs: T) => Array; 833 | 834 | declare var range: CurriedFunction2>; 835 | 836 | declare function remove( 837 | from: number, 838 | ...rest: Array 839 | ): ((to: number, ...rest: Array) => (src: Array) => Array) & 840 | ((to: number, src: Array) => Array); 841 | declare function remove( 842 | from: number, 843 | to: number, 844 | ...rest: Array 845 | ): (src: Array) => Array; 846 | declare function remove(from: number, to: number, src: Array): Array; 847 | 848 | declare function repeat(x: T, times: number): Array; 849 | declare function repeat( 850 | x: T, 851 | ...rest: Array 852 | ): (times: number) => Array; 853 | 854 | declare function slice | string>( 855 | from: number, 856 | ...rest: Array 857 | ): ((to: number, ...rest: Array) => (src: T) => T) & 858 | ((to: number, src: T) => T); 859 | declare function slice | string>( 860 | from: number, 861 | to: number, 862 | ...rest: Array 863 | ): (src: T) => T; 864 | declare function slice | string>( 865 | from: number, 866 | to: number, 867 | src: T 868 | ): T; 869 | 870 | declare function sort>(fn: (a: V, b: V) => number, xs: T): T; 871 | declare function sort>( 872 | fn: (a: V, b: V) => number, 873 | ...rest: Array 874 | ): (xs: T) => T; 875 | 876 | declare function times(fn: (i: number) => T, n: number): Array; 877 | declare function times( 878 | fn: (i: number) => T, 879 | ...rest: Array 880 | ): (n: number) => Array; 881 | 882 | declare function take | string>(n: number, xs: T): T; 883 | declare function take | string>(n: number): (xs: T) => T; 884 | 885 | declare function takeLast | string>(n: number, xs: T): T; 886 | declare function takeLast | string>(n: number): (xs: T) => T; 887 | 888 | declare function takeLastWhile>( 889 | fn: UnaryPredicateFn, 890 | xs: T 891 | ): T; 892 | declare function takeLastWhile>( 893 | fn: UnaryPredicateFn 894 | ): (xs: T) => T; 895 | 896 | declare function takeWhile>(fn: UnaryPredicateFn, xs: T): T; 897 | declare function takeWhile>( 898 | fn: UnaryPredicateFn 899 | ): (xs: T) => T; 900 | 901 | declare function unfold( 902 | fn: (seed: T) => [R, T] | boolean, 903 | ...rest: Array 904 | ): (seed: T) => Array; 905 | declare function unfold( 906 | fn: (seed: T) => [R, T] | boolean, 907 | seed: T 908 | ): Array; 909 | 910 | declare function uniqBy( 911 | fn: (x: T) => V, 912 | ...rest: Array 913 | ): (xs: Array) => Array; 914 | declare function uniqBy(fn: (x: T) => V, xs: Array): Array; 915 | 916 | declare function uniqWith( 917 | fn: BinaryPredicateFn, 918 | ...rest: Array 919 | ): (xs: Array) => Array; 920 | declare function uniqWith( 921 | fn: BinaryPredicateFn, 922 | xs: Array 923 | ): Array; 924 | 925 | declare function update( 926 | index: number, 927 | ...rest: Array 928 | ): ((elem: T, ...rest: Array) => (src: Array) => Array) & 929 | ((elem: T, src: Array) => Array); 930 | declare function update( 931 | index: number, 932 | elem: T, 933 | ...rest: Array 934 | ): (src: Array) => Array; 935 | declare function update(index: number, elem: T, src: Array): Array; 936 | 937 | // TODO `without` as a transducer 938 | declare function without(xs: Array, src: Array): Array; 939 | declare function without( 940 | xs: Array, 941 | ...rest: Array 942 | ): (src: Array) => Array; 943 | 944 | declare function xprod(xs: Array, ys: Array): Array<[T, S]>; 945 | declare function xprod( 946 | xs: Array, 947 | ...rest: Array 948 | ): (ys: Array) => Array<[T, S]>; 949 | 950 | declare function zip(xs: Array, ys: Array): Array<[T, S]>; 951 | declare function zip( 952 | xs: Array, 953 | ...rest: Array 954 | ): (ys: Array) => Array<[T, S]>; 955 | 956 | declare function zipObj( 957 | xs: Array, 958 | ys: Array 959 | ): { [key: T]: S }; 960 | declare function zipObj( 961 | xs: Array, 962 | ...rest: Array 963 | ): (ys: Array) => { [key: T]: S }; 964 | 965 | declare type NestedArray = Array>; 966 | declare function flatten(xs: NestedArray): Array; 967 | 968 | declare function fromPairs(pair: Array<[T, V]>): { [key: string]: V }; 969 | 970 | declare function init | string>(xs: V): V; 971 | 972 | declare function length(xs: Array): number; 973 | 974 | declare function mergeAll( 975 | objs: Array<{ [key: string]: any }> 976 | ): { [key: string]: any }; 977 | 978 | declare function reverse | string>(xs: V): V; 979 | 980 | declare function reduce( 981 | fn: (acc: A, elem: B) => A, 982 | ...rest: Array 983 | ): ((init: A, xs: Array) => A) & 984 | ((init: A, ...rest: Array) => (xs: Array) => A); 985 | declare function reduce( 986 | fn: (acc: A, elem: B) => A, 987 | init: A, 988 | ...rest: Array 989 | ): (xs: Array) => A; 990 | declare function reduce( 991 | fn: (acc: A, elem: B) => A, 992 | init: A, 993 | xs: Array 994 | ): A; 995 | 996 | declare function reduceBy( 997 | fn: (acc: B, elem: A) => B, 998 | ...rest: Array 999 | ): (( 1000 | acc: B, 1001 | ...rest: Array 1002 | ) => (( 1003 | keyFn: (elem: A) => string, 1004 | ...rest: Array 1005 | ) => (xs: Array) => { [key: string]: B }) & 1006 | ((keyFn: (elem: A) => string, xs: Array) => { [key: string]: B })) & 1007 | (( 1008 | acc: B, 1009 | keyFn: (elem: A) => string, 1010 | ...rest: Array 1011 | ) => (xs: Array) => { [key: string]: B }) & 1012 | (( 1013 | acc: B, 1014 | keyFn: (elem: A) => string, 1015 | xs: Array 1016 | ) => { [key: string]: B }); 1017 | declare function reduceBy( 1018 | fn: (acc: B, elem: A) => B, 1019 | acc: B, 1020 | ...rest: Array 1021 | ): (( 1022 | keyFn: (elem: A) => string, 1023 | ...rest: Array 1024 | ) => (xs: Array) => { [key: string]: B }) & 1025 | ((keyFn: (elem: A) => string, xs: Array) => { [key: string]: B }); 1026 | declare function reduceBy( 1027 | fn: (acc: B, elem: A) => B, 1028 | acc: B, 1029 | keyFn: (elem: A) => string 1030 | ): (xs: Array) => { [key: string]: B }; 1031 | declare function reduceBy( 1032 | fn: (acc: B, elem: A) => B, 1033 | acc: B, 1034 | keyFn: (elem: A) => string, 1035 | xs: Array 1036 | ): { [key: string]: B }; 1037 | 1038 | declare function reduceRight( 1039 | fn: (elem: B, acc: A) => A, 1040 | ...rest: Array 1041 | ): ((init: A, xs: Array) => A) & 1042 | ((init: A, ...rest: Array) => (xs: Array) => A); 1043 | declare function reduceRight( 1044 | fn: (elem: B, acc: A) => A, 1045 | init: A, 1046 | ...rest: Array 1047 | ): (xs: Array) => A; 1048 | declare function reduceRight( 1049 | fn: (elem: B, acc: A) => A, 1050 | init: A, 1051 | xs: Array 1052 | ): A; 1053 | 1054 | declare function scan( 1055 | fn: (acc: A, elem: B) => A, 1056 | ...rest: Array 1057 | ): ((init: A, xs: Array) => Array) & 1058 | ((init: A, ...rest: Array) => (xs: Array) => Array); 1059 | declare function scan( 1060 | fn: (acc: A, elem: B) => A, 1061 | init: A, 1062 | ...rest: Array 1063 | ): (xs: Array) => Array; 1064 | declare function scan( 1065 | fn: (acc: A, elem: B) => A, 1066 | init: A, 1067 | xs: Array 1068 | ): Array; 1069 | 1070 | declare function splitAt | string>(i: number, xs: T): [T, T]; 1071 | declare function splitAt | string>( 1072 | i: number 1073 | ): (xs: T) => [T, T]; 1074 | declare function splitEvery | string>( 1075 | i: number, 1076 | xs: T 1077 | ): Array; 1078 | declare function splitEvery | string>( 1079 | i: number 1080 | ): (xs: T) => Array; 1081 | declare function splitWhen>( 1082 | fn: UnaryPredicateFn, 1083 | xs: T 1084 | ): [T, T]; 1085 | declare function splitWhen>( 1086 | fn: UnaryPredicateFn 1087 | ): (xs: T) => [T, T]; 1088 | 1089 | declare function tail | string>(xs: V): V; 1090 | 1091 | declare function transpose(xs: Array>): Array>; 1092 | 1093 | declare function uniq(xs: Array): Array; 1094 | 1095 | declare function unnest(xs: NestedArray): NestedArray; 1096 | 1097 | declare function zipWith( 1098 | fn: (a: T, b: S) => R, 1099 | ...rest: Array 1100 | ): ((xs: Array, ys: Array) => Array) & 1101 | ((xs: Array, ...rest: Array) => (ys: Array) => Array); 1102 | declare function zipWith( 1103 | fn: (a: T, b: S) => R, 1104 | xs: Array, 1105 | ...rest: Array 1106 | ): (ys: Array) => Array; 1107 | declare function zipWith( 1108 | fn: (a: T, b: S) => R, 1109 | xs: Array, 1110 | ys: Array 1111 | ): Array; 1112 | 1113 | // *Relation 1114 | declare function equals(x: T, ...rest: Array): (y: T) => boolean; 1115 | declare function equals(x: T, y: T): boolean; 1116 | 1117 | declare function eqBy( 1118 | fn: (x: A) => B, 1119 | ...rest: Array 1120 | ): ((x: A, y: A) => boolean) & 1121 | ((x: A, ...rest: Array) => (y: A) => boolean); 1122 | declare function eqBy( 1123 | fn: (x: A) => B, 1124 | x: A, 1125 | ...rest: Array 1126 | ): (y: A) => boolean; 1127 | declare function eqBy(fn: (x: A) => B, x: A, y: A): boolean; 1128 | 1129 | // Flow cares about the order in which these appear. Generally function 1130 | // siguatures should go from smallest arity to largest arity. 1131 | declare type PropEq = (( 1132 | prop: $Keys 1133 | ) => ((val: mixed) => (obj: T) => boolean) & 1134 | ((val: mixed, obj: T) => boolean)) & 1135 | ((prop: $Keys, val: mixed) => (obj: T) => boolean) & 1136 | ((prop: $Keys, val: mixed, obj: T) => boolean) & 1137 | // Array variants. 1138 | (( 1139 | prop: number 1140 | ) => ((val: mixed) => (obj: Array<*>) => boolean) & 1141 | ((val: mixed, obj: Array<*>) => boolean)) & 1142 | ((prop: number, val: mixed) => (obj: Array<*>) => boolean) & 1143 | ((prop: number, val: mixed, obj: Array<*>) => boolean); 1144 | declare var propEq: PropEq; 1145 | 1146 | declare function pathEq( 1147 | path: Array, 1148 | ...rest: Array 1149 | ): ((val: any, o: Object) => boolean) & 1150 | ((val: any, ...rest: Array) => (o: Object) => boolean); 1151 | declare function pathEq( 1152 | path: Array, 1153 | val: any, 1154 | ...rest: Array 1155 | ): (o: Object) => boolean; 1156 | declare function pathEq(path: Array, val: any, o: Object): boolean; 1157 | 1158 | declare function clamp( 1159 | min: T, 1160 | ...rest: Array 1161 | ): ((max: T, ...rest: Array) => (v: T) => T) & ((max: T, v: T) => T); 1162 | declare function clamp( 1163 | min: T, 1164 | max: T, 1165 | ...rest: Array 1166 | ): (v: T) => T; 1167 | declare function clamp(min: T, max: T, v: T): T; 1168 | 1169 | declare function countBy( 1170 | fn: (x: T) => string, 1171 | ...rest: Array 1172 | ): (list: Array) => { [key: string]: number }; 1173 | declare function countBy( 1174 | fn: (x: T) => string, 1175 | list: Array 1176 | ): { [key: string]: number }; 1177 | 1178 | declare function difference( 1179 | xs1: Array, 1180 | ...rest: Array 1181 | ): (xs2: Array) => Array; 1182 | declare function difference(xs1: Array, xs2: Array): Array; 1183 | 1184 | declare function differenceWith( 1185 | fn: BinaryPredicateFn, 1186 | ...rest: Array 1187 | ): ((xs1: Array) => (xs2: Array) => Array) & 1188 | ((xs1: Array, xs2: Array) => Array); 1189 | declare function differenceWith( 1190 | fn: BinaryPredicateFn, 1191 | xs1: Array, 1192 | ...rest: Array 1193 | ): (xs2: Array) => Array; 1194 | declare function differenceWith( 1195 | fn: BinaryPredicateFn, 1196 | xs1: Array, 1197 | xs2: Array 1198 | ): Array; 1199 | 1200 | declare function eqBy(fn: (x: T) => T, x: T, y: T): boolean; 1201 | declare function eqBy(fn: (x: T) => T): (x: T, y: T) => boolean; 1202 | declare function eqBy(fn: (x: T) => T, x: T): (y: T) => boolean; 1203 | declare function eqBy(fn: (x: T) => T): (x: T) => (y: T) => boolean; 1204 | 1205 | declare function gt(x: T, ...rest: Array): (y: T) => boolean; 1206 | declare function gt(x: T, y: T): boolean; 1207 | 1208 | declare function gte(x: T, ...rest: Array): (y: T) => boolean; 1209 | declare function gte(x: T, y: T): boolean; 1210 | 1211 | declare function identical(x: T, ...rest: Array): (y: T) => boolean; 1212 | declare function identical(x: T, y: T): boolean; 1213 | 1214 | declare function intersection(x: Array, y: Array): Array; 1215 | declare function intersection(x: Array): (y: Array) => Array; 1216 | 1217 | declare function intersectionWith( 1218 | fn: BinaryPredicateFn, 1219 | ...rest: Array 1220 | ): ((x: Array, y: Array) => Array) & 1221 | ((x: Array) => (y: Array) => Array); 1222 | declare function intersectionWith( 1223 | fn: BinaryPredicateFn, 1224 | x: Array, 1225 | ...rest: Array 1226 | ): (y: Array) => Array; 1227 | declare function intersectionWith( 1228 | fn: BinaryPredicateFn, 1229 | x: Array, 1230 | y: Array 1231 | ): Array; 1232 | 1233 | declare function lt(x: T, ...rest: Array): (y: T) => boolean; 1234 | declare function lt(x: T, y: T): boolean; 1235 | 1236 | declare function lte(x: T, ...rest: Array): (y: T) => boolean; 1237 | declare function lte(x: T, y: T): boolean; 1238 | 1239 | declare function max(x: T, ...rest: Array): (y: T) => T; 1240 | declare function max(x: T, y: T): T; 1241 | 1242 | declare function maxBy( 1243 | fn: (x: T) => V, 1244 | ...rest: Array 1245 | ): ((x: T, y: T) => T) & ((x: T) => (y: T) => T); 1246 | declare function maxBy( 1247 | fn: (x: T) => V, 1248 | x: T, 1249 | ...rest: Array 1250 | ): (y: T) => T; 1251 | declare function maxBy(fn: (x: T) => V, x: T, y: T): T; 1252 | 1253 | declare function min(x: T, ...rest: Array): (y: T) => T; 1254 | declare function min(x: T, y: T): T; 1255 | 1256 | declare function minBy( 1257 | fn: (x: T) => V, 1258 | ...rest: Array 1259 | ): ((x: T, y: T) => T) & ((x: T) => (y: T) => T); 1260 | declare function minBy( 1261 | fn: (x: T) => V, 1262 | x: T, 1263 | ...rest: Array 1264 | ): (y: T) => T; 1265 | declare function minBy(fn: (x: T) => V, x: T, y: T): T; 1266 | 1267 | declare function sortBy( 1268 | fn: (x: T) => V, 1269 | ...rest: Array 1270 | ): (x: Array) => Array; 1271 | declare function sortBy(fn: (x: T) => V, x: Array): Array; 1272 | 1273 | declare function symmetricDifference( 1274 | x: Array, 1275 | ...rest: Array 1276 | ): (y: Array) => Array; 1277 | declare function symmetricDifference(x: Array, y: Array): Array; 1278 | 1279 | declare function symmetricDifferenceWith( 1280 | fn: BinaryPredicateFn, 1281 | ...rest: Array 1282 | ): ((x: Array, ...rest: Array) => (y: Array) => Array) & 1283 | ((x: Array, y: Array) => Array); 1284 | declare function symmetricDifferenceWith( 1285 | fn: BinaryPredicateFn, 1286 | x: Array, 1287 | ...rest: Array 1288 | ): (y: Array) => Array; 1289 | declare function symmetricDifferenceWith( 1290 | fn: BinaryPredicateFn, 1291 | x: Array, 1292 | y: Array 1293 | ): Array; 1294 | 1295 | declare function union( 1296 | x: Array, 1297 | ...rest: Array 1298 | ): (y: Array) => Array; 1299 | declare function union(x: Array, y: Array): Array; 1300 | 1301 | declare function unionWith( 1302 | fn: BinaryPredicateFn, 1303 | ...rest: Array 1304 | ): ((x: Array, ...rest: Array) => (y: Array) => Array) & 1305 | ((x: Array, y: Array) => Array); 1306 | declare function unionWith( 1307 | fn: BinaryPredicateFn, 1308 | x: Array, 1309 | ...rest: Array 1310 | ): (y: Array) => Array; 1311 | declare function unionWith( 1312 | fn: BinaryPredicateFn, 1313 | x: Array, 1314 | y: Array 1315 | ): Array; 1316 | 1317 | // *Object 1318 | declare function assoc( 1319 | key: string, 1320 | ...args: Array 1321 | ): ((val: T, ...rest: Array) => (src: S) => { [k: string]: T }) & 1322 | ((val: T, src: S) => { [k: string]: T } & S); 1323 | declare function assoc( 1324 | key: string, 1325 | val: T, 1326 | ...args: Array 1327 | ): (src: S) => { [k: string]: T } & S; 1328 | declare function assoc( 1329 | key: string, 1330 | val: T, 1331 | src: S 1332 | ): { [k: string]: T } & S; 1333 | 1334 | declare function assocPath( 1335 | key: Array, 1336 | ...args: Array 1337 | ): ((val: T, ...rest: Array) => (src: S) => { [k: string]: T }) & 1338 | ((val: T) => (src: S) => { [k: string]: T } & S); 1339 | declare function assocPath( 1340 | key: Array, 1341 | val: T, 1342 | ...args: Array 1343 | ): (src: S) => { [k: string]: T } & S; 1344 | declare function assocPath( 1345 | key: Array, 1346 | val: T, 1347 | src: S 1348 | ): { [k: string]: T } & S; 1349 | 1350 | declare function clone(src: T): $Shape; 1351 | 1352 | declare function dissoc( 1353 | key: string, 1354 | ...args: Array 1355 | ): (src: { [k: string]: T }) => { [k: string]: T }; 1356 | declare function dissoc( 1357 | key: string, 1358 | src: { [k: string]: T } 1359 | ): { [k: string]: T }; 1360 | 1361 | declare function dissocPath( 1362 | key: Array, 1363 | ...args: Array 1364 | ): (src: { [k: string]: T }) => { [k: string]: T }; 1365 | declare function dissocPath( 1366 | key: Array, 1367 | src: { [k: string]: T } 1368 | ): { [k: string]: T }; 1369 | 1370 | declare function evolve(NestedObject, A): A; 1371 | declare function evolve(NestedObject): A => A; 1372 | 1373 | declare function eqProps( 1374 | key: string, 1375 | ...args: Array 1376 | ): ((o1: Object, ...rest: Array) => (o2: Object) => boolean) & 1377 | ((o1: Object, o2: Object) => boolean); 1378 | declare function eqProps( 1379 | key: string, 1380 | o1: Object, 1381 | ...args: Array 1382 | ): (o2: Object) => boolean; 1383 | declare function eqProps(key: string, o1: Object, o2: Object): boolean; 1384 | 1385 | declare function has(key: string, o: Object): boolean; 1386 | declare function has(key: string): (o: Object) => boolean; 1387 | 1388 | declare function hasIn(key: string, o: Object): boolean; 1389 | declare function hasIn(key: string): (o: Object) => boolean; 1390 | 1391 | declare function invert(o: Object): { [k: string]: Array }; 1392 | declare function invertObj(o: Object): { [k: string]: string }; 1393 | 1394 | declare function keys(o: Object): Array; 1395 | 1396 | /* TODO 1397 | lens 1398 | lensIndex 1399 | lensPath 1400 | lensProp 1401 | */ 1402 | 1403 | declare function mapObjIndexed( 1404 | fn: (val: A, key: string, o: Object) => B, 1405 | o: { [key: string]: A } 1406 | ): { [key: string]: B }; 1407 | declare function mapObjIndexed( 1408 | fn: (val: A, key: string, o: Object) => B, 1409 | ...args: Array 1410 | ): (o: { [key: string]: A }) => { [key: string]: B }; 1411 | 1412 | declare function merge(o1: A, ...rest: Array): (o2: B) => A & B; 1413 | declare function merge(o1: A, o2: B): A & B; 1414 | 1415 | declare function mergeAll( 1416 | os: Array<{ [k: string]: T }> 1417 | ): { [k: string]: T }; 1418 | 1419 | declare function mergeWith< 1420 | T, 1421 | S, 1422 | R, 1423 | A: { [k: string]: T }, 1424 | B: { [k: string]: S } 1425 | >( 1426 | fn: (v1: T, v2: S) => R 1427 | ): ((o1: A, ...rest: Array) => (o2: B) => A & B) & 1428 | ((o1: A, o2: B) => A & B); 1429 | declare function mergeWith< 1430 | T, 1431 | S, 1432 | R, 1433 | A: { [k: string]: T }, 1434 | B: { [k: string]: S } 1435 | >( 1436 | fn: (v1: T, v2: S) => R, 1437 | o1: A, 1438 | o2: B 1439 | ): A & B; 1440 | declare function mergeWith< 1441 | T, 1442 | S, 1443 | R, 1444 | A: { [k: string]: T }, 1445 | B: { [k: string]: S } 1446 | >( 1447 | fn: (v1: T, v2: S) => R, 1448 | o1: A, 1449 | ...rest: Array 1450 | ): (o2: B) => A & B; 1451 | 1452 | declare function mergeWithKey< 1453 | T, 1454 | S, 1455 | R, 1456 | A: { [k: string]: T }, 1457 | B: { [k: string]: S } 1458 | >( 1459 | fn: (key: $Keys, v1: T, v2: S) => R 1460 | ): ((o1: A, ...rest: Array) => (o2: B) => A & B) & 1461 | ((o1: A, o2: B) => A & B); 1462 | declare function mergeWithKey< 1463 | T, 1464 | S, 1465 | R, 1466 | A: { [k: string]: T }, 1467 | B: { [k: string]: S } 1468 | >( 1469 | fn: (key: $Keys, v1: T, v2: S) => R, 1470 | o1: A, 1471 | o2: B 1472 | ): A & B; 1473 | declare function mergeWithKey< 1474 | T, 1475 | S, 1476 | R, 1477 | A: { [k: string]: T }, 1478 | B: { [k: string]: S } 1479 | >( 1480 | fn: (key: $Keys, v1: T, v2: S) => R, 1481 | o1: A, 1482 | ...rest: Array 1483 | ): (o2: B) => A & B; 1484 | 1485 | declare function objOf( 1486 | key: string, 1487 | ...rest: Array 1488 | ): (val: T) => { [key: string]: T }; 1489 | declare function objOf(key: string, val: T): { [key: string]: T }; 1490 | 1491 | declare function omit( 1492 | keys: Array<$Keys>, 1493 | ...rest: Array 1494 | ): (val: T) => Object; 1495 | declare function omit(keys: Array<$Keys>, val: T): Object; 1496 | 1497 | // TODO over 1498 | 1499 | declare function path( 1500 | p: Array, 1501 | ...rest: Array 1502 | ): (o: NestedObject) => V; 1503 | declare function path( 1504 | p: Array, 1505 | ...rest: Array 1506 | ): (o: null | void) => void; 1507 | declare function path( 1508 | p: Array, 1509 | ...rest: Array 1510 | ): (o: mixed) => ?V; 1511 | declare function path>(p: Array, o: A): V; 1512 | declare function path(p: Array, o: A): void; 1513 | declare function path(p: Array, o: A): ?V; 1514 | 1515 | declare function path( 1516 | p: Array, 1517 | ...rest: Array 1518 | ): (o: NestedObject) => V; 1519 | declare function path( 1520 | p: Array, 1521 | ...rest: Array 1522 | ): (o: null | void) => void; 1523 | declare function path( 1524 | p: Array, 1525 | ...rest: Array 1526 | ): (o: mixed) => ?V; 1527 | declare function path>(p: Array, o: A): V; 1528 | declare function path(p: Array, o: A): void; 1529 | declare function path(p: Array, o: A): ?V; 1530 | 1531 | declare function pathOr>( 1532 | or: T, 1533 | ...rest: Array 1534 | ): ((p: Array, ...rest: Array) => (o: ?A) => V | T) & 1535 | ((p: Array, o: ?A) => V | T); 1536 | declare function pathOr>( 1537 | or: T, 1538 | p: Array, 1539 | ...rest: Array 1540 | ): (o: ?A) => V | T; 1541 | declare function pathOr>( 1542 | or: T, 1543 | p: Array, 1544 | o: ?A 1545 | ): V | T; 1546 | 1547 | declare function pick( 1548 | keys: Array, 1549 | ...rest: Array 1550 | ): (val: { [key: string]: A }) => { [key: string]: A }; 1551 | declare function pick( 1552 | keys: Array, 1553 | val: { [key: string]: A } 1554 | ): { [key: string]: A }; 1555 | 1556 | declare function pickAll( 1557 | keys: Array, 1558 | ...rest: Array 1559 | ): (val: { [key: string]: A }) => { [key: string]: ?A }; 1560 | declare function pickAll( 1561 | keys: Array, 1562 | val: { [key: string]: A } 1563 | ): { [key: string]: ?A }; 1564 | 1565 | declare function pickBy( 1566 | fn: BinaryPredicateFn2, 1567 | ...rest: Array 1568 | ): (val: { [key: string]: A }) => { [key: string]: A }; 1569 | declare function pickBy( 1570 | fn: BinaryPredicateFn2, 1571 | val: { [key: string]: A } 1572 | ): { [key: string]: A }; 1573 | 1574 | declare function project( 1575 | keys: Array, 1576 | ...rest: Array 1577 | ): (val: Array<{ [key: string]: T }>) => Array<{ [key: string]: T }>; 1578 | declare function project( 1579 | keys: Array, 1580 | val: Array<{ [key: string]: T }> 1581 | ): Array<{ [key: string]: T }>; 1582 | 1583 | declare function prop( 1584 | key: T, 1585 | ...rest: Array 1586 | ): (o: O) => $ElementType; 1587 | declare function prop( 1588 | __: $npm$ramda$Placeholder, 1589 | o: O 1590 | ): (key: T) => $ElementType; 1591 | declare function prop(key: T, o: O): $ElementType; 1592 | 1593 | declare function propOr( 1594 | or: T, 1595 | ...rest: Array 1596 | ): ((p: $Keys, ...rest: Array) => (o: A) => V | T) & 1597 | ((p: $Keys, o: A) => V | T); 1598 | declare function propOr( 1599 | or: T, 1600 | p: $Keys, 1601 | ...rest: Array 1602 | ): (o: A) => V | T; 1603 | declare function propOr( 1604 | or: T, 1605 | p: $Keys, 1606 | o: A 1607 | ): V | T; 1608 | 1609 | declare function keysIn(o: Object): Array; 1610 | 1611 | declare function props( 1612 | keys: Array, 1613 | ...rest: Array 1614 | ): (o: O) => Array<$ElementType>; 1615 | declare function props( 1616 | keys: Array, 1617 | o: O 1618 | ): Array<$ElementType>; 1619 | 1620 | // TODO set 1621 | 1622 | declare function toPairs( 1623 | o: O 1624 | ): Array<[$Keys, T]>; 1625 | 1626 | declare function toPairsIn( 1627 | o: O 1628 | ): Array<[string, T]>; 1629 | 1630 | declare function values(o: O): Array; 1631 | 1632 | declare function valuesIn(o: O): Array; 1633 | 1634 | declare function where( 1635 | predObj: { [key: string]: UnaryPredicateFn }, 1636 | ...rest: Array 1637 | ): (o: { [k: string]: T }) => boolean; 1638 | declare function where( 1639 | predObj: { [key: string]: UnaryPredicateFn }, 1640 | o: { [k: string]: T } 1641 | ): boolean; 1642 | 1643 | declare function whereEq( 1644 | predObj: O, 1645 | ...rest: Array 1646 | ): (o: $Shape) => boolean; 1647 | declare function whereEq( 1648 | predObj: O, 1649 | o: $Shape 1650 | ): boolean; 1651 | 1652 | // TODO view 1653 | 1654 | // *Function 1655 | declare var __: $npm$ramda$Placeholder; 1656 | 1657 | declare var T: (_: any) => true; 1658 | declare var F: (_: any) => false; 1659 | 1660 | declare function addIndex( 1661 | iterFn: (fn: (x: A) => B, xs: Array) => Array 1662 | ): (fn: (x: A, idx: number, xs: Array) => B, xs: Array) => Array; 1663 | 1664 | declare function always(x: T): (x: any) => T; 1665 | 1666 | declare function ap( 1667 | fns: Array<(x: T) => V>, 1668 | ...rest: Array 1669 | ): (xs: Array) => Array; 1670 | declare function ap(fns: Array<(x: T) => V>, xs: Array): Array; 1671 | 1672 | declare function apply( 1673 | fn: (...args: Array) => V, 1674 | ...rest: Array 1675 | ): (xs: Array) => V; 1676 | declare function apply(fn: (...args: Array) => V, xs: Array): V; 1677 | 1678 | declare function applySpec< 1679 | V, 1680 | S, 1681 | A: Array, 1682 | T: NestedObject<(...args: A) => S> 1683 | >( 1684 | spec: T 1685 | ): (...args: A) => NestedObject; 1686 | 1687 | declare function binary( 1688 | fn: (...args: Array) => T 1689 | ): (x: any, y: any) => T; 1690 | 1691 | declare function bind( 1692 | fn: (...args: Array) => any, 1693 | thisObj: T 1694 | ): (...args: Array) => any; 1695 | 1696 | declare function call( 1697 | fn: (...args: Array) => T, 1698 | ...args: Array 1699 | ): T; 1700 | 1701 | declare function comparator( 1702 | fn: BinaryPredicateFn 1703 | ): (x: T, y: T) => number; 1704 | 1705 | // TODO add tests 1706 | declare function construct( 1707 | ctor: Class> 1708 | ): (x: T) => GenericContructor; 1709 | 1710 | // TODO add tests 1711 | declare function constructN( 1712 | n: number, 1713 | ctor: Class> 1714 | ): (...args: any) => GenericContructorMulti; 1715 | 1716 | // TODO make less generic 1717 | declare function converge(after: Function, fns: Array): Function; 1718 | 1719 | declare function empty(x: T): T; 1720 | 1721 | declare function flip( 1722 | fn: (arg0: A, arg1: B) => TResult 1723 | ): CurriedFunction2; 1724 | declare function flip( 1725 | fn: (arg0: A, arg1: B, arg2: C) => TResult 1726 | ): ((arg0: B, arg1: A, ...rest: Array) => (arg2: C) => TResult) & 1727 | ((arg0: B, arg1: A, arg2: C) => TResult); 1728 | declare function flip( 1729 | fn: (arg0: A, arg1: B, arg2: C, arg3: D) => TResult 1730 | ): (( 1731 | arg1: B, 1732 | arg0: A, 1733 | ...rest: Array 1734 | ) => (arg2: C, arg3: D) => TResult) & 1735 | ((arg1: B, arg0: A, arg2: C, arg3: D) => TResult); 1736 | declare function flip( 1737 | fn: (arg0: A, arg1: B, arg2: C, arg3: D, arg4: E) => TResult 1738 | ): (( 1739 | arg1: B, 1740 | arg0: A, 1741 | ...rest: Array 1742 | ) => (arg2: C, arg3: D, arg4: E) => TResult) & 1743 | ((arg1: B, arg0: A, arg2: C, arg3: D, arg4: E) => TResult); 1744 | 1745 | declare function identity(x: T): T; 1746 | 1747 | declare function invoker( 1748 | arity: number, 1749 | name: $Enum 1750 | ): CurriedFunction2 & 1751 | CurriedFunction3 & 1752 | CurriedFunction4; 1753 | 1754 | declare function juxt( 1755 | fns: Array<(...args: Array) => T> 1756 | ): (...args: Array) => Array; 1757 | 1758 | // TODO lift 1759 | 1760 | // TODO liftN 1761 | 1762 | declare function memoize) => B>(fn: T): T; 1763 | 1764 | declare function nAry( 1765 | arity: number, 1766 | fn: (...args: Array) => T 1767 | ): (...args: Array) => T; 1768 | 1769 | declare function nthArg(n: number): (...args: Array) => T; 1770 | 1771 | declare function of(x: T): Array; 1772 | 1773 | declare function once) => B>(fn: T): T; 1774 | 1775 | declare var partial: Partial; 1776 | // TODO partialRight 1777 | // TODO pipeK 1778 | 1779 | declare function tap(fn: (x: T) => any, ...rest: Array): (x: T) => T; 1780 | declare function tap(fn: (x: T) => any, x: T): T; 1781 | 1782 | declare function tryCatch( 1783 | tryer: (a: A) => B 1784 | ): ((catcher: (e: E, a: A) => B) => (a: A) => B) & 1785 | ((catcher: (e: E, a: A) => B, a: A) => B); 1786 | declare function tryCatch( 1787 | tryer: (a: A) => B, 1788 | catcher: (e: E, a: A) => B 1789 | ): (a: A) => B; 1790 | declare function tryCatch( 1791 | tryer: (a: A) => B, 1792 | catcher: (e: E, a: A) => B, 1793 | a: A 1794 | ): B; 1795 | 1796 | declare function unapply( 1797 | fn: (xs: Array) => V 1798 | ): (...args: Array) => V; 1799 | 1800 | declare function unary(fn: (...args: Array) => T): (x: any) => T; 1801 | 1802 | declare var uncurryN: ((2, (A) => B => C) => (A, B) => C) & 1803 | ((3, (A) => B => C => D) => (A, B, C) => D) & 1804 | ((4, (A) => B => C => D => E) => (A, B, C, D) => E) & 1805 | (( 1806 | 5, 1807 | (A) => B => C => D => E => F 1808 | ) => (A, B, C, D, E) => F) & 1809 | (( 1810 | 6, 1811 | (A) => B => C => D => E => F => G 1812 | ) => (A, B, C, D, E, F) => G) & 1813 | (( 1814 | 7, 1815 | (A) => B => C => D => E => F => G => H 1816 | ) => (A, B, C, D, E, F, G) => H) & 1817 | (( 1818 | 8, 1819 | (A) => B => C => D => E => F => G => H => I 1820 | ) => (A, B, C, D, E, F, G, H) => I); 1821 | 1822 | //TODO useWith 1823 | 1824 | declare function wrap) => B>( 1825 | fn: F, 1826 | fn2: (fn: F, ...args: Array) => D 1827 | ): (...args: Array) => D; 1828 | 1829 | // *Logic 1830 | 1831 | declare function allPass( 1832 | fns: Array<(...args: Array) => boolean> 1833 | ): (...args: Array) => boolean; 1834 | 1835 | declare function and( 1836 | x: boolean, 1837 | ...rest: Array 1838 | ): (y: boolean) => boolean; 1839 | declare function and(x: boolean, y: boolean): boolean; 1840 | 1841 | declare function anyPass( 1842 | fns: Array<(...args: Array) => boolean> 1843 | ): (...args: Array) => boolean; 1844 | 1845 | declare function both( 1846 | x: (...args: Array) => boolean, 1847 | ...rest: Array 1848 | ): (y: (...args: Array) => boolean) => (...args: Array) => boolean; 1849 | declare function both( 1850 | x: (...args: Array) => boolean, 1851 | y: (...args: Array) => boolean 1852 | ): (...args: Array) => boolean; 1853 | 1854 | declare function complement( 1855 | x: (...args: Array) => boolean 1856 | ): (...args: Array) => boolean; 1857 | 1858 | declare function cond( 1859 | fns: Array<[(...args: Array) => boolean, (...args: Array) => B]> 1860 | ): (...args: Array) => B; 1861 | 1862 | declare function defaultTo( 1863 | d: T, 1864 | ...rest: Array 1865 | ): (x: ?V) => V | T; 1866 | declare function defaultTo(d: T, x: ?V): V | T; 1867 | 1868 | declare function either( 1869 | x: (...args: Array) => *, 1870 | ...rest: Array 1871 | ): (y: (...args: Array) => *) => (...args: Array) => *; 1872 | declare function either( 1873 | x: (...args: Array) => *, 1874 | y: (...args: Array) => * 1875 | ): (...args: Array) => *; 1876 | 1877 | declare function ifElse( 1878 | cond: (...args: Array) => boolean, 1879 | ...rest: Array 1880 | ): (( 1881 | f1: (...args: Array) => B, 1882 | ...rest: Array 1883 | ) => (f2: (...args: Array) => C) => (...args: Array) => B | C) & 1884 | (( 1885 | f1: (...args: Array) => B, 1886 | f2: (...args: Array) => C 1887 | ) => (...args: Array) => B | C); 1888 | declare function ifElse( 1889 | cond: (...args: Array) => boolean, 1890 | f1: (...args: Array) => B, 1891 | f2: (...args: Array) => C 1892 | ): (...args: Array) => B | C; 1893 | 1894 | declare function isEmpty(x: ?Array | Object | string): boolean; 1895 | 1896 | declare function not(x: boolean): boolean; 1897 | 1898 | declare function or(x: boolean, y: boolean): boolean; 1899 | declare function or(x: boolean): (y: boolean) => boolean; 1900 | 1901 | declare var pathSatisfies: CurriedFunction3< 1902 | UnaryPredicateFn, 1903 | string[], 1904 | Object, 1905 | boolean 1906 | >; 1907 | 1908 | declare function propSatisfies( 1909 | cond: (x: T) => boolean, 1910 | prop: string, 1911 | o: NestedObject 1912 | ): boolean; 1913 | declare function propSatisfies( 1914 | cond: (x: T) => boolean, 1915 | prop: string, 1916 | ...rest: Array 1917 | ): (o: NestedObject) => boolean; 1918 | declare function propSatisfies( 1919 | cond: (x: T) => boolean, 1920 | ...rest: Array 1921 | ): ((prop: string, ...rest: Array) => (o: NestedObject) => boolean) & 1922 | ((prop: string, o: NestedObject) => boolean); 1923 | 1924 | declare function unless( 1925 | pred: UnaryPredicateFn, 1926 | ...rest: Array 1927 | ): ((fn: (x: S) => V, ...rest: Array) => (x: T | S) => T | V) & 1928 | ((fn: (x: S) => V, x: T | S) => T | V); 1929 | declare function unless( 1930 | pred: UnaryPredicateFn, 1931 | fn: (x: S) => V, 1932 | ...rest: Array 1933 | ): (x: T | S) => V | T; 1934 | declare function unless( 1935 | pred: UnaryPredicateFn, 1936 | fn: (x: S) => V, 1937 | x: T | S 1938 | ): T | V; 1939 | 1940 | declare function until( 1941 | pred: UnaryPredicateFn, 1942 | ...rest: Array 1943 | ): ((fn: (x: T) => T, ...rest: Array) => (x: T) => T) & 1944 | ((fn: (x: T) => T, x: T) => T); 1945 | declare function until( 1946 | pred: UnaryPredicateFn, 1947 | fn: (x: T) => T, 1948 | ...rest: Array 1949 | ): (x: T) => T; 1950 | declare function until( 1951 | pred: UnaryPredicateFn, 1952 | fn: (x: T) => T, 1953 | x: T 1954 | ): T; 1955 | 1956 | declare function when( 1957 | pred: UnaryPredicateFn, 1958 | ...rest: Array 1959 | ): ((fn: (x: S) => V, ...rest: Array) => (x: T | S) => T | V) & 1960 | ((fn: (x: S) => V, x: T | S) => T | V); 1961 | declare function when( 1962 | pred: UnaryPredicateFn, 1963 | fn: (x: S) => V, 1964 | ...rest: Array 1965 | ): (x: T | S) => V | T; 1966 | declare function when( 1967 | pred: UnaryPredicateFn, 1968 | fn: (x: S) => V, 1969 | x: T | S 1970 | ): T | V; 1971 | } 1972 | -------------------------------------------------------------------------------- /flow-typed/src/index.flow.js: -------------------------------------------------------------------------------- 1 | // NOTE separate flow type declaration for src/**/*.js 2 | 3 | declare type Robot = { 4 | on: function, 5 | } 6 | 7 | declare type GetContentPara = { 8 | owner: string, 9 | repo: string, 10 | path?: string, 11 | } 12 | 13 | declare type Payload = { 14 | issue: any, 15 | repository: any, 16 | comment: any, 17 | pull_request: any, 18 | } 19 | 20 | declare type Context = { 21 | payload: Payload, 22 | github: any, 23 | issue: { body: string } => string, 24 | } 25 | 26 | declare type Ramda = { 27 | pipe: (...args: Array) => function, 28 | match: function, 29 | path: function, 30 | test: function, 31 | ifElse: function, 32 | } 33 | 34 | declare type Command = { 35 | action: string, 36 | options: Object, 37 | } 38 | 39 | declare type Template = { 40 | name: string, 41 | download_url: string, 42 | } 43 | -------------------------------------------------------------------------------- /jobs/deploy-heroku.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | source .env 5 | 6 | 7 | # config heroku app 8 | heroku config:set APP_ID=$APP_ID \ 9 | WEBHOOK_SECRET=$WEBHOOK_SECRET \ 10 | PRIVATE_KEY="$(cat ./*.private-key.pem)" 1>/dev/null 11 | 12 | # deploy heroku app 13 | git push heroku master -f 14 | git tag "deploy-$(date '+%Y-%m-%d-%Hh_%Mm')" 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gh-template-bot", 3 | "version": "0.1.0-alpha", 4 | "description": "Bot to generate markdown templates for different issues and pull requests", 5 | "author": "liuderchi ", 6 | "license": "ISC", 7 | "repository": "https://github.com/liuderchi/gh-template-bot.git", 8 | "scripts": { 9 | "start": "probot run ./src/index.js", 10 | "start:nodemon": "nodemon --exec 'npm start'", 11 | "jest": "jest", 12 | "eslint": "eslint ./", 13 | "flow": "flow check", 14 | "codecov": "codecov", 15 | "lint": "npm run eslint", 16 | "test": "npm run jest && npm run flow && npm run codecov", 17 | "changelog": "github-changes -o liuderchi -r gh-template-bot -b master -f ./CHANGELOG.md -t CHANGELOG --order-semver --use-commit-body" 18 | }, 19 | "dependencies": { 20 | "handlebars": "^4.1.2", 21 | "minimist": "^1.2.0", 22 | "probot": "^3.0.0", 23 | "ramda": "^0.25.0", 24 | "request": "^2.83.0", 25 | "request-promise": "^4.2.2" 26 | }, 27 | "devDependencies": { 28 | "codecov": "^3.0.0", 29 | "eslint": "^4.18.2", 30 | "eslint-plugin-prettier": "^2.3.1", 31 | "flow-bin": "^0.59.0", 32 | "github-changes": "^1.1.1", 33 | "jest": "^21.2.1", 34 | "localtunnel": "^1.8.2", 35 | "nodemon": "^1.12.1", 36 | "prettier": "^1.8.2", 37 | "standard": "^10.0.3" 38 | }, 39 | "engines": { 40 | "node": ">= 10" 41 | }, 42 | "jest": { 43 | "testEnvironment": "node", 44 | "collectCoverage": true, 45 | "collectCoverageFrom": [ 46 | "src/**/*.{js,jsx}", 47 | "!src/**/*.test.{js,jsx}", 48 | "!src/**/*.flow.js" 49 | ], 50 | "coverageDirectory": "./coverage/", 51 | "testPathIgnorePatterns": [ 52 | "/node_modules/", 53 | "/coverage/", 54 | "/flow-typed/" 55 | ] 56 | }, 57 | "standard": { 58 | "env": [ 59 | "jest" 60 | ] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | const { handleIssueWH, handleIssueCommentWH, handlePullRequestWH } = require('./webhookHandler') 4 | 5 | module.exports = (robot /*: Robot */) => { 6 | robot.on(['issues.opened', 'issues.edited'], handleIssueWH) 7 | robot.on(['issue_comment.created', 'issue_comment.edited'], handleIssueCommentWH) 8 | robot.on(['pull_request.opened', 'pull_request.edited'], handlePullRequestWH) 9 | } 10 | -------------------------------------------------------------------------------- /src/templates/dialog.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 🤖 Hello {{ withDefault username "Human" }}! I Understand These Commands: 4 | 5 | ### `/template issue` 6 | 7 | open `.github/ISSUE_TEMPLATE.md` or a *[sample issue][issue]* 8 | 9 | ### `/template pr` 10 | 11 | open `.github/PULL_REQUEST_TEMPLATE.md` or a *[sample pull request][pr]* 12 | 13 | ### `/template feature` 14 | 15 | open *[a template to propose new feature][feature]* 16 | 17 | ### `/template duplicate --num 23` 18 | 19 | open custom [Handlebars Template][handlebarsjs], in this case `.github/duplicate.md` with `num` set to 23 20 | 21 | for example, you've had `.github/duplicate.md` like [this][example]: 22 | 23 | ```markdown 24 | 25 | 😢 This is duplicate of #{{ withDefault __ "{{ num }}" }}. 26 | ``` 27 | 28 | I would say `😢 This is duplicate of #23.` 29 | 30 | --- 31 | 32 | > Remember to :recycle:**Refresh This Page** after updating your command. 33 | 34 | [issue]: https://github.com/TalAter/open-source-templates 35 | [pr]: https://raw.githubusercontent.com/stevemao/github-issue-templates/master/simple/PULL_REQUEST_TEMPLATE.md 36 | [feature]: https://github.com/TalAter/open-source-templates 37 | [handlebarsjs]: http://handlebarsjs.com/ 38 | [example]: https://github.com/liuderchi/gh-template-bot/blob/master/src/templates/duplicate.md 39 | -------------------------------------------------------------------------------- /src/templates/duplicate.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 😢 This is duplicate of #{{ num }}. 4 | -------------------------------------------------------------------------------- /src/templates/feature.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## Detailed Description 6 | 7 | 8 | ## Context 9 | 10 | 11 | 12 | ## Possible Implementation 13 | 14 | 15 | ## Your Environment 16 | 17 | * Version used: 18 | * Environment name and version (e.g. Chrome 39, node.js 5.4): 19 | * Operating System and version (desktop or mobile): 20 | * Link to your project: 21 | -------------------------------------------------------------------------------- /src/templates/issue.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ## Description 7 | 8 | 9 | ## Expected Behavior 10 | 11 | 12 | ## Actual Behavior 13 | 14 | 15 | ## Possible Fix 16 | 17 | 18 | ## Steps to Reproduce 19 | 20 | 21 | 1. 22 | 2. 23 | 3. 24 | 4. 25 | 26 | ## Context 27 | 28 | 29 | ## Your Environment 30 | 31 | * Version used: 32 | * Environment name and version (e.g. Chrome 39, node.js 5.4): 33 | * Operating System and version (desktop or mobile): 34 | * Link to your project: 35 | -------------------------------------------------------------------------------- /src/templates/pr.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Fixes #{{ n }} 5 | 6 | ## Proposed Changes 7 | 8 | - 9 | - 10 | - 11 | -------------------------------------------------------------------------------- /src/utils/__tests__/template.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const { getCommand, validateAction, getMDContent } = require('../template') 4 | 5 | describe('getCommand()', () => { 6 | test('returns null action when issue body is empty', () => { 7 | expect(getCommand('')) 8 | .toMatchObject({ 9 | action: null, 10 | }) 11 | }) 12 | test('returns null action when issue body starts with `/Template` which is not fully match', () => { 13 | expect(getCommand('/Template foo')) 14 | .toMatchObject({ 15 | action: null, 16 | }) 17 | }) 18 | test('returns Dialog action when issue body starts with `/template`, but not match issue|pr|feature', () => { 19 | expect(getCommand('\n\n /template\t ')) 20 | .toMatchObject({ 21 | action: 'DIALOG', 22 | }) 23 | }) 24 | test('returns Specific action when issue body starts with `/template`, but not match issue|pr|feature', () => { 25 | expect(getCommand('/template foo ')) 26 | .toMatchObject({ 27 | action: 'FOO', 28 | }) 29 | expect(getCommand('/template features')) 30 | .toMatchObject({ 31 | action: 'FEATURES', 32 | }) 33 | }) 34 | test('returns Specific action with options when issue body contains option syntax', () => { 35 | expect(getCommand('/template issue --number 123')) 36 | .toMatchObject({ 37 | action: 'ISSUE', 38 | options: { 39 | number: 123, 40 | }, 41 | }) 42 | expect(getCommand('/template issue dummy -f --name derek --action filtered')) 43 | .toMatchObject({ 44 | action: 'ISSUE', 45 | options: { 46 | f: true, 47 | name: 'derek', 48 | }, 49 | }) 50 | }) 51 | test('returns null action when issue body not starts with `/template`, without special markdown checkbox format', () => { 52 | expect(getCommand('\nsome words\n/template pr')) 53 | .toMatchObject({ 54 | action: null, 55 | }) 56 | }) 57 | test('returns correspond action when issue body with checked markdown checkbox format', () => { 58 | expect(getCommand('Please pick one template:\n\n - [x] `/template feature`')) 59 | .toMatchObject({ 60 | action: 'FEATURE', 61 | }) 62 | 63 | expect(getCommand('Please pick one template:\n\n - [ ] `/template pr`\n - [x] `/template Issue`')) 64 | .toMatchObject({ 65 | action: 'ISSUE', 66 | }) 67 | }) 68 | 69 | }) 70 | 71 | describe('getMDContent()', () => { 72 | 73 | test('insert dialog without options', async () => { 74 | const newContent = await getMDContent( 75 | { 76 | action: 'DIALOG', 77 | options: {}, 78 | }, 79 | [], 80 | '/template' 81 | ) 82 | expect(newContent.split('\n')[2]) 83 | .toBe('## 🤖 Hello Human! I Understand These Commands:')}) 84 | 85 | test('insert dialog with options', async () => { 86 | const newContent = await getMDContent( 87 | { 88 | action: 'DIALOG', 89 | options: {username: 'derek'}, 90 | }, 91 | [], 92 | '/template --username derek' 93 | ) 94 | expect(newContent.split('\n')[2]) 95 | .toBe('## 🤖 Hello derek! I Understand These Commands:')}) 96 | }) 97 | 98 | describe('validateAction()', () => { 99 | 100 | test('if action is not a preserve word nor match any templates, modify it to default `DIALOG`', () => { 101 | const command = { 102 | action: 'NO_SUCH_DOC', 103 | options: {}, 104 | } 105 | const templates = [ 106 | { name: 'SOME_DOC.md', download_url: 'https://foo.bar/some_doc.md' } , 107 | ] 108 | validateAction(command, templates) 109 | expect(command.action).toBe('DIALOG') 110 | }) 111 | 112 | test('if action is not a preserve word but match some template, do not modify it', () => { 113 | const action = 'SOME_DOC' 114 | const command = { 115 | action, 116 | options: {}, 117 | } 118 | const templates = [ 119 | { name: 'SOME_DOC.md', download_url: 'https://foo.bar/some_doc.md' } , 120 | ] 121 | validateAction(command, templates) 122 | expect(command.action).toBe(action) 123 | 124 | command.action = 'pr' 125 | validateAction(command, templates) 126 | expect(command.action).toBe('pr') 127 | }) 128 | }) 129 | -------------------------------------------------------------------------------- /src/utils/ghAPI.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | const R = require('ramda') 4 | 5 | const getCustomTemplates /*: (Object, GetContentPara) => Promise> */ = async ( 6 | gitHubContext, 7 | { owner, repo, path='.github' } 8 | ) => { 9 | const { repos: { getContent } } = gitHubContext 10 | try { 11 | const { data: customTemplates } = await getContent({ owner, repo, path }) 12 | return customTemplates 13 | .filter(({ name, type }) => R.match(/\.md$/, name).length > 0 && type === 'file') 14 | .map(R.pick(['name', 'download_url'])) 15 | } catch (e) { 16 | console.error(e) 17 | return [] 18 | } 19 | } 20 | 21 | 22 | module.exports = { 23 | getCustomTemplates, 24 | } 25 | -------------------------------------------------------------------------------- /src/utils/handlebars.js: -------------------------------------------------------------------------------- 1 | //@flow 2 | 3 | const Handlebars = require('handlebars') 4 | 5 | Handlebars.registerHelper('withDefault', (x, defaultValue) => x ? x : defaultValue) 6 | 7 | module.exports = { 8 | Handlebars, 9 | } 10 | -------------------------------------------------------------------------------- /src/utils/template.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | const R /*: Ramda */ = require('ramda') 6 | const minimist = require('minimist') 7 | const rp /*: string => Promise */ = require('request-promise') 8 | 9 | const { Handlebars } = require('./handlebars') 10 | 11 | 12 | const getCommand /*: string => Command */ = issueBody => { 13 | const cmdRegexForDialog = /[-*] \[x\] `\/template\s+((issue|pr|feature)`)/im 14 | const getActionInDialog /*: string => string */ = R.pipe(R.match(cmdRegexForDialog), R.path(['2'])) 15 | 16 | const tokenize /*: string => Object */ = R.pipe( 17 | str => str.trim().split('\n')[0].trim().split(/\s/), 18 | minimist 19 | ) 20 | 21 | const getAction /*: string => string|null */ = issueBody => { 22 | const { _: [ directive, action = 'DIALOG' ] } = tokenize(issueBody) 23 | return (directive === '/template') ? action.toUpperCase() : null 24 | } 25 | 26 | const getOptions /*: string => Object */ = issueBody => { 27 | const { _: [ directive ], ...options } = tokenize(issueBody) 28 | return (directive === '/template') ? options : {} 29 | } 30 | 31 | return { 32 | action: R.ifElse( 33 | getActionInDialog, 34 | R.pipe( 35 | getActionInDialog, 36 | action => action.toUpperCase() 37 | ), 38 | getAction 39 | )(issueBody), 40 | options: getOptions(issueBody), 41 | } 42 | } 43 | 44 | const matchAction /*: string => Template => boolean */ = action => ({ name }) => name.toLowerCase() === `${action.toLowerCase()}.md` 45 | 46 | const validateAction /*: (Command, Array