├── .gitignore ├── README.md ├── build ├── .DS_Store ├── bundle.js └── index.html ├── client ├── .DS_Store ├── components │ ├── App.jsx │ ├── helpers │ │ ├── Prettify.js │ │ └── buildConfig.js │ └── webpackComponents │ │ ├── DevServer.jsx │ │ ├── Frontend.jsx │ │ ├── Image.jsx │ │ ├── Linting.jsx │ │ ├── Optimization.jsx │ │ ├── Plugin.jsx │ │ ├── Styling.jsx │ │ ├── Test.jsx │ │ ├── Transpiler.jsx │ │ ├── UI.jsx │ │ └── Utilities.jsx ├── css │ └── App.css ├── index.html └── index.js ├── controller └── data.js ├── filesToServe └── webpack-config.js ├── models ├── database.js └── dependencies.js ├── package-lock.json ├── package.json ├── route ├── api.js └── download.js ├── server └── server.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebpackConfigAssist 2 | 3 | Please visit our website 4 | ## https://webpack-generator.herokuapp.com/ 5 | 6 | **More Features will be updated.** 7 | You can simply click what you want in the file. 8 | You can either download it or copy into your codebase. 9 | 10 | **Author:** 11 | Aryeh Kobrinsky [GitHub](https://github.com/akobrinsky). 12 | Stanley Huang [GitHub](https://github.com/stanpython). 13 | Nick Kruckenberg [GitHub](https://github.com/kruckenberg). 14 | Kadir Gundogdu [GitHub](https://github.com/kadirgund). 15 | Minchan Jun [GitHub](https://github.com/MinchanJun). 16 | -------------------------------------------------------------------------------- /build/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stanpython/Webpack-Configurator/7aaed0fba9566bf997c24dcab22063edd7584acb/build/.DS_Store -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | Webpack App -------------------------------------------------------------------------------- /client/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stanpython/Webpack-Configurator/7aaed0fba9566bf997c24dcab22063edd7584acb/client/.DS_Store -------------------------------------------------------------------------------- /client/components/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import '../css/App.css'; 3 | import 'bootstrap/dist/css/bootstrap.min.css'; 4 | import Frontend from './webpackComponents/Frontend'; 5 | import Test from './webpackComponents/Test'; 6 | import UI from './webpackComponents/UI'; 7 | import Transpiler from './webpackComponents/Transpiler'; 8 | import Styling from './webpackComponents/Styling'; 9 | import Image from './webpackComponents/Image'; 10 | import Utilities from './webpackComponents/Utilities'; 11 | import Linting from './webpackComponents/Linting'; 12 | import Optimization from './webpackComponents/Optimization'; 13 | import Plugin from './webpackComponents/Plugin'; 14 | import 'highlight.js/styles/dracula.css'; 15 | import Highlight from 'react-highlight'; 16 | import { Prettify } from './helpers/Prettify'; 17 | import { fetchedRulesToObjects, merge, buildConfig, buildRequirements, buildList, buildDeps, installScript } from './helpers/buildConfig'; 18 | import { CopyToClipboard } from 'react-copy-to-clipboard'; 19 | import { Button } from 'react-bootstrap'; 20 | // dear iterators, for any questions about the frontend, shoot a slack to Kadir and Burak 21 | 22 | const App = () => { 23 | 24 | const [selected, setSelected] = useState({}); 25 | const [store, setStore] = useState(''); 26 | const [requirementDisplay, setrequirementDisplay] = useState(''); 27 | const [devDisplay, setDevDisplay] = useState(''); 28 | const [rules, setRules] = useState({}); 29 | const [dependencies, setDependencies] = useState({}); 30 | const [devDependencies, setDevDependencies] = useState({}); 31 | const [requirements, setRequirements] = useState({}); 32 | 33 | let fetched = false; 34 | 35 | const getData = () => { 36 | fetch('/api') 37 | .then(response => response.json()) 38 | .then(data => { 39 | const result = fetchedRulesToObjects(data) 40 | setRules(result[0]); 41 | setDependencies(result[1]); 42 | setDevDependencies(result[2]); 43 | setRequirements(result[3]); 44 | }) 45 | } 46 | 47 | const getDownload = (requirementDisplay, store) => { 48 | const fileContents = `const path = require('path');\n` + requirementDisplay + `\n\n` + `module.exports = ` + store; 49 | 50 | const postOptions = { 51 | method: 'POST', 52 | headers: { 'Content-Type': 'application/json'}, 53 | body: JSON.stringify({ fileContents }), 54 | } 55 | 56 | fetch('/download', postOptions); 57 | } 58 | 59 | useEffect(() => { 60 | if (!fetched) { 61 | getData(); 62 | fetched = true; 63 | } 64 | 65 | // Build new config object based on current checkbox selections 66 | let newConfig = buildConfig(selected, rules); 67 | if (newConfig === undefined) { // displays default config object 68 | newConfig = { 69 | entry: './src/index.js', 70 | output: { 71 | path: "path.resolve(__dirname, 'dist')", 72 | filename: 'bundle.js', 73 | }, 74 | }; 75 | } 76 | 77 | /** Pass newConfig object through Prettify, which returns a string with 78 | * line returns added, quotation marks stripped from regex expressions and 79 | * function invocations. */ 80 | let prettified = Prettify(newConfig); 81 | // Update state with prettified string 82 | setStore(prettified); 83 | 84 | // Build new requirements string based on current checkbox selections 85 | let newReqs = buildRequirements(selected, requirements); 86 | // Update state with newly built requirements string 87 | setrequirementDisplay(newReqs); 88 | 89 | // Build script for packages using helper functions 90 | let newDevs = installScript(selected, dependencies, devDependencies); 91 | // Update state with packages as string 92 | setDevDisplay(newDevs); 93 | }, [selected]) 94 | 95 | 96 | const handleSelectChange = (name, value) => { 97 | const defaultState = { 98 | nolibrary: false, 99 | react: false, 100 | vue: false, 101 | svelte: false, 102 | } 103 | 104 | if (name === 'nolibrary' || name === 'react' || name === 'vue' || name === 'svelte') { 105 | // console.log('frontend') 106 | setSelected({ ...selected, ...defaultState, [name]: value }) 107 | } else { 108 | setSelected({ ...selected, [name]: value }) 109 | } 110 | } 111 | 112 | return ( 113 |
114 |
115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 |
126 |
127 | 128 | {`const path = require('path');\n` + requirementDisplay + `\n\n` + `module.exports = ` + store} 129 | 130 |
131 |

NPM Packages

132 | 133 | {devDisplay} 134 | 135 |
136 | 137 | 138 | 139 | 140 | 141 |
142 |
143 |
144 |
145 | ) 146 | 147 | } 148 | 149 | export default App; 150 | -------------------------------------------------------------------------------- /client/components/helpers/Prettify.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | const stringifyObject = require('stringify-object'); 3 | 4 | export function Prettify(obj) { 5 | return stringifyObject(obj, { 6 | transform: (obj, prop, originalResult) => { 7 | if (prop === 'path' || prop === 'plugins' || prop === 'contentBase' || prop === 'preprocess' || prop === 'exclude') { 8 | return originalResult.replace(/['"]+/g, '').replace(/\\/g, "'"); 9 | } if (prop === 'test') { 10 | return originalResult.replace(/['"]+/g, ''); 11 | } 12 | return originalResult; 13 | }, 14 | indent: ' ', 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /client/components/helpers/buildConfig.js: -------------------------------------------------------------------------------- 1 | /** fetchedRulesToObjects parses the fetched data into 2 | * three 3 | */ 4 | const fetchedRulesToObjects = (rulesArray) => { 5 | const rulesObj = {}; 6 | const dependencies = {}; 7 | const devDependencies = {}; 8 | const requirements = {}; 9 | 10 | for (const rule of rulesArray) { 11 | 12 | rulesObj[rule.name] = rule.code || {}; 13 | dependencies[rule.name] = rule.dependencies; 14 | devDependencies[rule.name] = rule.devDependencies; 15 | requirements[rule.name] = rule.require; 16 | } 17 | 18 | return [rulesObj, dependencies, devDependencies, requirements]; 19 | } 20 | 21 | /** `merge` is a helper function used to merge base config 22 | * object with update objects. `merge` is called from buildConfig 23 | */ 24 | const merge = (base, update) => { 25 | /** Helper function used to determine if value is an object */ 26 | const isObject = (value) => { 27 | return ( 28 | typeof value === 'object' && 29 | !Array.isArray(value) && 30 | !(value instanceof RegExp) && 31 | value !== null 32 | ) 33 | }; 34 | 35 | /** Loop through keys of update object */ 36 | for (const key of Object.keys(update)) { 37 | /** Construct booleans for flow control. Determine if 38 | * both the base and update values at current key are 39 | * arrays or objects. 40 | */ 41 | const both = [update[key], base[key]]; 42 | const bothArrays = both.every(Array.isArray); 43 | const bothObjects = both.every(isObject); 44 | 45 | /** If both base and update values at current key are arrays, 46 | * concatenate them and store at key on base. If both base 47 | * and update values are objects, make recursive call, 48 | * storing the return at key on base. Otherwise, add or overwrite 49 | * value at key of base with value at key of update. 50 | */ 51 | if (bothArrays) { 52 | base[key] = [...base[key], ...update[key]]; 53 | if (key === 'extensions') { 54 | base[key] = base[key].filter((val, index, arr) => arr.indexOf(val) === index); 55 | } 56 | } else if (bothObjects) { 57 | base[key] = merge(base[key], update[key]); 58 | } else { 59 | base[key] = update[key]; 60 | } 61 | } 62 | 63 | return base; 64 | }; 65 | 66 | 67 | /** Helper function that takes in selected state variable (state of checkboxes) 68 | * and returns a filtered array of the names of those boxes that are checked. 69 | */ 70 | const buildList = (stateVariables) => { 71 | const toBuild = []; 72 | for (const key in stateVariables) { 73 | if (stateVariables[key]) toBuild.push(key); 74 | } 75 | return toBuild; 76 | } 77 | 78 | /** buildConfig takes selected state variable and update rules, 79 | * uses helper function to convert selected state variable into 80 | * a filtered array, and maps over that array to form an array of 81 | * update objects pulled from update rules. `merge` helper function called 82 | * from within a reducer to combine all update rules in the 83 | * array into a single result object. 84 | */ 85 | const buildConfig = (stateVariables, updateObjects) => { 86 | /** Convert stateVariables object into a filtered array. 87 | * Need an array that has the name of all the checkboxes 88 | * that are set to true. The names should match the names 89 | * of the corresponding update in updateObjects. 90 | */ 91 | const toBuild = buildList(stateVariables); 92 | 93 | /** Map array of selected boxes to create array of objects to merge */ 94 | const buildObjects = toBuild.map((objectName) => updateObjects[objectName]); 95 | 96 | /** Build config object by reducing all update objects to a single object using merge */ 97 | return buildObjects.reduce((config, update) => { 98 | return merge(config, update) 99 | }, updateObjects.nolibrary); 100 | }; 101 | 102 | /** Returns a string containing requirements matching current checkbox selections. */ 103 | const buildRequirements = (stateVariables, requirementsList) => { 104 | // Create an array containing the names of currently checked boxes 105 | const toBuild = buildList(stateVariables); 106 | 107 | // Map over array of checked objects, building an array of matching requirements. 108 | const requirements = toBuild.map((objectName) => requirementsList[objectName]); 109 | // Filter empty strings 110 | const filteredReqs = requirements.filter((item) => item.length > 0); 111 | 112 | // Loop through array of update strings, concatenating them into a single string. 113 | let requirementString = ''; 114 | filteredReqs.forEach((el) => requirementString += el + `\n`); 115 | 116 | return requirementString; 117 | } 118 | /** Returns a string containing packages matching current checkbox and radio selections. */ 119 | const buildDeps = (stateVariables, depsList) => { 120 | // Create an array containing the names of currently checked boxes and radio buttons 121 | const toBuildReg = buildList(stateVariables); 122 | 123 | // Map over array of checked objects, building an array of matching requirements. 124 | const deps = toBuildReg.map((objectName) => depsList[objectName]); 125 | // Filter empty strings 126 | const filteredDeps = deps.filter((item) => item.length > 0); 127 | 128 | // Loop through array of update strings, concatenating them into a single string. 129 | let depstring = ''; 130 | filteredDeps.forEach((el) => { 131 | // Join array as string (remove commas) 132 | if (Array.isArray(el)) { 133 | el = el.join(' '); 134 | } 135 | depstring += el + ` ` 136 | }); 137 | 138 | return depstring; 139 | } 140 | 141 | //return a string containing dependency state and development dependency state 142 | const installScript = (stateVariables, dep, devDep) => { 143 | //check if the object is empty, return empty string 144 | if (Object.keys(dep).length === 0 && Object.keys(devDep).length === 0) return ''; 145 | const reg = buildDeps(stateVariables, dep); 146 | const dev = buildDeps(stateVariables, devDep); 147 | 148 | // npm i reg && npm i -D dev 149 | return `npm i ${reg} && npm i -D ${dev}` 150 | } 151 | export { fetchedRulesToObjects, merge, buildConfig, buildRequirements, buildList, buildDeps, installScript }; -------------------------------------------------------------------------------- /client/components/webpackComponents/DevServer.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stanpython/Webpack-Configurator/7aaed0fba9566bf997c24dcab22063edd7584acb/client/components/webpackComponents/DevServer.jsx -------------------------------------------------------------------------------- /client/components/webpackComponents/Frontend.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Frontend = (props) => { 5 | 6 | const handleChange = (event) => { 7 | 8 | props.onChange(event.target.value, event.target.checked); 9 | }; 10 | 11 | return ( 12 |
13 | 19 |
20 | ) 21 | } 22 | 23 | export default Frontend; -------------------------------------------------------------------------------- /client/components/webpackComponents/Image.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Image = (props) => { 5 | 6 | const handleChange = (e) => { 7 | props.onChange(e.target.value, e.target.checked); 8 | } 9 | 10 | return ( 11 |
12 | 16 |
17 | ) 18 | } 19 | 20 | export default Image; -------------------------------------------------------------------------------- /client/components/webpackComponents/Linting.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Linting = (props) => { 5 | 6 | const handleChange = (event) => { 7 | props.onChange(event.target.value, event.target.checked); 8 | }; 9 | 10 | return ( 11 |
12 | 16 |
17 | ) 18 | } 19 | 20 | export default Linting; -------------------------------------------------------------------------------- /client/components/webpackComponents/Optimization.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Optimization = (props) => { 5 | 6 | const handleChange = (e) => { 7 | props.onChange(e.target.value, e.target.checked); 8 | } 9 | 10 | return ( 11 |
12 | 15 |
16 | ) 17 | } 18 | 19 | export default Optimization; -------------------------------------------------------------------------------- /client/components/webpackComponents/Plugin.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | 5 | const Plugin = (props) => { 6 | 7 | const handleChange = (e) => { 8 | props.onChange(e.target.value, e.target.checked); 9 | } 10 | 11 | return ( 12 |
13 | 20 | 21 |
22 | ) 23 | } 24 | 25 | export default Plugin; -------------------------------------------------------------------------------- /client/components/webpackComponents/Styling.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Styling = (props) => { 5 | 6 | const handleChange = (e) => { 7 | props.onChange(e.target.value, e.target.checked); 8 | } 9 | 10 | return ( 11 |
12 | 19 |
20 | ) 21 | } 22 | 23 | export default Styling; -------------------------------------------------------------------------------- /client/components/webpackComponents/Test.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | 5 | const Test = (props) => { 6 | 7 | const handleChange = (e) => { 8 | props.onChange(e.target.value, e.target.checked); 9 | } 10 | 11 | return ( 12 |
13 | 22 |
23 | ) 24 | } 25 | 26 | export default Test; -------------------------------------------------------------------------------- /client/components/webpackComponents/Transpiler.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Transpiler = (props) => { 5 | 6 | // here we tie the selections to the state selected, and the logic is so that 7 | // some of the logic is dependent on other radios or checkboxes 8 | 9 | const handleChange = (e) => { 10 | props.onChange(e.target.value, e.target.checked); 11 | } 12 | 13 | return ( 14 |
15 | 19 |
20 | ) 21 | } 22 | 23 | export default Transpiler; -------------------------------------------------------------------------------- /client/components/webpackComponents/UI.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const UI = (props) => { 5 | 6 | const handleChange = (e) => { 7 | props.onChange(e.target.value, e.target.checked); 8 | } 9 | 10 | return ( 11 |
12 | 16 |
17 | ) 18 | } 19 | 20 | export default UI; -------------------------------------------------------------------------------- /client/components/webpackComponents/Utilities.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import '../../css/App.css'; 3 | 4 | const Utilities = (props) => { 5 | 6 | const handleChange = (e) => { 7 | props.onChange(e.target.value, e.target.checked); 8 | } 9 | 10 | return ( 11 |
12 | 16 |
17 | ) 18 | } 19 | 20 | export default Utilities; -------------------------------------------------------------------------------- /client/css/App.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #F5F5F5; 3 | font-family: 'Source Code Pro','Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 4 | font-size: 16px; 5 | color: #282b36; 6 | } 7 | h1 { 8 | text-align: center; 9 | font-family: 'Roboto'; 10 | } 11 | header { 12 | margin: 50px 0; 13 | } 14 | .version { 15 | color: #da10e6; 16 | text-shadow: 1px 1px #000000b8, 2px 2px #000000b8, 3px 3px #000000b8; 17 | } 18 | #copy { 19 | margin-top: 30px; 20 | } 21 | #copy .hljs { 22 | padding: 15px; 23 | } 24 | .main-container { 25 | display: flex; 26 | justify-content: center; 27 | width: 1200px; 28 | margin: 0 auto; 29 | padding-bottom: 40px; 30 | } 31 | .component-container { 32 | font-size: 14px; 33 | } 34 | .code-container { 35 | width: 75%; 36 | margin-left: 0; 37 | } 38 | code.javascript.hljs { 39 | min-height: 850px; 40 | border-radius: 8px; 41 | box-shadow: 0 0 8px #00000078; 42 | padding: 25px; 43 | } 44 | strong { 45 | color: #b32e9c; 46 | } 47 | pre { 48 | margin-top: 5px; 49 | } 50 | ul { 51 | margin: 5px 5px 0 0; 52 | padding-left: 0; 53 | } 54 | 55 | li { 56 | list-style: none; 57 | } 58 | 59 | .hljs-attr { 60 | color: #d289cc; 61 | } 62 | .hljs-bullet, .hljs-quote, .hljs-link, .hljs-number, .hljs-regexp, .hljs-literal { 63 | color: #8be9fd !important; 64 | } 65 | .hljs-subst, .hljs-type, .hljs-built_in, .hljs-builtin-name, .hljs-symbol, .hljs-selector-id, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-template-tag, .hljs-template-variable, .hljs-addition { 66 | color: #ffcb06 !important; 67 | } 68 | .btn-outline-dark { 69 | float: right; 70 | } 71 | input[type=checkbox], input[type=radio] { 72 | box-sizing: border-box; 73 | margin-right: 5px; 74 | } 75 | .btn-outline-info { 76 | margin-right: 15px; 77 | float: right; 78 | } -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 |
14 |

Webpack Generator 2.0

15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import App from './components/App'; 4 | 5 | // should grab the App component and attach to the index.html 6 | render(, 7 | document.getElementById('root'), 8 | ); -------------------------------------------------------------------------------- /controller/data.js: -------------------------------------------------------------------------------- 1 | const models = require("../models/dependencies"); 2 | const dependencies = require("../models/dependencies"); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const webpackController = {}; 6 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 7 | 8 | // webpackController.add = async (req, res, next) => { 9 | // const arr = [ 10 | 11 | // ] 12 | // let request = await models.Library.insertMany(arr); 13 | 14 | // res.locals.added = request; 15 | // next(); 16 | // } 17 | 18 | webpackController.getAll = async (req, res, next) => { 19 | const response = await models.Library.find({}) 20 | res.locals.data = response; 21 | next(); 22 | }; 23 | 24 | webpackController.writeFile = async (req, res, next) => { 25 | const textForFile = req.body.fileContents; 26 | fs.writeFileSync(path.resolve(__dirname, '../filesToServe/webpack-config.js'), textForFile); 27 | next(); 28 | } 29 | 30 | 31 | 32 | module.exports = webpackController; 33 | 34 | // { 35 | // name: "tailwindcss", 36 | // code: { 37 | // module: { 38 | // rules: [ 39 | // { 40 | // test: "/\.css$/", 41 | // use: [ 42 | // 'style-loader', 43 | // { 44 | // loader: 'css-loader', 45 | // options: { 46 | // importLoaders: 1 47 | // } 48 | // }, 49 | // 'postcss-loader' 50 | // ] 51 | // } 52 | // ] 53 | // } 54 | // }, 55 | // require: "", 56 | // dependencies: ["tailwindcss"], 57 | // devDependencies: [] 58 | // }, 59 | // { 60 | // name: "cssmodules", 61 | // code: { 62 | // module: { 63 | // rules: [ 64 | // { 65 | // test: "/\.css$/", 66 | // use: [ 67 | // "style-loader", 68 | // { 69 | // loader: "css-loader", 70 | // options: { 71 | // importLoaders: 1, 72 | // modules: true, 73 | // }, 74 | // }, 75 | // ], 76 | // }, 77 | // ], 78 | // }, 79 | // }, 80 | // require: "", 81 | // dependencies: [], 82 | // devDependencies: ["css-loader", "style-loader"] 83 | // } 84 | 85 | // { 86 | // name: "webpackbundleanalyzer", 87 | // code: { 88 | // plugins: [ 89 | // new BundleAnalyzerPlugin({ 90 | // analyzerMode: "static", 91 | // openAnalyzer: false, 92 | // }) 93 | // ] 94 | // }, 95 | // require: "const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;", 96 | // dependencies: [], 97 | // devDependencies: ["webpack-bundle-analyzer"] 98 | // } 99 | 100 | // { 101 | // name: "prettier", 102 | // code: {}, 103 | // require: "", 104 | // dependencies: [], 105 | // devDependencies: ["prettier", "eslint-config-prettier", "eslint-plugin-prettier"] 106 | // } 107 | 108 | // { 109 | // name: "eslint", 110 | // code: {}, 111 | // require: "", 112 | // dependencies: [], 113 | // devDependencies: ["eslint"] 114 | // } 115 | 116 | // { 117 | // name: "testcafe", 118 | // code: {}, 119 | // require: "", 120 | // dependencies: [], 121 | // devDependencies: ["testcafe"] 122 | // } 123 | 124 | // { 125 | // name: "cypress", 126 | // code: {}, 127 | // require: "", 128 | // dependencies: [], 129 | // devDependencies: ["cypress"] 130 | // } 131 | 132 | // { 133 | // name: "ava", 134 | // code: {}, 135 | // require: "", 136 | // dependencies: [], 137 | // devDependencies: ["ava"] 138 | // } 139 | 140 | // { 141 | // name: "jasmine", 142 | // code: {}, 143 | // require: "", 144 | // dependencies: [], 145 | // devDependencies: ["jasmine"] 146 | // } 147 | 148 | // { 149 | // name: "chai", 150 | // code: {}, 151 | // require: "", 152 | // dependencies: [], 153 | // devDependencies: ["chai"] 154 | // } 155 | 156 | // { 157 | // name: "mocha", 158 | // code: {}, 159 | // require: "", 160 | // dependencies: [], 161 | // devDependencies: ["mocha"] 162 | // } 163 | 164 | // { 165 | // name: "jest", 166 | // code: {}, 167 | // require: "", 168 | // dependencies: [], 169 | // devDependencies: ["jest"] 170 | // } 171 | 172 | // { 173 | // name: "bootstrap", 174 | // code: {}, 175 | // require: "", 176 | // dependencies: ["bootstrap", "jquery", "popper.js"], 177 | // devDependencies: ["css-loader", "style-loader"] 178 | // } 179 | 180 | // { 181 | // name: "cleanwebpackplugin", 182 | // code: { 183 | // plugins: [ 184 | // "new CleanWebpackPlugin()" 185 | // ] 186 | // }, 187 | // require: "const { CleanWebpackPlugin } = require('clean-webpack-plugin');", 188 | // dependencies: [], 189 | // devDependencies: ["clean-webpack-plugin"] 190 | // } 191 | 192 | // { 193 | // name: "copywebpackplugin", 194 | // code: { 195 | // plugins: [ 196 | // "new CopyPlugin({ patterns: [{ from: 'src/index.html' }], })" 197 | // ], 198 | // }, 199 | // require: "const CopyPlugin = require('copy-webpack-plugin');", 200 | // dependencies: [], 201 | // devDependencies: ["copy-webpack-plugin"] 202 | // } 203 | 204 | // { 205 | // name: "minicssextractplugin", 206 | // code: { 207 | // plugins: [ 208 | // "new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false, })" 209 | // ], 210 | // }, 211 | // require: "const MiniCssExtractPlugin = require('mini-css-extract-plugin');", 212 | // dependencies: [], 213 | // devDependencies: ["mini-css-extract-plugin"] 214 | // } 215 | 216 | // { 217 | // name: "htmlwebpackplugin", 218 | // code: { 219 | // plugins: [ 220 | // "new HtmlWebpackPlugin({ appMountId: 'app', filename: 'index.html'})" 221 | // ], 222 | // }, 223 | // require: "const HtmlWebpackPlugin = require('html-webpack-plugin');", 224 | // dependencies: [], 225 | // devDependencies: ["html-webpack-plugin"] 226 | // } 227 | 228 | // { 229 | // name: "codesplitvendor", 230 | // code: { 231 | // output: { 232 | // filename: "[name].[contenthash].js" 233 | // }, 234 | // module: { 235 | // rules: [ 236 | // { 237 | // test: "/\.js$/", 238 | // use: "babel-loader", 239 | // exclude: "/node_modules/" 240 | // }, 241 | // ], 242 | // }, 243 | // optimization: { 244 | // runtimeChunk: "single", 245 | // splitChunks: { 246 | // cacheGroups: { 247 | // vendor: { 248 | // test: "/[\\/]node_modules[\\/]/", 249 | // name: "vendors", 250 | // chunks: "all", 251 | // }, 252 | // }, 253 | // }, 254 | // }, 255 | // devServer: { 256 | // contentBase: './dist', 257 | // }, 258 | // }, 259 | // require: "", 260 | // dependencies: [], 261 | // devDependencies: ["html-webpack-plugin"] 262 | // } 263 | 264 | // { 265 | // name: "lodash", 266 | // code: { 267 | // plugins: [ 268 | // "new LodashModuleReplacementPlugin" 269 | // ], 270 | // }, 271 | // require: "const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');", 272 | // dependencies: ["lodash"], 273 | // devDependencies: ["lodash-webpack-plugin"] 274 | // } 275 | 276 | // { 277 | // name: "moment", 278 | // code: { 279 | // plugins: [ 280 | // "new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/)" 281 | // ] 282 | // }, 283 | // require: "", 284 | // dependencies: [ 285 | // "moment" 286 | // ], 287 | // devDependencies: [] 288 | // } 289 | 290 | // { 291 | // name: "typescript", 292 | // code: { 293 | // entry: "./src/index.ts", 294 | // module: { 295 | // rules: [ 296 | // { 297 | // test: "/\.ts(x)?$/", 298 | // loader: "ts-loader", 299 | // exclude: "/node_modules/", 300 | // }, 301 | // ], 302 | // }, 303 | // resolve: { 304 | // extensions: [ 305 | // ".tsx", 306 | // ".ts", 307 | // ".js", 308 | // ], 309 | // }, 310 | // }, 311 | // require: "", 312 | // dependencies: [], 313 | // devDependencies: ["typescript", "ts-loader", "@types/react", "types/react-dom"] 314 | // } 315 | 316 | // { 317 | // name: "less", 318 | // code: { 319 | // module: { 320 | // rules: [ 321 | // { 322 | // test: "/\.less$/", 323 | // use: [ 324 | // "style-loader", 325 | // "css-loader", 326 | // "less-loader", 327 | // ], 328 | // }, 329 | // ], 330 | // }, 331 | // }, 332 | // require: "", 333 | // dependencies: [], 334 | // devDependencies: ["css-loader", "less-loader", "less", "style-loader"] 335 | // } 336 | 337 | // { 338 | // name: "stylus", 339 | // code: { 340 | // module: { 341 | // rules: [ 342 | // { 343 | // test: "/\.styl$/", 344 | // use: [ 345 | // "style-loader", 346 | // "css-loader", 347 | // "stylus-loader", 348 | // ], 349 | // }, 350 | // ], 351 | // }, 352 | // }, 353 | // require: "", 354 | // dependencies: [], 355 | // devDependencies: ["css-loader", "stylus-loader", "stylus", "style-loader"] 356 | // } 357 | 358 | // { 359 | // name: "svg", 360 | // code: { 361 | // module: { 362 | // rules: [ 363 | // { 364 | // test: "/\.svg$/", 365 | // use: "file-loader", 366 | // }, 367 | // ], 368 | // }, 369 | // }, 370 | // require: "", 371 | // dependencies: [], 372 | // devDependencies: ["file-loader"] 373 | // } 374 | 375 | // { 376 | // name: "png", 377 | // code: { 378 | // module: { 379 | // rules: [ 380 | // { 381 | // test: '/\.png$/', 382 | // use: [ 383 | // { 384 | // loader: 'url-loader', 385 | // options: { 386 | // mimetype: 'image/png', 387 | // }, 388 | // }, 389 | // ], 390 | // }, 391 | // ], 392 | // }, 393 | // }, 394 | // require: "", 395 | // dependencies: [], 396 | // devDependencies: ["url-loader"] 397 | // } 398 | 399 | // { 400 | // name: "nolibrary", 401 | // code: { 402 | // entry: './src/index.js', 403 | // output: { 404 | // path: "path.resolve(__dirname, 'dist')", 405 | // filename: 'bundle.js', 406 | // }, 407 | // }, 408 | // require: "", 409 | // dependencies: [], 410 | // devDependencies: [] 411 | // } 412 | 413 | // { 414 | // name: "svelte", 415 | // code: { 416 | // module: { 417 | // rules: [ 418 | // { 419 | // test: "/\.svelte$/", 420 | // loader: 'svelte-loader', 421 | // options: { 422 | // preprocess: "require('svelte-preprocess')({})", 423 | // }, 424 | // }, 425 | // ], 426 | // }, 427 | // resolve: { 428 | // extensions: [ 429 | // '.mjs', 430 | // '.js', 431 | // '.svelte', 432 | // ], 433 | // }, 434 | // }, 435 | // require: "", 436 | // dependencies: [], 437 | // devDependencies: ["svelte", "svelte-loader", "svelte-preprocess"] 438 | // } 439 | 440 | // { 441 | // name: "vue", 442 | // code: { 443 | // module: { 444 | // rules: [ 445 | // { 446 | // test: "/\.vue$/", 447 | // loader: 'vue-loader', 448 | // }, 449 | // ], 450 | // }, 451 | // resolve: { 452 | // extensions: [ 453 | // '.js', 454 | // '.vue', 455 | // ], 456 | // }, 457 | // plugins: [ 458 | // "new VueLoaderPlugin()" 459 | // ], 460 | // }, 461 | // require: "const VueLoaderPlugin = require('vue-loader/lib/plugin');", 462 | // dependencies: ["vue"], 463 | // devDependencies: ["vue-loader", "vue-template-compiler", "babel-loader", "@babel-core", "@babel/preset-env"] 464 | // } 465 | 466 | // { 467 | // name: "babel", 468 | // code: { 469 | // module: { 470 | // rules: [ 471 | // { 472 | // test: "/\.(js|jsx)$/", 473 | // use: { 474 | // loader: 'babel-loader', 475 | // options: { 476 | // presets: ['@babel/preset-env', '@babel/preset-react'], 477 | // }, 478 | // }, 479 | // }, 480 | // ], 481 | // }, 482 | // resolve: { 483 | // extensions: [ 484 | // '.js', 485 | // '.jsx', 486 | // ], 487 | // }, 488 | // }, 489 | // require: "", 490 | // dependencies: [], 491 | // devDependencies: ["babel-loader", "@babel-core", "@babel/preset-env"] 492 | // } 493 | 494 | // { 495 | // name: "css", 496 | // code: { 497 | // modules: { 498 | // rules: [ 499 | // { 500 | // test: /\.css$/, 501 | // use: [ 502 | // 'style-loader', 503 | // 'css-loader', 504 | // ], 505 | // }, 506 | // ], 507 | // }, 508 | // }, 509 | // require: "", 510 | // dependencies: [], 511 | // devDependencies: ["css-loader", "style-loader"] 512 | // } 513 | 514 | // { 515 | // name: "react", 516 | // code: { 517 | // modules: { 518 | // rules: [ 519 | // { 520 | // test: "/\.(js|jsx)$/", 521 | // use: "babel-loader", 522 | // exclude: "/node_modules/" 523 | // }, 524 | // ], 525 | // }, 526 | // resolve: { 527 | // extensions: [ 528 | // '.js', 529 | // '.jsx', 530 | // ], 531 | // } 532 | // }, 533 | // require: "", 534 | // dependencies: ["react", "react-dom", "react-hot-loader"], 535 | // devDependencies: ["webpack", "webpack-cli", "babel-loader", "@babel/core", "@babel/preset-env", "@hot-loader/react-dom", "@babel/preset-react", "webpack-dev-server"] 536 | // } 537 | 538 | 539 | // { 540 | // name: "sass", 541 | // code: { 542 | // modules: { 543 | // rules: [ 544 | // { 545 | // test: "/\.scss$/", 546 | // use: [ 547 | // 'style-loader', 548 | // 'css-loader', 549 | // 'sass-loader', 550 | // ], 551 | // }, 552 | // ], 553 | // }, 554 | // }, 555 | // require: "", 556 | // dependencies: [], 557 | // devDependencies: ["css-loader", "style-loader", "sass-loader", "node-sass"] 558 | // } 559 | 560 | 561 | 562 | // =========================================== =============================================== 563 | 564 | 565 | // const db = require('../models/database'); 566 | // // const { query } = require('express'); 567 | // const dataObj = {}; 568 | 569 | // // Query database to receive all entries. Then organize entries and store each 'name' as a key on object with the properties of 570 | // // 'name' being the other columns. Send organized data to the frontend. 571 | // dataObj.getAll = (req, res, next) => { 572 | // const queryTest = 'SELECT * FROM "public"."webpack" LIMIT 100'; 573 | // db.query(queryTest).then((data) => { 574 | // const obj = {}; 575 | // data.rows.forEach((el) => { 576 | // obj[el.name] = { 577 | // npm: el.npm, 578 | // code: el.code, 579 | // description: el.description, 580 | // require: el.require, 581 | // }; 582 | // }); 583 | 584 | // res.locals.data = obj; 585 | 586 | // next(); 587 | // }); 588 | // }; 589 | 590 | // module.exports = dataObj; 591 | -------------------------------------------------------------------------------- /filesToServe/webpack-config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | 4 | module.exports = { 5 | entry: './src/index.js', 6 | output: { 7 | path: path.resolve(__dirname, 'dist'), 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | rules: [ 12 | { 13 | test: /.(js|jsx)$/, 14 | use: 'babel-loader', 15 | exclude: /node_modules/ 16 | }, 17 | { 18 | test: /.(js|jsx)$/, 19 | use: { 20 | loader: 'babel-loader', 21 | options: { 22 | presets: [ 23 | '@babel/preset-env', 24 | '@babel/preset-react' 25 | ] 26 | } 27 | } 28 | }, 29 | { 30 | test: /\.css$/, 31 | use: [ 32 | 'style-loader', 33 | 'css-loader' 34 | ] 35 | } 36 | ] 37 | }, 38 | resolve: { 39 | extensions: [ 40 | '.js', 41 | '.jsx' 42 | ] 43 | } 44 | } -------------------------------------------------------------------------------- /models/database.js: -------------------------------------------------------------------------------- 1 | const { Pool } = require('pg'); 2 | 3 | // ElephantSQL URI - Send Taylor or Patrick a Slack for access to database 4 | const PG_URI = 5 | 'postgres://qquarylc:9f-WympV5l824vTHMGwyNrlOfAM572tk@raja.db.elephantsql.com:5432/qquarylc'; 6 | 7 | // Pool creates an open connection to database 8 | // https://node-postgres.com/features/pooling 9 | const pool = new Pool({ 10 | connectionString: PG_URI, 11 | }); 12 | 13 | module.exports = { 14 | query: (text, params, callback) => { 15 | console.log('executed query', text); 16 | return pool.query(text, params, callback); 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /models/dependencies.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const MONGO_URI = 'mongodb+srv://webpackconfigassist:Codesmith55463@cluster0.n48qo.mongodb.net/webpackconfig?retryWrites=true&w=majority'; 4 | // const string = 'mongorestore --uri="mongodb+srv://webpackconfigassist:Codesmith55463@cluster0.n48qo.mongodb.net/?retryWrites=true&w=majority"' 5 | 6 | mongoose.connect(MONGO_URI, { 7 | // options for the connect method to parse the URI 8 | useNewUrlParser: true, 9 | useUnifiedTopology: true, 10 | // sets the name of the DB that our collections are part of 11 | dbName: 'webpackconfig' 12 | }) 13 | .then(() => console.log('Connected to Mongo DB.')) 14 | .catch(err => console.log(err)); 15 | 16 | const Schema = mongoose.Schema; 17 | 18 | // sets a schema for the 'dependencies' collection 19 | const dependenciesSchema = new Schema({ 20 | name: { type: String, unique: true }, 21 | code: { type: Object, required: true, }, 22 | require: String, 23 | dependencies: Array, 24 | devDependencies: Array 25 | }); 26 | 27 | // creats a model for the 'dependencies' collection that will be part of the export 28 | const Dependencies = mongoose.model('dependencies', dependenciesSchema); 29 | 30 | const librarySchema = new Schema({ 31 | name: { type: String, unique: true }, 32 | code: { type: Object, required: true, }, 33 | require: String, 34 | dependencies: Array, 35 | devDependencies: Array 36 | }); 37 | 38 | const Library = mongoose.model('library', librarySchema); 39 | 40 | // exports the model in an object to be used in the controller 41 | module.exports = { Dependencies, Library }; 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebpackConfigAssist", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "concurrently \"cross-env NODE_ENV=development webpack-dev-server --open --hot \" \"nodemon server/server.js\"", 9 | "start": "NODE_ENV=production nodemon server/server.js", 10 | "build": "NODE_ENV=production webpack" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/patrick934/WebpackConfigAssist.git" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/patrick934/WebpackConfigAssist/issues" 21 | }, 22 | "homepage": "https://github.com/patrick934/WebpackConfigAssist#readme", 23 | "dependencies": { 24 | "@babel/plugin-transform-runtime": "^7.11.0", 25 | "@reduxjs/toolkit": "^1.4.0", 26 | "bootstrap": "^4.5.2", 27 | "concurrently": "^5.3.0", 28 | "cors": "^2.8.5", 29 | "express": "^4.17.1", 30 | "highlight.js": "^10.1.2", 31 | "hot-module-replacement": "^3.0.4", 32 | "mini-css-extract-plugin": "^0.10.0", 33 | "mongoose": "^5.10.0", 34 | "node-fetch": "^2.6.0", 35 | "nodemon": "^2.0.4", 36 | "pg": "^8.3.0", 37 | "react": "^16.13.1", 38 | "react-bootstrap": "^1.3.0", 39 | "react-copy-to-clipboard": "^5.0.2", 40 | "react-dom": "^16.13.1", 41 | "react-highlight": "^0.12.0", 42 | "react-router": "^5.2.0", 43 | "react-router-dom": "^5.2.0", 44 | "redux": "^4.0.5", 45 | "stringify-object": "^3.3.0", 46 | "webpack-bundle-analyzer": "^3.8.0", 47 | "webpack-dev-server": "^3.11.0", 48 | "webpack-node-externals": "^2.5.1" 49 | }, 50 | "devDependencies": { 51 | "@babel/core": "^7.11.1", 52 | "@babel/preset-env": "^7.11.0", 53 | "@babel/preset-react": "^7.10.4", 54 | "babel-loader": "^8.1.0", 55 | "cross-env": "^7.0.2", 56 | "css-loader": "^4.2.1", 57 | "html-webpack-plugin": "^4.3.0", 58 | "sass-loader": "^9.0.3", 59 | "style-loader": "^1.2.1", 60 | "webpack": "^4.44.1", 61 | "webpack-cli": "^3.3.12" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /route/api.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | // const dataController = require('../controller/data'); 3 | const router = express.Router(); 4 | const webpackController = require('../controller/data'); 5 | 6 | // router.use('/add', webpackController.add, (req, res) => { 7 | // res.status(202).json(res.locals.added); 8 | // }); 9 | 10 | router.use('/', webpackController.getAll, (req, res) => { 11 | res.status(202).json(res.locals.data); 12 | }); 13 | 14 | module.exports = router; 15 | -------------------------------------------------------------------------------- /route/download.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const webpackController = require('../controller/data'); 4 | const path = require('path'); 5 | const { config } = require('process'); 6 | 7 | router.post('/', webpackController.writeFile, (req, res) => { 8 | res.download(path.resolve(__dirname, '../filesToServe', 'webpack-config.js')); 9 | }); 10 | 11 | router.get('/', (req, res) => { 12 | res.download(path.resolve(__dirname, '../filesToServe', 'webpack-config.js')); 13 | }); 14 | 15 | module.exports = router; -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const path = require('path'); 4 | const cors = require('cors'); 5 | 6 | // Require cors to prevent error 7 | // The error is most likely related to HTTP headers 8 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS 9 | 10 | app.use(cors()) 11 | app.use(express.json()); 12 | app.use(express.urlencoded()); 13 | 14 | const apiRoute = require('../route/api'); 15 | const downloadRoute = require('../route/download'); 16 | app.use('/api', apiRoute); 17 | app.use('/download', downloadRoute); 18 | 19 | if (process.env.NODE_ENV === 'production') { 20 | app.use('/build', express.static(path.join(__dirname, '../build'))); 21 | 22 | app.get('/', (req, res) => { 23 | res.sendFile(path.resolve(__dirname, '../client/index.html')); 24 | }); 25 | } 26 | 27 | app.listen(process.env.PORT || 3000, () => console.log('Listening on port 3000...')); 28 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | 6 | module.exports = { 7 | entry: path.resolve(__dirname, './client/index.js'), 8 | output: { 9 | path: path.resolve(__dirname, 'build'), 10 | filename: 'bundle.js', 11 | }, 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.jsx?/, 16 | exclude: /node_modules/, 17 | use: { 18 | loader: 'babel-loader', 19 | options: { 20 | presets: ['@babel/preset-env', '@babel/preset-react'], 21 | plugins: ['@babel/plugin-transform-runtime'], 22 | }, 23 | }, 24 | }, 25 | { 26 | test: /\.css$/i, 27 | use: ['style-loader', 'css-loader'], 28 | }, 29 | ], 30 | }, 31 | plugins: [new HtmlWebpackPlugin(), new MiniCssExtractPlugin()], 32 | mode: process.env.NODE_ENV, 33 | resolve: { 34 | extensions: ['.js', '.jsx'], 35 | }, 36 | devServer: { 37 | // host: 'localhost', 38 | // port: 8080, 39 | contentBase: path.join(__dirname, './client'), 40 | publicPath: '/build/', 41 | historyApiFallback: true, 42 | hot: true, 43 | proxy: { 44 | '/api': 'http://localhost:3000', 45 | '/download': 'http://localhost:3000', 46 | }, 47 | }, 48 | }; 49 | --------------------------------------------------------------------------------