├── .gitignore ├── .nvmrc ├── .travis.yml ├── LICENSE ├── README.md ├── bin └── flow-scripts.js ├── fixtures ├── .flowconfig ├── package.json ├── src │ ├── Bar.jsx │ ├── Foo.jsx │ ├── Qux.jsx │ ├── bar.js │ ├── baz.js │ ├── foo.js │ └── qux.js └── yarn.lock ├── flow-typed └── package-dep-libdefs.js ├── lib ├── cli.js ├── commands │ ├── index.js │ ├── stub.js │ └── unmonitored.js └── constants.js ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | 30 | # Testing dirs 31 | flow-typed 32 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 6.10.3 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '6' 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Tay Yang Shun 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flow Scripts 2 | 3 | Utility tools for Flow. Provides a few helpful functions like generating stubs and finding files that are not covered by Flow. Refer to the [commands section](#available-commands) for more. 4 | 5 | If you have suggestions for further commands, feel free to [create an issue](https://github.com/yangshun/flow-scripts/issues/new). 6 | 7 | ## Installation 8 | 9 | ``` 10 | $ npm install -g flow-scripts 11 | $ flow-scripts [options] 12 | ``` 13 | 14 | ## Available Commands 15 | 16 | - [`stub`](#stub) 17 | - [`unmonitored`](#unmonitored) 18 | 19 | ## `Stub` 20 | 21 | ``` 22 | $ flow-scripts stub 23 | ``` 24 | 25 | #### What it does 26 | 27 | Generates naive stubs for the packages that your project requires. To be used with `flowignore`-ing of `node_modules` for faster start up times. 28 | 29 | #### When should you use this? 30 | 31 | If you are: 32 | 33 | 1. You are thoroughly annoyed by your web app project taking so long to start up because of Flow and want to `flowignore` the `node_modules` folder 34 | 1. You do not want to check in community libdefs into your repository 35 | 1. You are okay with not having Flow libdefs for external libraries. 36 | 37 | It also possible to combine usage of `flow-typed install` with `flow-scripts stub` as stubs for existing libdefs found in `flow-typed/npm/` will not be generated. 38 | 39 | #### Motivation 40 | 41 | By default, running Flow on start up will read all the files under `node_modules`. This takes very very long and it is a huge pain to be waiting that long each time your web app starts. According to Facebook, ignoring the `node_modules` directory isn't a good idea because Flow looks in there to a) ensure you've actually installed your dependencies and b) find Flow libdefs for packages which might have included them, and Flow will throw a `Required module not found` error. Refer to this [issue](https://github.com/facebook/flow/issues/869) for an in-depth discussion on the topic. 42 | 43 | However, combined with the inclusion of libdefs (or stubs) for external libraries, ignoring `node_modules` might not seem like that bad an idea after all. 44 | 45 | #### Workaround 46 | 47 | The workaround is to `flowignore` the `node_modules` directory and include the libdefs inside the `flow-typed/` directory or provide a stub for it. This can be done manually or automatically via the `flow-typed install` command. 48 | 49 | The `flow-typed install` command does fetch community libdefs and generates stubs pretty well, but has a few problems: 50 | 51 | 1. Some users might not want to fetch community libdefs because it adds many files to the source. 52 | 1. The libdefs of some libraries are not pulled into `flow-typed/npm/`, such as `immutable` because it is already present in `node_modules/immutable`. This is not picked up because we `flowignore` the `node_modules`. 53 | 54 | The `flow-scripts stub` command fixes some of these problems by generating the stubs required for the `dependencies` in `package.json`. If there are existing libdef files in the `flow-typed/npm` directory, the stubs for these libraries will not be generated. 55 | 56 | In `.flowconfig`, add: 57 | 58 | ``` 59 | [ignore] 60 | .*node_modules/.* 61 | ``` 62 | 63 | In the project directory, run: 64 | 65 | ``` 66 | $ flow-scripts stub 67 | ``` 68 | 69 | This will do the following: 70 | 71 | 1. Tell Flow to ignore checking of `node_modules`. 72 | 2. Generates the stubs required for the `dependencies` in `package.json` that are not present in `flow-typed/npm/` and write them into `flow-typed/package-dep-libdefs.js`. 73 | 74 | **Optional:** By adding the script to an npm script `postinstall` hook, when new packages are installed, it will be automatically added into `flow-typed/`. It would be recommended to save `flow-scripts` as a `devDependency` rather than a global dependency in this case. 75 | 76 | In `package.json`, add this `postinstall` hook: 77 | 78 | ``` 79 | "scripts": { 80 | "postinstall": "flow-scripts stub" 81 | }, 82 | ``` 83 | 84 | #### Known Issues 85 | 86 | - A very barebones stub of the library is being generated based solely on the package name. If you are using `lodash` and want to import a specific function like `lodash/omit`, it will not work as the stub generated by `flow-scripts stub` is for `lodash` and not `lodash/omit`. In that case, you might want to pull in a community libdef from [flow-typed](https://github.com/flowtype/flow-typed) instead. 87 | 88 | #### TODO 89 | 90 | - Pull out Flow libdefs for packages that already contain them such as `immutable`. 91 | 92 | ## `Unmonitored` 93 | 94 | ``` 95 | $ flow-scripts unmonitored [options] [pattern] 96 | ``` 97 | 98 | #### What it does 99 | 100 | Searches for files matching the specified [glob pattern](https://www.wikiwand.com/en/Glob_(programming)) and lists the files that do not contain `@flow`. Files that have `@noflow` are ignored. If `pattern` is not specified, it defaults to `./**/*.{js,jsx}`. Please note that this commands works on files only, and not directories, hence you will have to explicitly specify a file extension. You will also have to quote your parameter (use double quotes if you need it to run in Windows). An example as follows: 101 | 102 | ``` 103 | $ flow-scripts unmonitored "src/**/*.js" 104 | ``` 105 | 106 | #### Options 107 | 108 | - `--fix`: Automatically fix those files by adding `// @flow` at the top. 109 | 110 | ## Development 111 | 112 | Testing this library is tricky because it relies on a real project that has multiple dependencies in `package.json`. Hence we create a mock project in the `fixtures` folder that has some common JS dependencies defined and symlink the `flow-scripts` library within that project to our development file in the root folder. Run the commands within that mock project to test that the library is actually working as intended. 113 | 114 | ``` 115 | $ cd test-project 116 | $ npm install # or yarn install 117 | $ npm link ../ 118 | $ flow-scripts stub # flow-typed/package-dep-libdefs.js file should be generated 119 | ``` 120 | 121 | ## License 122 | 123 | MIT 124 | -------------------------------------------------------------------------------- /bin/flow-scripts.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const commander = require('commander'); 4 | const pkg = require('../package.json'); 5 | const cli = require('../lib/cli'); 6 | const constants = require('../lib/constants'); 7 | 8 | commander 9 | .version(pkg.version) 10 | .usage('[command] [flags]'); 11 | 12 | console.log('flow-scripts %s\n', pkg.version); 13 | 14 | commander 15 | .command('stub') 16 | .description('Generates naive flow-typed stubs for packages in dependencies') 17 | .action(() => { 18 | cli.execute('stub'); 19 | }); 20 | 21 | commander 22 | .command('unmonitored [pattern]') 23 | .description(`Lists the files matching the specified glob pattern that do not contain "${constants.FLOW_MARKER}"`) 24 | .option('--fix', `Adds "${constants.FLOW_MARKER}" to the unmonitored files`) 25 | .action((pattern, options) => { 26 | cli.execute('unmonitored', { pattern }, { fix: options.fix }); 27 | }); 28 | 29 | commander.parse(process.argv); 30 | -------------------------------------------------------------------------------- /fixtures/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [options] 8 | -------------------------------------------------------------------------------- /fixtures/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flow-scripts-test-project", 3 | "scripts": { 4 | "postinstall": "flow-scripts stub" 5 | }, 6 | "dependencies": { 7 | "babel-polyfill": "6.22.0", 8 | "classnames": "2.2.5", 9 | "immutable": "^3.8.1", 10 | "lodash": "4.17.4", 11 | "moment": "2.17.1", 12 | "raven-js": "3.9.1", 13 | "react": "15.4.2", 14 | "react-autobind": "1.0.6", 15 | "react-document-title": "2.0.2", 16 | "react-dom": "15.4.2", 17 | "react-ga": "2.1.2", 18 | "react-google-login": "^2.8.2", 19 | "react-redux": "5.0.2", 20 | "react-router": "3.0.2", 21 | "react-router-redux": "4.0.7", 22 | "redux": "3.6.0", 23 | "redux-logger": "2.7.4", 24 | "redux-thunk": "2.2.0" 25 | }, 26 | "devDependencies": { 27 | "flow-bin": "0.38.0", 28 | "flow-scripts": "file:.." 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /fixtures/src/Bar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | function Bar(props) { 5 | return
Bar
; 6 | } 7 | -------------------------------------------------------------------------------- /fixtures/src/Foo.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | function Bar(props) { 7 | return
Foo
; 8 | } 9 | -------------------------------------------------------------------------------- /fixtures/src/Qux.jsx: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | function Bar(props) { 7 | return
Foo
; 8 | } 9 | -------------------------------------------------------------------------------- /fixtures/src/bar.js: -------------------------------------------------------------------------------- 1 | function bar(a, b) { 2 | return a + b; 3 | } 4 | -------------------------------------------------------------------------------- /fixtures/src/baz.js: -------------------------------------------------------------------------------- 1 | // @noflow 2 | function bar(a, b) { 3 | return a + b; 4 | } 5 | -------------------------------------------------------------------------------- /fixtures/src/foo.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | function add(a, b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /fixtures/src/qux.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | function add(a, b) { 4 | return a + b; 5 | } 6 | -------------------------------------------------------------------------------- /fixtures/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/react@*": 6 | version "15.0.12" 7 | resolved "https://registry.yarnpkg.com/@types/react/-/react-15.0.12.tgz#aea95e45631bd745be45d65c2dc02327848212f2" 8 | 9 | asap@~2.0.3: 10 | version "2.0.5" 11 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" 12 | 13 | babel-polyfill@6.22.0: 14 | version "6.22.0" 15 | resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.22.0.tgz#1ac99ebdcc6ba4db1e2618c387b2084a82154a3b" 16 | dependencies: 17 | babel-runtime "^6.22.0" 18 | core-js "^2.4.0" 19 | regenerator-runtime "^0.10.0" 20 | 21 | babel-runtime@^6.22.0: 22 | version "6.23.0" 23 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" 24 | dependencies: 25 | core-js "^2.4.0" 26 | regenerator-runtime "^0.10.0" 27 | 28 | balanced-match@^1.0.0: 29 | version "1.0.0" 30 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 31 | 32 | brace-expansion@^1.1.7: 33 | version "1.1.8" 34 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 35 | dependencies: 36 | balanced-match "^1.0.0" 37 | concat-map "0.0.1" 38 | 39 | classnames@2.2.5: 40 | version "2.2.5" 41 | resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" 42 | 43 | commander@^2.9.0: 44 | version "2.9.0" 45 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 46 | dependencies: 47 | graceful-readlink ">= 1.0.0" 48 | 49 | concat-map@0.0.1: 50 | version "0.0.1" 51 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 52 | 53 | core-js@^1.0.0: 54 | version "1.2.7" 55 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" 56 | 57 | core-js@^2.4.0: 58 | version "2.4.1" 59 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" 60 | 61 | deep-diff@0.3.4: 62 | version "0.3.4" 63 | resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.4.tgz#aac5c39952236abe5f037a2349060ba01b00ae48" 64 | 65 | encoding@^0.1.11: 66 | version "0.1.12" 67 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 68 | dependencies: 69 | iconv-lite "~0.4.13" 70 | 71 | exenv@^1.2.1: 72 | version "1.2.1" 73 | resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.1.tgz#75de1c8dee02e952b102aa17f8875973e0df14f9" 74 | 75 | fbjs@^0.8.1, fbjs@^0.8.4: 76 | version "0.8.9" 77 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14" 78 | dependencies: 79 | core-js "^1.0.0" 80 | isomorphic-fetch "^2.1.1" 81 | loose-envify "^1.0.0" 82 | object-assign "^4.1.0" 83 | promise "^7.1.1" 84 | setimmediate "^1.0.5" 85 | ua-parser-js "^0.7.9" 86 | 87 | flow-bin@0.38.0: 88 | version "0.38.0" 89 | resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.38.0.tgz#3ae096d401c969cc8b5798253fb82381e2d0237a" 90 | 91 | "flow-scripts@file:..": 92 | version "0.4.0" 93 | dependencies: 94 | commander "^2.9.0" 95 | glob "^7.1.2" 96 | lodash "^4.17.4" 97 | 98 | fs.realpath@^1.0.0: 99 | version "1.0.0" 100 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 101 | 102 | glob@^7.1.2: 103 | version "7.1.2" 104 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 105 | dependencies: 106 | fs.realpath "^1.0.0" 107 | inflight "^1.0.4" 108 | inherits "2" 109 | minimatch "^3.0.4" 110 | once "^1.3.0" 111 | path-is-absolute "^1.0.0" 112 | 113 | "graceful-readlink@>= 1.0.0": 114 | version "1.0.1" 115 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 116 | 117 | history@^3.0.0: 118 | version "3.2.1" 119 | resolved "https://registry.yarnpkg.com/history/-/history-3.2.1.tgz#71c7497f4e6090363d19a6713bb52a1bfcdd99aa" 120 | dependencies: 121 | invariant "^2.2.1" 122 | loose-envify "^1.2.0" 123 | query-string "^4.2.2" 124 | warning "^3.0.0" 125 | 126 | hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0: 127 | version "1.2.0" 128 | resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" 129 | 130 | iconv-lite@~0.4.13: 131 | version "0.4.15" 132 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" 133 | 134 | immutable@^3.8.1: 135 | version "3.8.1" 136 | resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2" 137 | 138 | inflight@^1.0.4: 139 | version "1.0.6" 140 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 141 | dependencies: 142 | once "^1.3.0" 143 | wrappy "1" 144 | 145 | inherits@2: 146 | version "2.0.3" 147 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 148 | 149 | invariant@^2.0.0, invariant@^2.2.1: 150 | version "2.2.2" 151 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" 152 | dependencies: 153 | loose-envify "^1.0.0" 154 | 155 | is-stream@^1.0.1: 156 | version "1.1.0" 157 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 158 | 159 | isomorphic-fetch@^2.1.1: 160 | version "2.2.1" 161 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 162 | dependencies: 163 | node-fetch "^1.0.1" 164 | whatwg-fetch ">=0.10.0" 165 | 166 | js-tokens@^3.0.0: 167 | version "3.0.1" 168 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" 169 | 170 | json-stringify-safe@^5.0.1: 171 | version "5.0.1" 172 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 173 | 174 | lodash-es@^4.2.0, lodash-es@^4.2.1: 175 | version "4.17.4" 176 | resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" 177 | 178 | lodash._getnative@^3.0.0: 179 | version "3.9.1" 180 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 181 | 182 | lodash.isarguments@^3.0.0: 183 | version "3.1.0" 184 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 185 | 186 | lodash.isarray@^3.0.0: 187 | version "3.0.4" 188 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 189 | 190 | lodash.keys@^3.1.2: 191 | version "3.1.2" 192 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 193 | dependencies: 194 | lodash._getnative "^3.0.0" 195 | lodash.isarguments "^3.0.0" 196 | lodash.isarray "^3.0.0" 197 | 198 | lodash@4.17.4, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1: 199 | version "4.17.4" 200 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 201 | 202 | loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0: 203 | version "1.3.1" 204 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 205 | dependencies: 206 | js-tokens "^3.0.0" 207 | 208 | minimatch@^3.0.4: 209 | version "3.0.4" 210 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 211 | dependencies: 212 | brace-expansion "^1.1.7" 213 | 214 | moment@2.17.1: 215 | version "2.17.1" 216 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82" 217 | 218 | node-fetch@^1.0.1: 219 | version "1.6.3" 220 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" 221 | dependencies: 222 | encoding "^0.1.11" 223 | is-stream "^1.0.1" 224 | 225 | object-assign@^4.0.1, object-assign@^4.1.0: 226 | version "4.1.1" 227 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 228 | 229 | once@^1.3.0: 230 | version "1.4.0" 231 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 232 | dependencies: 233 | wrappy "1" 234 | 235 | path-is-absolute@^1.0.0: 236 | version "1.0.1" 237 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 238 | 239 | promise@^7.1.1: 240 | version "7.1.1" 241 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" 242 | dependencies: 243 | asap "~2.0.3" 244 | 245 | query-string@^4.2.2: 246 | version "4.3.2" 247 | resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.2.tgz#ec0fd765f58a50031a3968c2431386f8947a5cdd" 248 | dependencies: 249 | object-assign "^4.1.0" 250 | strict-uri-encode "^1.0.0" 251 | 252 | raven-js@3.9.1: 253 | version "3.9.1" 254 | resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.9.1.tgz#d0482100849ea0ab91058308dfa1ec97bc073bac" 255 | dependencies: 256 | json-stringify-safe "^5.0.1" 257 | 258 | react-autobind@1.0.6: 259 | version "1.0.6" 260 | resolved "https://registry.yarnpkg.com/react-autobind/-/react-autobind-1.0.6.tgz#936bb58edf6b89b619c50f82f0e617159fdfd4f1" 261 | 262 | react-document-title@2.0.2: 263 | version "2.0.2" 264 | resolved "https://registry.yarnpkg.com/react-document-title/-/react-document-title-2.0.2.tgz#1e42b672d300f8f90d8d05544b0d71f0ca7860aa" 265 | dependencies: 266 | react-side-effect "^1.0.2" 267 | 268 | react-dom@15.4.2: 269 | version "15.4.2" 270 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f" 271 | dependencies: 272 | fbjs "^0.8.1" 273 | loose-envify "^1.1.0" 274 | object-assign "^4.1.0" 275 | 276 | react-ga@2.1.2: 277 | version "2.1.2" 278 | resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.1.2.tgz#7af206c5e8761d7176e15773fe826acdb70ac653" 279 | dependencies: 280 | object-assign "^4.0.1" 281 | 282 | react-google-login@^2.8.2: 283 | version "2.8.2" 284 | resolved "https://registry.yarnpkg.com/react-google-login/-/react-google-login-2.8.2.tgz#61ad71c3e65e07df2f818ffca1bfa156e072b972" 285 | dependencies: 286 | "@types/react" "*" 287 | 288 | react-redux@5.0.2: 289 | version "5.0.2" 290 | resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.2.tgz#3d9878f5f71c6fafcd45de1fbb162ea31f389814" 291 | dependencies: 292 | hoist-non-react-statics "^1.0.3" 293 | invariant "^2.0.0" 294 | lodash "^4.2.0" 295 | lodash-es "^4.2.0" 296 | loose-envify "^1.1.0" 297 | 298 | react-router-redux@4.0.7: 299 | version "4.0.7" 300 | resolved "https://registry.yarnpkg.com/react-router-redux/-/react-router-redux-4.0.7.tgz#9b1fde4e70106c50f47214e12bdd888cfb96e2a6" 301 | 302 | react-router@3.0.2: 303 | version "3.0.2" 304 | resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.0.2.tgz#5a19156678810e01d81901f9c0fef63284b8a514" 305 | dependencies: 306 | history "^3.0.0" 307 | hoist-non-react-statics "^1.2.0" 308 | invariant "^2.2.1" 309 | loose-envify "^1.2.0" 310 | warning "^3.0.0" 311 | 312 | react-side-effect@^1.0.2: 313 | version "1.1.0" 314 | resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-1.1.0.tgz#57209f7ebc940d55e0fda82fe51422654175d609" 315 | dependencies: 316 | exenv "^1.2.1" 317 | shallowequal "^0.2.2" 318 | 319 | react@15.4.2: 320 | version "15.4.2" 321 | resolved "https://registry.yarnpkg.com/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef" 322 | dependencies: 323 | fbjs "^0.8.4" 324 | loose-envify "^1.1.0" 325 | object-assign "^4.1.0" 326 | 327 | redux-logger@2.7.4: 328 | version "2.7.4" 329 | resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-2.7.4.tgz#891e5d29e7f111d08b5781a237b9965b5858c7f8" 330 | dependencies: 331 | deep-diff "0.3.4" 332 | 333 | redux-thunk@2.2.0: 334 | version "2.2.0" 335 | resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" 336 | 337 | redux@3.6.0: 338 | version "3.6.0" 339 | resolved "https://registry.yarnpkg.com/redux/-/redux-3.6.0.tgz#887c2b3d0b9bd86eca2be70571c27654c19e188d" 340 | dependencies: 341 | lodash "^4.2.1" 342 | lodash-es "^4.2.1" 343 | loose-envify "^1.1.0" 344 | symbol-observable "^1.0.2" 345 | 346 | regenerator-runtime@^0.10.0: 347 | version "0.10.3" 348 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e" 349 | 350 | setimmediate@^1.0.5: 351 | version "1.0.5" 352 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 353 | 354 | shallowequal@^0.2.2: 355 | version "0.2.2" 356 | resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e" 357 | dependencies: 358 | lodash.keys "^3.1.2" 359 | 360 | strict-uri-encode@^1.0.0: 361 | version "1.1.0" 362 | resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" 363 | 364 | symbol-observable@^1.0.2: 365 | version "1.0.4" 366 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" 367 | 368 | ua-parser-js@^0.7.9: 369 | version "0.7.12" 370 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb" 371 | 372 | warning@^3.0.0: 373 | version "3.0.0" 374 | resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" 375 | dependencies: 376 | loose-envify "^1.0.0" 377 | 378 | whatwg-fetch@>=0.10.0: 379 | version "2.0.2" 380 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.2.tgz#fe294d1d89e36c5be8b3195057f2e4bc74fc980e" 381 | 382 | wrappy@1: 383 | version "1.0.2" 384 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 385 | -------------------------------------------------------------------------------- /flow-typed/package-dep-libdefs.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated by flow-scripts. 2 | 3 | declare module 'commander' { 4 | declare module.exports: any; 5 | } 6 | 7 | declare module 'glob' { 8 | declare module.exports: any; 9 | } 10 | 11 | declare module 'lodash' { 12 | declare module.exports: any; 13 | } 14 | -------------------------------------------------------------------------------- /lib/cli.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const commands = require('./commands'); 4 | 5 | const cli = { 6 | execute: function(cmd, args, options) { 7 | if (!commands.hasOwnProperty(cmd)) { 8 | console.error('No execution code found for %s', cmd); 9 | return; 10 | } 11 | commands[cmd](args, options); 12 | }, 13 | }; 14 | 15 | module.exports = cli; 16 | -------------------------------------------------------------------------------- /lib/commands/index.js: -------------------------------------------------------------------------------- 1 | const stub = require('./stub'); 2 | const unmonitored = require('./unmonitored'); 3 | 4 | module.exports = { 5 | stub, 6 | unmonitored, 7 | }; 8 | -------------------------------------------------------------------------------- /lib/commands/stub.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const glob = require('glob'); 3 | const path = require('path'); 4 | const _ = require('lodash'); 5 | 6 | const constants = require('../constants'); 7 | 8 | module.exports = function (args, options) { 9 | const dir = constants.DEFAULT_FLOW_TYPED_DIR; 10 | const filename = constants.DEFAULT_PACKAGE_DEP_LIBDEFS_FILENAME; 11 | if (!fs.existsSync(dir)) { 12 | console.log(`The directory \`${dir}\` does not exist, creating it...`); 13 | fs.mkdirSync(dir); 14 | } 15 | 16 | const libdefDir = path.join(process.cwd(), dir, constants.DEFAULT_FLOW_TYPED_NPM_DIR); 17 | let packagesWithLibdef = constants.DEFAULT_FLOW_LIBDEFS; 18 | if (fs.existsSync(libdefDir)) { 19 | const libdefFiles = fs.readdirSync(libdefDir); 20 | const libdefs = libdefFiles.map(file => { 21 | const [, match] = constants.LIBDEF_REGEX.exec(file) || []; 22 | return match; 23 | }) 24 | .filter(Boolean); 25 | 26 | packagesWithLibdef = packagesWithLibdef.concat(libdefs); 27 | } else { 28 | console.log('No existing community libdefs found. It is recommended to run ' + 29 | '`flow-typed install` first to pull in community libdefs.\n'); 30 | } 31 | 32 | const fullPackagePath = path.join(process.cwd(), 'package.json'); 33 | const pkg = require(fullPackagePath); 34 | const dependencies = Object.keys(pkg.dependencies); 35 | const packagesWithoutLibdef = _.difference(dependencies, packagesWithLibdef); 36 | 37 | let fileContents = '// This file is autogenerated by flow-scripts.\n\n'; 38 | fileContents += packagesWithoutLibdef.map(dep => { 39 | console.log(` Generating stub libdef for "${dep}".`); 40 | return '' + 41 | `declare module '${dep}' { 42 | declare module.exports: any; 43 | }`; 44 | }).join('\n\n') + '\n'; 45 | fs.writeFileSync(`${dir}/${filename}`, fileContents); 46 | console.log(); 47 | console.log(`Wrote generated libdef stubs to \`${process.cwd()}/${dir}/${filename}\``); 48 | }; 49 | -------------------------------------------------------------------------------- /lib/commands/unmonitored.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const glob = require('glob'); 3 | 4 | const constants = require('../constants'); 5 | 6 | module.exports = function (args, options) { 7 | const pattern = args.pattern || './**/*.{js,jsx}'; 8 | const fix = !!options.fix; 9 | glob(pattern, null, (err, files) => { 10 | if (err) { 11 | console.error(err); 12 | process.exit(1); 13 | } 14 | 15 | console.log(`Found ${files.length} file(s) matching the pattern "${pattern}"...`); 16 | if (!files.length) { 17 | return; 18 | } 19 | const unmonitoredFiles = []; 20 | const ignoredFiles = []; 21 | files.forEach(file => { 22 | const content = fs.readFileSync(file); 23 | if (content.indexOf(constants.NOFLOW_MARKER) > -1) { 24 | ignoredFiles.push(file); 25 | } else if (content.indexOf(constants.FLOW_MARKER) === -1) { 26 | unmonitoredFiles.push(file); 27 | } 28 | }); 29 | if (!unmonitoredFiles.length) { 30 | console.log(`There are no unmonitored files that do not contain "${constants.FLOW_MARKER}"!`); 31 | return; 32 | } 33 | if (ignoredFiles.length) { 34 | console.log(`Found ${ignoredFiles.length} file(s) that contain ` + 35 | `"${constants.NOFLOW_MARKER}". They will be excluded.`); 36 | } 37 | console.log(`Found ${unmonitoredFiles.length} file(s) that do ` + 38 | `not contain "${constants.FLOW_MARKER}":\n`); 39 | unmonitoredFiles.forEach(file => { 40 | console.log(` ${file.replace(/^\.\//, '')}`); 41 | if (fix) { 42 | fs.writeFileSync(file, `// ${constants.FLOW_MARKER}\n` + fs.readFileSync(file)); 43 | } 44 | }); 45 | 46 | console.log(); 47 | if (!fix) { 48 | console.log('Run the command again with --fix to automatically append ' + 49 | `"${constants.FLOW_MARKER}" to those files.`); 50 | } else { 51 | console.log(`${unmonitoredFiles.length} fixed by automatically ` + 52 | `appending "${constants.FLOW_MARKER}"`); 53 | } 54 | 55 | console.log(); 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | DEFAULT_FLOW_TYPED_DIR: 'flow-typed', 3 | DEFAULT_PACKAGE_DEP_LIBDEFS_FILENAME: 'package-dep-libdefs.js', 4 | DEFAULT_FLOW_TYPED_NPM_DIR: 'npm', 5 | // These are bundled with Flow, so we do not generate stubs for them 6 | DEFAULT_FLOW_LIBDEFS: ['react', 'react-dom', 'react-dom/server'], 7 | FLOW_MARKER: '@flow', 8 | NOFLOW_MARKER: '@noflow', 9 | LIBDEF_REGEX: /^(.+)_v\w+\.\w+\.\w+\.js$/, 10 | }; 11 | 12 | module.exports = config; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flow-scripts", 3 | "version": "0.4.0", 4 | "description": "Utility scripts for Flowtypes", 5 | "main": "index.js", 6 | "files": [ 7 | "bin", 8 | "lib", 9 | "README.md" 10 | ], 11 | "bin": { 12 | "flow-scripts": "bin/flow-scripts.js" 13 | }, 14 | "scripts": { 15 | "test": "Tests not ready." 16 | }, 17 | "repository": "https://github.com/yangshun/flow-scripts.git", 18 | "keywords": [ 19 | "flow", 20 | "flowtypes" 21 | ], 22 | "author": "Tay Yang Shun", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/yangshun/flow-scripts/issues" 26 | }, 27 | "homepage": "https://github.com/yangshun/flow-scripts", 28 | "npmName": "flow-scripts", 29 | "dependencies": { 30 | "commander": "^2.9.0", 31 | "glob": "^7.1.2", 32 | "lodash": "^4.17.4" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | balanced-match@^1.0.0: 6 | version "1.0.0" 7 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 8 | 9 | brace-expansion@^1.1.7: 10 | version "1.1.8" 11 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 12 | dependencies: 13 | balanced-match "^1.0.0" 14 | concat-map "0.0.1" 15 | 16 | commander@^2.9.0: 17 | version "2.9.0" 18 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 19 | dependencies: 20 | graceful-readlink ">= 1.0.0" 21 | 22 | concat-map@0.0.1: 23 | version "0.0.1" 24 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 25 | 26 | fs.realpath@^1.0.0: 27 | version "1.0.0" 28 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 29 | 30 | glob@^7.1.2: 31 | version "7.1.2" 32 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 33 | dependencies: 34 | fs.realpath "^1.0.0" 35 | inflight "^1.0.4" 36 | inherits "2" 37 | minimatch "^3.0.4" 38 | once "^1.3.0" 39 | path-is-absolute "^1.0.0" 40 | 41 | "graceful-readlink@>= 1.0.0": 42 | version "1.0.1" 43 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 44 | 45 | inflight@^1.0.4: 46 | version "1.0.6" 47 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 48 | dependencies: 49 | once "^1.3.0" 50 | wrappy "1" 51 | 52 | inherits@2: 53 | version "2.0.3" 54 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 55 | 56 | lodash@^4.17.4: 57 | version "4.17.4" 58 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 59 | 60 | minimatch@^3.0.4: 61 | version "3.0.4" 62 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 63 | dependencies: 64 | brace-expansion "^1.1.7" 65 | 66 | once@^1.3.0: 67 | version "1.4.0" 68 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 69 | dependencies: 70 | wrappy "1" 71 | 72 | path-is-absolute@^1.0.0: 73 | version "1.0.1" 74 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 75 | 76 | wrappy@1: 77 | version "1.0.2" 78 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 79 | --------------------------------------------------------------------------------