├── .gitignore ├── LICENSE ├── README.md ├── lib ├── .DS_Store ├── check │ ├── checkBabel.js │ ├── checkBrowserify.js │ ├── checkForPackageJSON.js │ └── checkWebpack.js ├── genericHandler.js ├── get │ └── getUsesYarn.js ├── index.js ├── initialize.js ├── install │ ├── installAliasify.js │ ├── installBabelPluginResolver.js │ ├── installPreact.js │ └── uninstallPreact.js ├── mod │ ├── modBabelRC.js │ ├── modBrowserifyConfig.js │ ├── modWebpackConfig.js │ └── webpackAliasLines.js ├── runCommands.js └── undo.js ├── package-lock.json ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Colin McDonnell 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 | # bye-react 2 | 3 | Made by [@vriad](https://twitter.com/vriad) 4 | 5 | Migrate your project from [React](https://github.com/facebook/react) to [Preact](https://github.com/developit/preact) with a single command. 6 | More specifically, this tool switches the project over to [preact-compat](https://github.com/developit/preact-compat), the "compatibility layer that makes React-based modules work with Preact, without any code changes". After running the command below, no code changes should be necessary for your project to run successfully. 7 | 8 | ## Disclaimers 9 | 1. Requires usage of Webpack, Browserify, or the Babel React preset (or any combination thereof). If you don’t use any of these, this won't work. Also you should probably be using one of these. 10 | 2. Not guaranteed to work in all cases. You should be using a version of React that is compatible with the current stable release (@15.6.1). May interact in interesting and unfortunate ways with non-standard build pipelines (e.g. if you dynamically generate .babelrc or package.json, etc). 11 | 3. Will delete comments inside package.json and .babelrc files. These files contain JSON-compliant data. To add the aliases, bye-react reads in the JSON, modifies it, and writes it back to disk. Comments are lost en route. If these are important to you then don't use bye-react. 12 | 13 | ## Usage 14 | #### Install 15 | `npm install -g bye-react` 16 | 17 | or 18 | 19 | `yarn global add bye-react` 20 | 21 | #### Usage 22 | `cd ~/your/react/project` 23 | 24 | `bye-react` 25 | 26 | #### Undoing 27 | When you first run `bye-react` backups are made of all config files modified by this tool. Running these undo commands restores these files to their original state. It also uninstalls preact and reinstalls react and react-dom. 28 | `bye-react -u` 29 | 30 | or 31 | 32 | `bye-react --undo` 33 | 34 | ## How It Works 35 | 1. Uninstalls react and react-dom. 36 | 2. Installs preact and preact-compat (obviously) via npm (or yarn, if a Yarn lockfile is detected) 37 | 3. Checks for usage of [Webpack](https://github.com/webpack). If detected, an alias is added to webpack.config.js. Specifically [these lines](lib/mod/webpackAliasLines.js) are appended to the end of the file. 38 | 4. Checks for usage of [Babel’s React preset](https://babeljs.io/docs/plugins/preset-react/). If detected, [babel-plugin-module-resolver](https://github.com/tleunen/babel-plugin-module-resolver) is installed and used to create an alias in .babelrc 39 | 5. Checks for usage of Browserify. If detected, [aliasify](https://github.com/benbria/aliasify) is installed and used to create an alias in package.json. 40 | -------------------------------------------------------------------------------- /lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinhacks/bye-react/18d7d0139c955269e3e0adaac0f68c9665963568/lib/.DS_Store -------------------------------------------------------------------------------- /lib/check/checkBabel.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const cjson = require("cjson") 4 | 5 | 6 | module.exports = (state)=>{ 7 | return new Promise((res,rej)=>{ 8 | 9 | let babelRCPath = path.resolve(process.cwd(), ".babelrc") 10 | if(fs.existsSync(babelRCPath)){ 11 | let babelRCContents = fs.readFileSync(babelRCPath, 'utf8') || "{}" 12 | let babelRC = cjson.parse(babelRCContents) 13 | if(babelRC.presets.includes("react")){ 14 | console.log("\n###################\nBabel detected.") 15 | return res(true) 16 | // return rej("ERROR: it doesn't look like you're using the React preset for Babel.\nSpecifically, we couldn't find \"react\" in the list of presets in your .babelrc file.") 17 | } 18 | // return rej("ERROR: could not find webpack.config.js.\nAre you in the root directory of your project?") 19 | } 20 | 21 | let packageJSONPath = path.resolve(process.cwd(), "package.json") 22 | let packageJSONContents = fs.readFileSync(packageJSONPath, 'utf8') || "{}" 23 | let packageJSON = cjson.parse(packageJSONContents) 24 | if(packageJSON['dependencies'] && packageJSON['dependencies']['babel-preset-react']){ 25 | console.log("\n###################\nBabel detected.") 26 | return res(true) 27 | } 28 | if(packageJSON['devDependencies'] && packageJSON['devDependencies']['babel-preset-react']){ 29 | console.log("\n###################\nBabel detected.") 30 | return res(true) 31 | } 32 | console.log("Babel not detected.") 33 | res(false) 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /lib/check/checkBrowserify.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const colors = require('colors'); 4 | const { exec } = require('child_process'); 5 | 6 | 7 | module.exports = (state)=>{ 8 | return new Promise((res,rej)=>{ 9 | 10 | exec("browserify --version", (err, stdout, stderr) => { 11 | if(stdout.length && parseInt(stdout)){ 12 | console.log("\n###################\nBrowserify detected.") 13 | res(true) 14 | } 15 | res(false) 16 | }) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /lib/check/checkForPackageJSON.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const colors = require('colors'); 4 | 5 | module.exports = ()=>{ 6 | let packageJSON = path.resolve(process.cwd(), "package.json") 7 | if(!fs.existsSync(packageJSON)){ 8 | console.log("FATAL: Can't find package.json.".red) 9 | console.log("Are you sure you're in your project root?".red) 10 | process.exit() 11 | return res(false) 12 | // return rej("ERROR: could not find webpack.config.js.\nAre you in the root directory of your project?") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/check/checkWebpack.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | 5 | module.exports = (state)=>{ 6 | return new Promise((res,rej)=>{ 7 | let configPath = path.resolve(process.cwd(), "webpack.config.js") 8 | if(!fs.existsSync(configPath)){ 9 | return res(false) 10 | // return rej("ERROR: could not find webpack.config.js.\nAre you in the root directory of your project?") 11 | } 12 | console.log("Webpack detected...") 13 | res(true) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /lib/genericHandler.js: -------------------------------------------------------------------------------- 1 | 2 | const colors = require('colors/safe'); 3 | 4 | module.exports = (err)=>{ 5 | console.log(err) 6 | console.log("GENERICHANDLER") 7 | console.log(colors.red(err.toString())) 8 | process.exit() 9 | } -------------------------------------------------------------------------------- /lib/get/getUsesYarn.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = (state)=>{ 5 | return new Promise((res,rej)=>{ 6 | let yarnLock = path.resolve(process.cwd(), "yarn.lock") 7 | let usesYarn = fs.existsSync(yarnLock) 8 | res(usesYarn) 9 | }) 10 | } -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const co = require('co'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | const initialize = require("./initialize") 7 | const undo = require("./undo") 8 | const genericHandler = require("./genericHandler") 9 | 10 | const installPreact = require("./install/installPreact") 11 | const installAliasify = require("./install/installAliasify") 12 | const installBabelPluginResolver = require("./install/installBabelPluginResolver") 13 | 14 | const getUsesYarn = require("./get/getUsesYarn") 15 | 16 | const checkForPackageJSON = require("./check/checkForPackageJSON") 17 | const checkWebpack = require("./check/checkWebpack") 18 | const checkBabel = require("./check/checkBabel") 19 | const checkBrowserify = require("./check/checkBrowserify") 20 | 21 | const modWebpackConfig = require("./mod/modWebpackConfig") 22 | const modBabelRC = require("./mod/modBabelRC") 23 | const modBrowserifyConfig = require("./mod/modBrowserifyConfig") 24 | 25 | var program = require('commander'); 26 | 27 | program 28 | .option('-u, --undo', 'Undo all changes done by bye-react.') 29 | .parse(process.argv); 30 | 31 | 32 | let changesMade = false 33 | 34 | let start = ()=>{ 35 | 36 | let state = {} 37 | 38 | initialize() 39 | .then(getUsesYarn) 40 | .then((usesYarn)=>{ 41 | state.usesYarn = usesYarn 42 | return state 43 | }) 44 | .then(checkForPackageJSON) 45 | .then(()=>{ 46 | return installPreact(state) 47 | }) 48 | .then(checkWebpack) 49 | .then((usesWebpack)=>{ 50 | if(usesWebpack) { 51 | changesMade = true 52 | return modWebpackConfig() 53 | } 54 | return 55 | }) 56 | .then(checkBabel) 57 | .then((usesBabel)=>{ 58 | if(usesBabel){ 59 | changesMade = true 60 | return installBabelPluginResolver(state).then(modBabelRC) 61 | 62 | } 63 | return 64 | }) 65 | .then(checkBrowserify) 66 | .then((usesBrowserify)=>{ 67 | if(usesBrowserify){ 68 | changesMade = true 69 | return installAliasify(state).then(modBrowserifyConfig) 70 | } 71 | return 72 | }).then((state)=>{ 73 | if(changesMade){ 74 | console.log("\nDONE!") 75 | console.log("- Build and run the project as you normally would.") 76 | console.log("- If you encounter a bug, running `bye-react-undo` will undo all the changes made by this tool.") 77 | }else{ 78 | console.log("Did not detect Browserify, Webpack, or Babel.") 79 | console.log("One of these three is required for this tool to work.") 80 | console.log("Try following the steps for \"Manually aliasing\" at https://preactjs.com/guide/switching-to-preact.") 81 | } 82 | process.exit() 83 | return 84 | }).catch(genericHandler) 85 | } 86 | 87 | console.log(JSON.stringify(program.undo,null,2)) 88 | if(program.undo){ 89 | console.log("Undoing bye-react...") 90 | undo() 91 | }else{ 92 | console.log("Running bye-react...") 93 | start() 94 | } -------------------------------------------------------------------------------- /lib/initialize.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const rimraf = require('rimraf') 4 | 5 | module.exports = ()=>{ 6 | let byeReactDir = path.resolve(process.cwd(), ".bye-react") 7 | if(!fs.existsSync(byeReactDir)){ 8 | fs.mkdirSync(byeReactDir) 9 | } 10 | for (var file of [".babelrc", "package.json", "webpack.config.js"]){ 11 | let filePath = path.resolve(process.cwd(), file) 12 | let duplicatePath = path.join(byeReactDir, file) 13 | if(fs.existsSync(filePath) && !fs.existsSync(duplicatePath)){ 14 | let contents = fs.readFileSync(filePath,'utf8') 15 | fs.writeFileSync(duplicatePath, contents) 16 | } 17 | } 18 | console.log("Backing up config files...") 19 | return new Promise((res)=>res()) 20 | } -------------------------------------------------------------------------------- /lib/install/installAliasify.js: -------------------------------------------------------------------------------- 1 | const runCommands = require("../runCommands") 2 | 3 | module.exports = (state)=>{ 4 | console.log("Installing aliasify...") 5 | let command = state.usesYarn ? "yarn add aliasify --dev" : "npm install --save-dev aliasify" 6 | return runCommands([ 7 | command 8 | ]) 9 | } 10 | -------------------------------------------------------------------------------- /lib/install/installBabelPluginResolver.js: -------------------------------------------------------------------------------- 1 | const runCommands = require("../runCommands") 2 | 3 | module.exports = (state)=>{ 4 | console.log("Installing babel-plugin-module-resolver...") 5 | let command = state.usesYarn ? "yarn add babel-plugin-module-resolver --dev" : "npm install --save-dev babel-plugin-module-resolver" 6 | return runCommands([ 7 | command 8 | ]) 9 | } 10 | -------------------------------------------------------------------------------- /lib/install/installPreact.js: -------------------------------------------------------------------------------- 1 | const runCommands = require("../runCommands") 2 | 3 | module.exports = (state)=>{ 4 | 5 | let uninstallReact = state.usesYarn ? "yarn remove react react-dom" : "npm uninstall react react-dom" 6 | let installPreact = state.usesYarn ? "yarn add preact preact-compat" : "npm install preact preact-compat --save" 7 | 8 | return runCommands([ 9 | uninstallReact, 10 | installPreact 11 | ]) 12 | } 13 | -------------------------------------------------------------------------------- /lib/install/uninstallPreact.js: -------------------------------------------------------------------------------- 1 | const runCommands = require("../runCommands") 2 | 3 | module.exports = (state)=>{ 4 | 5 | let uninstallPreact = state.usesYarn ? "yarn remove preact preact-compat" : "npm uninstall preact preact-compat" 6 | let installReact = state.usesYarn ? "yarn add react react-dom" : "npm install react react-dom --save" 7 | 8 | return runCommands([ 9 | uninstallPreact, 10 | installReact 11 | ]) 12 | } 13 | -------------------------------------------------------------------------------- /lib/mod/modBabelRC.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const cjson = require("cjson") 4 | 5 | module.exports = (state)=>{ 6 | return new Promise((res,rej)=>{ 7 | 8 | console.log("Adding alias to .babelrc with babel-plugin-module-resolver...") 9 | let babelRCPath = path.resolve(process.cwd(), ".babelrc") 10 | let babelRCContents = fs.existsSync(babelRCPath) ? fs.readFileSync(babelRCPath, 'utf8') : "{}" 11 | let babelRC = cjson.parse(babelRCContents) 12 | 13 | babelRC.plugins = babelRC.plugins || [] 14 | 15 | let moduleResolverSeen = false 16 | let moduleResolver = ["module-resolver", { 17 | "root": ["."], 18 | "alias": { 19 | "react": "preact-compat", 20 | "react-dom": "preact-compat", 21 | "create-react-class": "preact-compat/lib/create-react-class" 22 | } 23 | }] 24 | 25 | for(let pluginIndex in babelRC.plugins){ 26 | let plugin = babelRC.plugins[pluginIndex] 27 | if(Array.isArray(plugin)){ 28 | if(plugin[0] == "module-resolver"){ 29 | moduleResolverSeen = true 30 | babelRC.plugins[pluginIndex] = moduleResolver 31 | } 32 | } 33 | } 34 | 35 | if(!moduleResolverSeen){ 36 | babelRC.plugins.push(moduleResolver) 37 | } 38 | 39 | fs.writeFileSync(babelRCPath, JSON.stringify(babelRC,null,2)) 40 | res("Successfully modified .babelrc.") 41 | 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /lib/mod/modBrowserifyConfig.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const cjson = require("cjson") 4 | 5 | module.exports = (state)=>{ 6 | return new Promise((res,rej)=>{ 7 | 8 | console.log("Adding new alias to package.json with aliasify...") 9 | let packageJSONPath = path.resolve(process.cwd(), "package.json") 10 | let packageJSONContents = fs.readFileSync(packageJSONPath, 'utf8') || "{}" 11 | let packageJSON = cjson.parse(packageJSONContents) 12 | 13 | packageJSON.aliasify = packageJSON.aliasify || {} 14 | packageJSON.aliasify.aliases = packageJSON.aliasify.aliases || {} 15 | packageJSON.aliasify.aliases['react'] = "preact-compat" 16 | packageJSON.aliasify.aliases['react-dom'] = "preact-compat" 17 | packageJSON.aliasify.aliases['create-react-class'] = "preact-compat/lib/create-react-class" 18 | 19 | fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON,null,2)) 20 | res("Successfully modified package.json.") 21 | 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /lib/mod/modWebpackConfig.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | const newWebpackConfigs = [ 5 | "", 6 | "", 7 | "// adding aliases for preact", 8 | "// apologies for the ugliness", 9 | "// robustness > aesthetics in this case", 10 | "module.exports.resolve = module.exports.resolve || {}", 11 | "module.exports.resolve.alias = module.exports.resolve.alias || {}", 12 | "module.exports.resolve.alias['react'] = 'preact-compat'", 13 | "module.exports.resolve.alias['react-dom'] = 'preact-compat'", 14 | "module.exports.resolve.alias['create-react-class'] = 'preact-compat/lib/create-react-class'", 15 | "" 16 | ] 17 | 18 | module.exports = (state)=>{ 19 | return new Promise((res,rej)=>{ 20 | let configPath = path.resolve(process.cwd(), "webpack.config.js") 21 | fs.appendFile(configPath, newWebpackConfigs.join("\n"), (err)=>{ 22 | if(err) { 23 | return rej(err) 24 | } 25 | return res() 26 | }) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /lib/mod/webpackAliasLines.js: -------------------------------------------------------------------------------- 1 | module.exports.resolve = module.exports.resolve || {} 2 | module.exports.resolve.alias = module.exports.resolve.alias || {} 3 | module.exports.resolve.alias['react'] = 'preact-compat' 4 | module.exports.resolve.alias['react-dom'] = 'preact-compat' 5 | module.exports.resolve.alias['create-react-class'] = 'preact-compat/lib/create-react-class' -------------------------------------------------------------------------------- /lib/runCommands.js: -------------------------------------------------------------------------------- 1 | const { exec } = require('child_process'); 2 | 3 | let runCommands = (commands)=>{ 4 | return new Promise((res,rej)=>{ 5 | if(!commands.length){ 6 | return res() 7 | } 8 | let command = commands.shift() 9 | console.log("> "+command) 10 | 11 | const options = {maxBuffer: 1024 * 1700} 12 | let execution = exec(command, options, (err, stdout, stderr) => { 13 | if(err){ 14 | console.log(err) 15 | return rej(err) 16 | } 17 | return runCommands(commands).then(()=>{ 18 | if(!commands.length){ 19 | res(true) 20 | return 21 | } 22 | }) 23 | }) 24 | execution.stdout.pipe(process.stdout); 25 | execution.stderr.pipe(process.stderr); 26 | }) 27 | } 28 | 29 | module.exports = runCommands -------------------------------------------------------------------------------- /lib/undo.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const rimraf = require('rimraf') 5 | 6 | const runCommands = require("./runCommands") 7 | const getUsesYarn = require("./get/getUsesYarn") 8 | 9 | const undo = ()=>{ 10 | let byeReactDir = path.resolve(process.cwd(), ".bye-react") 11 | if(!fs.existsSync(byeReactDir)){ 12 | fs.mkdirSync(byeReactDir) 13 | } 14 | 15 | console.log("Replacing config files from backup...") 16 | for (var file of [".babelrc", "package.json", "webpack.config.js"]){ 17 | let originalPath = path.join(byeReactDir, file) 18 | let replacedPath = path.resolve(process.cwd(), file) 19 | if(fs.existsSync(originalPath)){ 20 | console.log("Replacing original "+file+"...") 21 | let contents = fs.readFileSync(originalPath,'utf8') 22 | fs.writeFileSync(replacedPath, contents) 23 | }else if(fs.existsSync(replacedPath)){ // remove files that weren't there before 24 | console.log("Removing "+file+"...") 25 | fs.unlinkSync(replacedPath) 26 | } 27 | } 28 | 29 | rimraf.sync(byeReactDir) 30 | // fs.unlinkSync(byeReactDir) 31 | 32 | getUsesYarn().then((usesYarn)=>{ 33 | let uninstallEverything = usesYarn ? "yarn remove preact preact-compat" : "npm uninstall preact preact-compat" 34 | let installReact = usesYarn ? "yarn add react react-dom" : "npm install react react-dom --save" 35 | 36 | return runCommands([ 37 | uninstallEverything, 38 | installReact 39 | ]) 40 | }) 41 | 42 | 43 | return new Promise((res)=>res()) 44 | } 45 | module.exports = undo -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testmoduleone", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "asap": { 7 | "version": "2.0.6", 8 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 9 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 10 | }, 11 | "co": { 12 | "version": "4.6.0", 13 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 14 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 15 | }, 16 | "co-prompt": { 17 | "version": "1.0.0", 18 | "resolved": "https://registry.npmjs.org/co-prompt/-/co-prompt-1.0.0.tgz", 19 | "integrity": "sha1-+zcOntrEhXayenMv5dfyHZ/G5vY=" 20 | }, 21 | "colors": { 22 | "version": "1.1.2", 23 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", 24 | "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" 25 | }, 26 | "commander": { 27 | "version": "2.11.0", 28 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", 29 | "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" 30 | }, 31 | "core-js": { 32 | "version": "1.2.7", 33 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", 34 | "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" 35 | }, 36 | "encoding": { 37 | "version": "0.1.12", 38 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 39 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=" 40 | }, 41 | "fbjs": { 42 | "version": "0.8.14", 43 | "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", 44 | "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=" 45 | }, 46 | "iconv-lite": { 47 | "version": "0.4.18", 48 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", 49 | "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" 50 | }, 51 | "immutability-helper": { 52 | "version": "2.3.1", 53 | "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.3.1.tgz", 54 | "integrity": "sha1-jM/OkhVyCMEgsq+tftBcERFMCG4=" 55 | }, 56 | "invariant": { 57 | "version": "2.2.2", 58 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", 59 | "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=" 60 | }, 61 | "is-stream": { 62 | "version": "1.1.0", 63 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 64 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 65 | }, 66 | "isomorphic-fetch": { 67 | "version": "2.2.1", 68 | "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", 69 | "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=" 70 | }, 71 | "js-tokens": { 72 | "version": "3.0.2", 73 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 74 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" 75 | }, 76 | "keypress": { 77 | "version": "0.2.1", 78 | "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", 79 | "integrity": "sha1-HoBFQlABjbrUw/6USX1uZ7YmnHc=" 80 | }, 81 | "loose-envify": { 82 | "version": "1.3.1", 83 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", 84 | "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=" 85 | }, 86 | "node-fetch": { 87 | "version": "1.7.2", 88 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.2.tgz", 89 | "integrity": "sha512-xZZUq2yDhKMIn/UgG5q//IZSNLJIwW2QxS14CNH5spuiXkITM2pUitjdq58yLSaU7m4M0wBNaM2Gh/ggY4YJig==" 90 | }, 91 | "object-assign": { 92 | "version": "4.1.1", 93 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 94 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 95 | }, 96 | "preact": { 97 | "version": "8.2.1", 98 | "resolved": "https://registry.npmjs.org/preact/-/preact-8.2.1.tgz", 99 | "integrity": "sha1-Z0JD3wyEeITQGYNARKovzTEecu0=" 100 | }, 101 | "preact-compat": { 102 | "version": "3.17.0", 103 | "resolved": "https://registry.npmjs.org/preact-compat/-/preact-compat-3.17.0.tgz", 104 | "integrity": "sha1-Uoz9/DARkMGg9HVnM2vh9L4CZrM=" 105 | }, 106 | "preact-render-to-string": { 107 | "version": "3.6.3", 108 | "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-3.6.3.tgz", 109 | "integrity": "sha1-SB0NW9rJGS0zR1V0N9XNAKoxIEM=" 110 | }, 111 | "preact-transition-group": { 112 | "version": "1.1.1", 113 | "resolved": "https://registry.npmjs.org/preact-transition-group/-/preact-transition-group-1.1.1.tgz", 114 | "integrity": "sha1-8KSTJ+pRXs406ivoZMSn0p5dbhA=" 115 | }, 116 | "pretty-format": { 117 | "version": "3.8.0", 118 | "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", 119 | "integrity": "sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=" 120 | }, 121 | "promise": { 122 | "version": "7.3.1", 123 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 124 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==" 125 | }, 126 | "prop-types": { 127 | "version": "15.5.10", 128 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", 129 | "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=" 130 | }, 131 | "setimmediate": { 132 | "version": "1.0.5", 133 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 134 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" 135 | }, 136 | "standalone-react-addons-pure-render-mixin": { 137 | "version": "0.1.1", 138 | "resolved": "https://registry.npmjs.org/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz", 139 | "integrity": "sha1-PHQJ9MecQN6axyxhbPZ5qZTzdVE=" 140 | }, 141 | "ua-parser-js": { 142 | "version": "0.7.14", 143 | "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz", 144 | "integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o=" 145 | }, 146 | "whatwg-fetch": { 147 | "version": "2.0.3", 148 | "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", 149 | "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bye-react", 3 | "version": "1.0.1", 4 | "description": "Migrate from React to Preact with one command.", 5 | "main": "index.js", 6 | "directories": { 7 | "lib": "lib" 8 | }, 9 | "scripts": { 10 | "test": "test" 11 | }, 12 | "author": "Colin McDonnell ", 13 | "license": "MIT", 14 | "bin": { 15 | "bye-react": "./lib/index.js" 16 | }, 17 | "dependencies": { 18 | "cjson": "^0.5.0", 19 | "co": "^4.6.0", 20 | "co-prompt": "^1.0.0", 21 | "colors": "^1.1.2", 22 | "commander": "^2.11.0", 23 | "preact": "^8.2.1", 24 | "preact-compat": "^3.17.0", 25 | "rimraf": "^2.6.1" 26 | }, 27 | "engines": { 28 | "node": ">=6.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | asap@~2.0.3: 6 | version "2.0.6" 7 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 8 | 9 | balanced-match@^1.0.0: 10 | version "1.0.0" 11 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 12 | 13 | brace-expansion@^1.1.7: 14 | version "1.1.8" 15 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" 16 | dependencies: 17 | balanced-match "^1.0.0" 18 | concat-map "0.0.1" 19 | 20 | cjson@^0.5.0: 21 | version "0.5.0" 22 | resolved "https://registry.yarnpkg.com/cjson/-/cjson-0.5.0.tgz#a0f48601e016164dfb2c6d891e380c96cada9839" 23 | dependencies: 24 | json-parse-helpfulerror "^1.0.3" 25 | 26 | co-prompt@^1.0.0: 27 | version "1.0.0" 28 | resolved "https://registry.yarnpkg.com/co-prompt/-/co-prompt-1.0.0.tgz#fb370e9edac48576b27a732fe5d7f21d9fc6e6f6" 29 | dependencies: 30 | keypress "~0.2.1" 31 | 32 | co@^4.6.0: 33 | version "4.6.0" 34 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 35 | 36 | colors@^1.1.2: 37 | version "1.1.2" 38 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" 39 | 40 | commander@^2.11.0: 41 | version "2.11.0" 42 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 43 | 44 | concat-map@0.0.1: 45 | version "0.0.1" 46 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 47 | 48 | core-js@^1.0.0: 49 | version "1.2.7" 50 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" 51 | 52 | encoding@^0.1.11: 53 | version "0.1.12" 54 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 55 | dependencies: 56 | iconv-lite "~0.4.13" 57 | 58 | fbjs@^0.8.9: 59 | version "0.8.14" 60 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.14.tgz#d1dbe2be254c35a91e09f31f9cd50a40b2a0ed1c" 61 | dependencies: 62 | core-js "^1.0.0" 63 | isomorphic-fetch "^2.1.1" 64 | loose-envify "^1.0.0" 65 | object-assign "^4.1.0" 66 | promise "^7.1.1" 67 | setimmediate "^1.0.5" 68 | ua-parser-js "^0.7.9" 69 | 70 | fs.realpath@^1.0.0: 71 | version "1.0.0" 72 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 73 | 74 | glob@^7.0.5: 75 | version "7.1.2" 76 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 77 | dependencies: 78 | fs.realpath "^1.0.0" 79 | inflight "^1.0.4" 80 | inherits "2" 81 | minimatch "^3.0.4" 82 | once "^1.3.0" 83 | path-is-absolute "^1.0.0" 84 | 85 | iconv-lite@~0.4.13: 86 | version "0.4.18" 87 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" 88 | 89 | immutability-helper@^2.1.2: 90 | version "2.3.1" 91 | resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.3.1.tgz#8ccfce92157208c120b2afad7ed05c11114c086e" 92 | dependencies: 93 | invariant "^2.2.0" 94 | 95 | inflight@^1.0.4: 96 | version "1.0.6" 97 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 98 | dependencies: 99 | once "^1.3.0" 100 | wrappy "1" 101 | 102 | inherits@2: 103 | version "2.0.3" 104 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 105 | 106 | invariant@^2.2.0: 107 | version "2.2.2" 108 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" 109 | dependencies: 110 | loose-envify "^1.0.0" 111 | 112 | is-stream@^1.0.1: 113 | version "1.1.0" 114 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 115 | 116 | isomorphic-fetch@^2.1.1: 117 | version "2.2.1" 118 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 119 | dependencies: 120 | node-fetch "^1.0.1" 121 | whatwg-fetch ">=0.10.0" 122 | 123 | jju@^1.1.0: 124 | version "1.3.0" 125 | resolved "https://registry.yarnpkg.com/jju/-/jju-1.3.0.tgz#dadd9ef01924bc728b03f2f7979bdbd62f7a2aaa" 126 | 127 | js-tokens@^3.0.0: 128 | version "3.0.2" 129 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 130 | 131 | json-parse-helpfulerror@^1.0.3: 132 | version "1.0.3" 133 | resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc" 134 | dependencies: 135 | jju "^1.1.0" 136 | 137 | keypress@~0.2.1: 138 | version "0.2.1" 139 | resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.2.1.tgz#1e80454250018dbad4c3fe94497d6e67b6269c77" 140 | 141 | loose-envify@^1.0.0, loose-envify@^1.3.1: 142 | version "1.3.1" 143 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 144 | dependencies: 145 | js-tokens "^3.0.0" 146 | 147 | minimatch@^3.0.4: 148 | version "3.0.4" 149 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 150 | dependencies: 151 | brace-expansion "^1.1.7" 152 | 153 | node-fetch@^1.0.1: 154 | version "1.7.2" 155 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.2.tgz#c54e9aac57e432875233525f3c891c4159ffefd7" 156 | dependencies: 157 | encoding "^0.1.11" 158 | is-stream "^1.0.1" 159 | 160 | object-assign@^4.1.0: 161 | version "4.1.1" 162 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 163 | 164 | once@^1.3.0: 165 | version "1.4.0" 166 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 167 | dependencies: 168 | wrappy "1" 169 | 170 | path-is-absolute@^1.0.0: 171 | version "1.0.1" 172 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 173 | 174 | preact-compat@^3.17.0: 175 | version "3.17.0" 176 | resolved "https://registry.yarnpkg.com/preact-compat/-/preact-compat-3.17.0.tgz#528cfdfc301190c1a0f47567336be1f4be0266b3" 177 | dependencies: 178 | immutability-helper "^2.1.2" 179 | preact-render-to-string "^3.6.0" 180 | preact-transition-group "^1.1.0" 181 | prop-types "^15.5.8" 182 | standalone-react-addons-pure-render-mixin "^0.1.1" 183 | 184 | preact-render-to-string@^3.6.0: 185 | version "3.6.3" 186 | resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-3.6.3.tgz#481d0d5bdac9192d3347557437d5cd00aa312043" 187 | dependencies: 188 | pretty-format "^3.5.1" 189 | 190 | preact-transition-group@^1.1.0: 191 | version "1.1.1" 192 | resolved "https://registry.yarnpkg.com/preact-transition-group/-/preact-transition-group-1.1.1.tgz#f0a49327ea515ece34ea2be864c4a7d29e5d6e10" 193 | 194 | preact@^8.2.1: 195 | version "8.2.1" 196 | resolved "https://registry.yarnpkg.com/preact/-/preact-8.2.1.tgz#674243df0c847884d019834044aa2fcd311e72ed" 197 | 198 | pretty-format@^3.5.1: 199 | version "3.8.0" 200 | resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" 201 | 202 | promise@^7.1.1: 203 | version "7.3.1" 204 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" 205 | dependencies: 206 | asap "~2.0.3" 207 | 208 | prop-types@^15.5.8: 209 | version "15.5.10" 210 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154" 211 | dependencies: 212 | fbjs "^0.8.9" 213 | loose-envify "^1.3.1" 214 | 215 | rimraf@^2.6.1: 216 | version "2.6.1" 217 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" 218 | dependencies: 219 | glob "^7.0.5" 220 | 221 | setimmediate@^1.0.5: 222 | version "1.0.5" 223 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 224 | 225 | standalone-react-addons-pure-render-mixin@^0.1.1: 226 | version "0.1.1" 227 | resolved "https://registry.yarnpkg.com/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz#3c7409f4c79c40de9ac72c616cf679a994f37551" 228 | 229 | ua-parser-js@^0.7.9: 230 | version "0.7.14" 231 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.14.tgz#110d53fa4c3f326c121292bbeac904d2e03387ca" 232 | 233 | whatwg-fetch@>=0.10.0: 234 | version "2.0.3" 235 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" 236 | 237 | wrappy@1: 238 | version "1.0.2" 239 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 240 | --------------------------------------------------------------------------------