├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── LICENSE ├── README.md ├── flow-pkg ├── index.js └── package.json ├── index.js ├── package-lock.json ├── package.json └── tests ├── bundle.js ├── file1.flow.js ├── file2.flow.js ├── file3.flow.js ├── file3.js ├── main.js ├── mainTestPkg.js ├── mainforce.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "skipFiles": ["/**"], 12 | "program": "${workspaceFolder}\\tests\\test.js" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { "deno.enable": false } 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Dalci de Jesus Bagolin 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 | # esbuild-plugin-flow 2 | 3 | Esbuild plugin to strip types for Flow files using [flow-remove-types](https://www.npmjs.com/package/flow-remove-types) 4 | 5 | ## Installation 6 | 7 | ``` 8 | npm i --dev https://github.com/dalcib/esbuild-plugin-flow 9 | ``` 10 | 11 | ## Usage 12 | 13 | The esbuild [plugin API](https://esbuild.github.io/plugins/) isn't supported via CLI, so use a custom build script like so: 14 | 15 | ```js 16 | const esbuild = require('esbuild') 17 | const flow = require('esbuild-plugin-flow') 18 | 19 | esbuild 20 | .build({ 21 | entryPoints: ['index.js'], 22 | outfile: 'dist/bundle.js', 23 | bundle: true, 24 | plugins: [flow(/\.flow\.jsx?$/)], 25 | }) 26 | .catch(() => process.exit(1)) 27 | ``` 28 | 29 | ## Options 30 | 31 | The plugin has to parameters: `regexp` and `[force]` 32 | 33 | ### regexp 34 | 35 | The plugin needs a RegExp to define: 36 | 37 | #### a) paths or packages to be included 38 | 39 | ```javascript 40 | ;/node_modules\\package.*\.jsx?$/ 41 | ``` 42 | 43 | #### b) extentions 44 | 45 | ```javascript 46 | ;/\.flow\.jsx?$/ 47 | ``` 48 | 49 | #### c) a combination of both 50 | 51 | ```javascript 52 | ;/node_modules\\package1.*\.jsx?$|node_modules\\package2.*\.jsx?$|\.flow\.jsx?$/ 53 | ``` 54 | 55 | ### force [optional] 56 | 57 | A Boolean indicating that the plugin must act regardless of the existence of flow annotations (`// @flow` or `/** @flow /*`) in the file. 58 | 59 | ## Entry Point 60 | 61 | Due to limitations of Esbuild, the entry point is not processed. 62 | 63 | ## Tests 64 | 65 | For test, copy the folder `flow-pkg` to node_modules and run `node tests/test` 66 | -------------------------------------------------------------------------------- /flow-pkg/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export const fnx = (x: ?number, y: string, z: boolean): void => {} 3 | -------------------------------------------------------------------------------- /flow-pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flow-pkg", 3 | "version": "0.1.0", 4 | "description": "", 5 | "main": "index.js" 6 | } 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var flowRemoveTypes = require('flow-remove-types') 2 | var { readFile } = require('fs').promises 3 | 4 | module.exports = (regexp = /$^/, force) => { 5 | return { 6 | name: 'flow', 7 | setup(build) { 8 | build.onLoad({ filter: regexp }, async (args) => { 9 | const source = await readFile(args.path, 'utf8') 10 | let output = source 11 | if (force) { 12 | output = flowRemoveTypes('// @flow\n' + source, { pretty: true }) 13 | } else { 14 | if (source.slice(0, 8) === '// @flow' || source.match(/^\/\*.*@flow.*\*\//s)) { 15 | output = flowRemoveTypes(source, { pretty: true }) 16 | } 17 | } 18 | const contents = output.toString().replace(/static\s+\+/g, 'static ') 19 | return { 20 | contents, 21 | loader: 'jsx', 22 | } 23 | }) 24 | }, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esbuild-plugin-flow", 3 | "version": "0.1.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "version": "0.1.0", 9 | "license": "MIT", 10 | "dependencies": { 11 | "esbuild": "^0.8.7", 12 | "flow-remove-types": "^2.137.0" 13 | }, 14 | "devDependencies": { 15 | "flow-pkg": "file:/./test-flow-pkg" 16 | } 17 | }, 18 | "node_modules/esbuild": { 19 | "version": "0.8.7", 20 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.7.tgz", 21 | "integrity": "sha512-3PRWDk6Jb6uGEljeEPaR3RHdMTCMkzTpHbM+L0EhG/ohpIgFQvLXcB+nLRwy6N3/kt6kfIoxYQpq2mgd57dj6Q==", 22 | "hasInstallScript": true, 23 | "bin": { 24 | "esbuild": "bin/esbuild" 25 | } 26 | }, 27 | "node_modules/flow-parser": { 28 | "version": "0.138.0", 29 | "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.138.0.tgz", 30 | "integrity": "sha512-LFnTyjrv39UvCWl8NOcpByr/amj8a5k5z7isO2wv4T43nNrUnHQwX3rarTz9zcpHXkDAQv6X4MfQ4ZzJUptpbw==", 31 | "engines": { 32 | "node": ">=0.4.0" 33 | } 34 | }, 35 | "node_modules/flow-pkg": { 36 | "version": "0.1.0" 37 | }, 38 | "node_modules/flow-remove-types": { 39 | "version": "2.138.0", 40 | "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.138.0.tgz", 41 | "integrity": "sha512-gWZYpCAcpX5SD7j1S5DrWLWm+ir5LXkkRTrCokTdO5aW6M1cqQmHN5lxwoQTqkP8PfgXI8ILD810TL9CvexpgA==", 42 | "dependencies": { 43 | "flow-parser": "^0.138.0", 44 | "pirates": "^3.0.2", 45 | "vlq": "^0.2.1" 46 | }, 47 | "bin": { 48 | "flow-node": "flow-node", 49 | "flow-remove-types": "flow-remove-types" 50 | }, 51 | "engines": { 52 | "node": ">=4" 53 | } 54 | }, 55 | "node_modules/node-modules-regexp": { 56 | "version": "1.0.0", 57 | "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", 58 | "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", 59 | "engines": { 60 | "node": ">=0.10.0" 61 | } 62 | }, 63 | "node_modules/pirates": { 64 | "version": "3.0.2", 65 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-3.0.2.tgz", 66 | "integrity": "sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==", 67 | "dependencies": { 68 | "node-modules-regexp": "^1.0.0" 69 | }, 70 | "engines": { 71 | "node": ">= 4" 72 | } 73 | }, 74 | "node_modules/vlq": { 75 | "version": "0.2.3", 76 | "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", 77 | "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" 78 | }, 79 | "test-flow-pkg": { 80 | "name": "test-flow-pkg", 81 | "version": "0.1.0", 82 | "dev": true, 83 | "license": "MIT" 84 | } 85 | }, 86 | "dependencies": { 87 | "esbuild": { 88 | "version": "0.8.7", 89 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.8.7.tgz", 90 | "integrity": "sha512-3PRWDk6Jb6uGEljeEPaR3RHdMTCMkzTpHbM+L0EhG/ohpIgFQvLXcB+nLRwy6N3/kt6kfIoxYQpq2mgd57dj6Q==" 91 | }, 92 | "flow-parser": { 93 | "version": "0.138.0", 94 | "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.138.0.tgz", 95 | "integrity": "sha512-LFnTyjrv39UvCWl8NOcpByr/amj8a5k5z7isO2wv4T43nNrUnHQwX3rarTz9zcpHXkDAQv6X4MfQ4ZzJUptpbw==" 96 | }, 97 | "flow-pkg": { 98 | "version": "0.1.0" 99 | }, 100 | "flow-remove-types": { 101 | "version": "2.138.0", 102 | "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.138.0.tgz", 103 | "integrity": "sha512-gWZYpCAcpX5SD7j1S5DrWLWm+ir5LXkkRTrCokTdO5aW6M1cqQmHN5lxwoQTqkP8PfgXI8ILD810TL9CvexpgA==", 104 | "requires": { 105 | "flow-parser": "^0.138.0", 106 | "pirates": "^3.0.2", 107 | "vlq": "^0.2.1" 108 | } 109 | }, 110 | "node-modules-regexp": { 111 | "version": "1.0.0", 112 | "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", 113 | "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" 114 | }, 115 | "pirates": { 116 | "version": "3.0.2", 117 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-3.0.2.tgz", 118 | "integrity": "sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==", 119 | "requires": { 120 | "node-modules-regexp": "^1.0.0" 121 | } 122 | }, 123 | "vlq": { 124 | "version": "0.2.3", 125 | "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", 126 | "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esbuild-plugin-flow", 3 | "version": "0.3.2", 4 | "description": "Esbuild plugin to strip types for Flow files", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node tests/test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/dalcib/esbuild-plugin-flow.git" 12 | }, 13 | "author": "Dalci de Jesus Bagolin (https://github.org/dalcib)", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/dalcib/esbuild-plugin-flow/issues" 17 | }, 18 | "homepage": "https://github.com/dalcib/esbuild-plugin-flow#readme", 19 | "keywords": [ 20 | "esbuild", 21 | "plugin", 22 | "flow" 23 | ], 24 | "dependencies": { 25 | "flow-remove-types": "^2.137.0" 26 | }, 27 | "devDependencies": { 28 | "esbuild": "^0.8.7" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/bundle.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | var __defProp = Object.defineProperty; 3 | var __markAsModule = (target) => __defProp(target, "__esModule", {value: true}); 4 | var __commonJS = (callback, module) => () => { 5 | if (!module) { 6 | module = {exports: {}}; 7 | callback(module.exports, module); 8 | } 9 | return module.exports; 10 | }; 11 | var __export = (target, all) => { 12 | __markAsModule(target); 13 | for (var name in all) 14 | __defProp(target, name, {get: all[name], enumerable: true}); 15 | }; 16 | 17 | // flow:C:\Users\Dalci\Playground\esbuild-plugin-flow\tests\file1.flow.js 18 | var require_file1_flow = __commonJS((exports) => { 19 | __export(exports, { 20 | fn: () => fn 21 | }); 22 | const fn = (x, y) => { 23 | return x + y; 24 | }; 25 | }); 26 | 27 | // flow:C:\Users\Dalci\Playground\esbuild-plugin-flow\tests\file2.flow.js 28 | var require_file2_flow = __commonJS((exports) => { 29 | __export(exports, { 30 | fn: () => fn 31 | }); 32 | const fn = (x, y, z) => { 33 | }; 34 | }); 35 | 36 | // tests/file3.js 37 | var require_file3 = __commonJS((exports) => { 38 | __export(exports, { 39 | fn: () => fn 40 | }); 41 | const fn = (x, y) => x * y; 42 | }); 43 | 44 | // tests/main.js 45 | const fn1 = require_file1_flow(); 46 | const fn2 = require_file2_flow(); 47 | const fn3 = require_file3(); 48 | console.log(fn1(1, 2, 3)); 49 | console.log(fn2(1, 2, 3)); 50 | console.log(fn3(1, 2, 3)); 51 | })(); 52 | -------------------------------------------------------------------------------- /tests/file1.flow.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | export const fn = (x: ?number, y: number): number => { 3 | return x + y 4 | } 5 | -------------------------------------------------------------------------------- /tests/file2.flow.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * @flow 4 | * 5 | */ 6 | export const fn = (x: ?number, y: string, z: boolean): void => {} 7 | -------------------------------------------------------------------------------- /tests/file3.flow.js: -------------------------------------------------------------------------------- 1 | export const fn = (x: ?number, y: string, z: boolean): void => {} 2 | -------------------------------------------------------------------------------- /tests/file3.js: -------------------------------------------------------------------------------- 1 | export const fn = (x, y) => x * y 2 | -------------------------------------------------------------------------------- /tests/main.js: -------------------------------------------------------------------------------- 1 | const fn1 = require('./file1.flow.js') 2 | const fn2 = require('./file2.flow.js') 3 | const fn3 = require('./file3.js') 4 | console.log(fn1(1, 2, 3)) 5 | console.log(fn2(1, 2, 3)) 6 | console.log(fn3(1, 2, 3)) 7 | -------------------------------------------------------------------------------- /tests/mainTestPkg.js: -------------------------------------------------------------------------------- 1 | const fn1 = require('./file1.flow.js') 2 | const fn2 = require('flow-pkg') 3 | const fn3 = require('./file3.js') 4 | console.log(fn1(1, 2, 3)) 5 | console.log(fn2(1, 2, 3)) 6 | console.log(fn3(1, 2, 3)) 7 | -------------------------------------------------------------------------------- /tests/mainforce.js: -------------------------------------------------------------------------------- 1 | const fn1 = require('./file1.flow.js') 2 | const fn2 = require('./file3.flow.js') 3 | const fn3 = require('./file3.js') 4 | console.log(fn1(1, 2, 3)) 5 | console.log(fn2(1, 2, 3)) 6 | console.log(fn3(1, 2, 3)) 7 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | const esbuild = require('esbuild') 2 | const assert = require('assert').strict 3 | const fs = require('fs') 4 | const flow = require('../index') 5 | 6 | const reFlow = /: number|: string|: boolean|: \?number/ 7 | 8 | async function test(id, file, conf, force) { 9 | const result = await esbuild.build({ 10 | entryPoints: [file], 11 | write: false, 12 | plugins: [flow(conf, force)], 13 | outfile: `tests/bundle${id}.js`, 14 | bundle: true, 15 | }) 16 | 17 | const bundle = result.outputFiles[0].text 18 | const isFlow = !!bundle.match(reFlow) 19 | try { 20 | assert(isFlow === false, new Error()) 21 | console.log('✅', id, conf, force) 22 | } catch (e) { 23 | console.error('❌', id, conf, force, ' ', e, isFlow) 24 | } 25 | } 26 | 27 | test(1, 'tests/main.js', /\.jsx?$/) 28 | test(2, 'tests/main.js', /\.flow\.jsx?$/) 29 | test(3, 'tests/mainTestPkg.js', /node_modules\\flow-pkg.*\.jsx?$|\.flow\.jsx?$/) 30 | test(4, 'tests/mainforce.js', /\.jsx?$/, true) 31 | --------------------------------------------------------------------------------