diff --git a/.eslintrc.json b/.eslintrc.json index 895b737..b66130c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,44 +1,45 @@ -{ - "parserOptions": { - "ecmaVersion": 9 - }, - "extends": "google", - "rules": { +{ + "parserOptions": { + "ecmaVersion": 9 + }, + "extends": "google", + "rules": { "no-unused-vars": 0, "no-tabs": 0, "one-var": 0, + "linebreak-style": 0, "brace-style": ["error", "stroustrup", { "allowSingleLine": true }], - "max-len": 0, - "no-multiple-empty-lines": ["error", { "max": 1, "maxBOF": 1 }], - "padded-blocks": 0, - "curly": 0, - "object-curly-spacing": ["error", "always"], - "block-spacing": ["error", "always"], - "array-bracket-spacing": ["error", "always"], - "prefer-template": 2, - "new-cap": 0, - "guard-for-in": 0, - "indent": [ - "error", "tab", { - "CallExpression": { - "arguments": 1 - }, - "FunctionDeclaration": { - "body": 1, - "parameters": 2 - }, - "FunctionExpression": { - "body": 1, - "parameters": 2 - }, - "MemberExpression": 2, - "ObjectExpression": 1, - "SwitchCase": 1, - "ignoredNodes": [ - "ConditionalExpression", - "VariableDeclarator" - ] - } - ] - } -} + "max-len": 0, + "no-multiple-empty-lines": ["error", { "max": 1, "maxBOF": 1 }], + "padded-blocks": 0, + "curly": 0, + "object-curly-spacing": ["error", "always"], + "block-spacing": ["error", "always"], + "array-bracket-spacing": ["error", "always"], + "prefer-template": 2, + "new-cap": 0, + "guard-for-in": 0, + "indent": [ + "error", "tab", { + "CallExpression": { + "arguments": 1 + }, + "FunctionDeclaration": { + "body": 1, + "parameters": 2 + }, + "FunctionExpression": { + "body": 1, + "parameters": 2 + }, + "MemberExpression": 2, + "ObjectExpression": 1, + "SwitchCase": 1, + "ignoredNodes": [ + "ConditionalExpression", + "VariableDeclarator" + ] + } + ] + } +} diff --git a/local-server.js b/local-server.js index 4f88d6b..bb8ef80 100644 --- a/local-server.js +++ b/local-server.js @@ -1,90 +1,94 @@ -const htmlFiles = [ - 'header', - 'main', - 'dashboard/dashboard', - 'my-addresses/my-addresses', - 'new-address/new-address', - 'send/send', - 'transactions/transactions', - 'footer', - 'welcome/welcome', - 'restore/restore', - 'create-wallet/create-wallet', - 'set-password/set-password', - 'login/login', -]; - +const htmlFiles = [ + 'header', + 'main', + 'dashboard/dashboard', + 'my-addresses/my-addresses', + 'new-address/new-address', + 'send/send', + 'transactions/transactions', + 'footer', + 'welcome/welcome', + 'restore/restore', + 'create-wallet/create-wallet', + 'set-password/set-password', + 'login/login', +]; + let workDir = '/src/'; if (process.env.DIST_FOLDER) workDir = `/${process.env.DIST_FOLDER}/`; const express = require('express'); const app = express(); const fs = require('fs'); +const packageConfig = require('./package.json').config || {}; + +process.env.IP = process.env.IP || packageConfig.IP; +process.env.PORT = process.env.PORT || packageConfig.PORT; if ( ! process.env.IP || ! process.env.PORT) { console.error('Need to specify IP and PORT environments (example: IP=192.168.23.42 PORT=80 node local-server.js) !'); - process.exit(); -} - -let server; -if (process.env.PORT !== '443') server = require('http').createServer(app); -else server = require('https').createServer({ - pfx: fs.readFileSync(`${__dirname}/localhost.pfx`), - passphrase: '12345', -}, app); - -server.listen(process.env.PORT, process.env.IP, () => { - const address = server.address().address; - console.log(`Server running at http${process.env.PORT === '443' ? 's' : ''}://${address === '127.0.0.1' ? 'localhost' : address}:${server.address().port} from ${workDir}`); -}); - -app.use(express.static(__dirname + workDir)); - -if (workDir === '/src/') { - const path = require('path'); - - const templateJs = (file) => { return ``; }; - const templateCss = (file) => { return ``; }; - - let pathJsFiles = ``; - let pathCssFiles = ``; - - const generatePathFiles = async (filePath = '') => { - const fullFilePath = workDir + filePath; - let files; - try { - files = fs.readdirSync(path.join(__dirname, fullFilePath)); - } - catch (err) { - return console.error(`unable read files ${fullFilePath}:`, err); - } - for await (const file of files) { - const fileExt = path.extname(file).substr(1); - if (fileExt === 'js') pathJsFiles += templateJs(file); - else if (fileExt === 'css') pathCssFiles += templateCss(file); - else if ( ! fileExt) { - app.use(express.static(__dirname + fullFilePath + file)); - generatePathFiles(filePath + file); - } - } - }; - - (async () => { - await generatePathFiles('../lib/'); - await generatePathFiles(); - })(); - - app.use(express.static(`${__dirname}/public/`)); - app.use(express.static(`${__dirname}/lib/`)); - - app.get('/', (req, res) => { - let outputStr = ''; - outputStr += pathCssFiles; - htmlFiles.forEach((htmlFile) => { - outputStr += fs.readFileSync(`${__dirname + workDir + htmlFile}.html`); - }); - outputStr += pathJsFiles; - res.setHeader('Content-Type', 'text/html'); - res.send(outputStr); - }); -} + process.exit(); +} + +let server; +if (process.env.PORT !== '443') server = require('http').createServer(app); +else server = require('https').createServer({ + pfx: fs.readFileSync(`${__dirname}/localhost.pfx`), + passphrase: '12345', +}, app); + +server.listen(process.env.PORT, process.env.IP, () => { + const address = server.address().address; + console.log(`Server running at http${process.env.PORT === '443' ? 's' : ''}://${address === '127.0.0.1' ? 'localhost' : address}:${server.address().port} from ${workDir}`); +}); + +app.use(express.static(__dirname + workDir)); + +if (workDir === '/src/') { + const path = require('path'); + + const templateJs = (file) => { return ``; }; + const templateCss = (file) => { return ``; }; + + let pathJsFiles = ``; + let pathCssFiles = ``; + + const generatePathFiles = async (filePath = '') => { + const fullFilePath = workDir + filePath; + let files; + try { + files = fs.readdirSync(path.join(__dirname, fullFilePath)); + } + catch (err) { + return console.error(`unable read files ${fullFilePath}:`, err); + } + for await (const file of files) { + const fileExt = path.extname(file).substr(1); + if (fileExt === 'js') pathJsFiles += templateJs(file); + else if (fileExt === 'css') pathCssFiles += templateCss(file); + else if ( ! fileExt) { + app.use(express.static(__dirname + fullFilePath + file)); + generatePathFiles(filePath + file); + } + } + }; + + (async () => { + await generatePathFiles('../lib/'); + await generatePathFiles(); + })(); + + app.use(express.static(`${__dirname}/public/`)); + app.use(express.static(`${__dirname}/lib/`)); + + app.get('/', (req, res) => { + let outputStr = ''; + outputStr += pathCssFiles; + htmlFiles.forEach((htmlFile) => { + outputStr += fs.readFileSync(`${__dirname + workDir + htmlFile}.html`); + }); + outputStr += pathJsFiles; + res.setHeader('Content-Type', 'text/html'); + res.send(outputStr); + }); +} diff --git a/package.json b/package.json index 5bc89e4..ff14c64 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,40 @@ -{ - "name": "bitgesell-wallet", - "version": "0.9.5", - "description": "Bitgesell Wallet JS", - "homepage": "https://app.bglwallet.io", - "bugs": "https://github.com/epexa/bitgesell-wallet/issues", - "license": "Proprietary", - "author": "epexa", - "main": "local-server.js", - "repository": "epexa/bitgesell-wallet", - "config": { - "IP": "127.0.0.1", - "PORT": "80", - "DIST_FOLDER": "../bitgesell-wallet-dist" - }, +{ + "name": "bitgesell-wallet", + "version": "0.9.5", + "description": "Bitgesell Wallet JS", + "homepage": "https://app.bglwallet.io", + "bugs": "https://github.com/epexa/bitgesell-wallet/issues", + "license": "Proprietary", + "author": "epexa", + "main": "local-server.js", + "repository": "epexa/bitgesell-wallet", + "config": { + "IP": "127.0.0.1", + "PORT": "80", + "DIST_FOLDER": "../bitgesell-wallet-dist" + }, "scripts": { - "test": "eslint 'src/*.js'", - "local-server": "IP=$npm_package_config_IP PORT=$npm_package_config_PORT node local-server.js", + "test": "eslint src/*.js", + "local-server": "node local-server.js", "start": "npm test && npm run local-server", - "build": "./build.sh $npm_package_config_DIST_FOLDER", - "dist-start": "npm run build && DIST_FOLDER=$npm_package_config_DIST_FOLDER npm run local-server" - }, - "husky": { - "hooks": { - "pre-commit": "npm test" - } + "build": "npm test && node scripts/build.js", + "dist-start": "npm run build && node scripts/dist-server.js" }, - "devDependencies": { - "@babel/cli": "^7.2.3", - "@babel/core": "^7.4.0", - "@babel/preset-env": "^7.4.2", - "clean-css-cli": "^4.2.1", - "eslint": "^5.15.3", - "eslint-config-google": "^0.12.0", - "express": "^4.16.4", - "html-minifier": "^3.5.21", - "husky": "^2.3.0", - "uglify-js": "^3.5.2" - } -} + "husky": { + "hooks": { + "pre-commit": "npm test" + } + }, + "devDependencies": { + "@babel/cli": "^7.2.3", + "@babel/core": "^7.4.0", + "@babel/preset-env": "^7.4.2", + "clean-css-cli": "^4.2.1", + "eslint": "^5.15.3", + "eslint-config-google": "^0.12.0", + "express": "^4.16.4", + "html-minifier": "^3.5.21", + "husky": "^2.3.0", + "uglify-js": "^3.5.2" + } +} diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 0000000..69338f5 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,127 @@ +const fs = require('fs'); +const path = require('path'); +const { execFileSync } = require('child_process'); + +const rootDir = path.resolve(__dirname, '..'); +const packageConfig = require('../package.json').config || {}; +const distFolder = path.resolve( + rootDir, + process.argv[2] || + process.env.DIST_FOLDER || + process.env.npm_package_config_DIST_FOLDER || + packageConfig.DIST_FOLDER || + '../bitgesell-wallet-dist', +); + +const packageBin = (packageName, binName) => { + const packagePath = require.resolve(`${packageName}/package.json`); + const packageJson = require(packagePath); + const binConfig = packageJson.bin; + const binPath = typeof binConfig === 'string' ? binConfig : binConfig[binName]; + return path.join(path.dirname(packagePath), binPath); +}; + +const bins = { + babel: packageBin('@babel/cli', 'babel'), + uglifyjs: packageBin('uglify-js', 'uglifyjs'), + 'html-minifier': packageBin('html-minifier', 'html-minifier'), + cleancss: packageBin('clean-css-cli', 'cleancss'), +}; + +const run = (name, args) => { + execFileSync(process.execPath, [ bins[name], ...args ], { + cwd: rootDir, + stdio: 'inherit', + }); +}; + +const copyRecursive = (from, to) => { + fs.mkdirSync(to, { recursive: true }); + for (const entry of fs.readdirSync(from, { withFileTypes: true })) { + const source = path.join(from, entry.name); + const target = path.join(to, entry.name); + if (entry.isDirectory()) copyRecursive(source, target); + else fs.copyFileSync(source, target); + } +}; + +const src = (...parts) => path.join(rootDir, ...parts); +const dist = (...parts) => path.join(distFolder, ...parts); + +fs.mkdirSync(distFolder, { recursive: true }); +copyRecursive(src('public'), distFolder); + +const appJs = dist('app.js'); +run('babel', [ + src('src', 'utils.js'), + src('src', 'api.js'), + src('src', 'app.js'), + src('src', 'login', 'login.js'), + src('src', 'welcome', 'welcome.js'), + src('src', 'create-wallet', 'create-wallet.js'), + src('src', 'set-password', 'set-password.js'), + src('src', 'restore', 'restore.js'), + src('src', 'my-addresses', 'my-addresses.js'), + src('src', 'new-address', 'new-address.js'), + src('src', 'transactions', 'transactions.js'), + src('src', 'dashboard', 'dashboard.js'), + src('src', 'send', 'send.js'), + '-o', + appJs, +]); + +run('uglifyjs', [ + src('lib', '1-jquery.slim.min.js'), + src('lib', '2-jquery.dataTables.min.js'), + src('lib', '3-dataTables.bootstrap4.min.js'), + src('lib', '4-dataTables.responsive.min.js'), + src('lib', '5-responsive.bootstrap.min.js'), + src('lib', 'bootstrap-native.min.js'), + src('lib', 'sweetalert2.min.js'), + src('lib', 'qrcode.js'), + src('lib', 'satoshi-bitcoin.js'), + src('lib', 'aes4js.min.js'), + src('lib', 'dayjs.min.js'), + appJs, + '-c', + 'drop_console=true,toplevel=true', + '-m', + 'toplevel=true', + '-o', + dist('app.min.js'), +]); + +fs.unlinkSync(appJs); + +run('html-minifier', [ + '--collapse-whitespace', + '--remove-comments', + src('src', 'header.html'), + src('src', 'main.html'), + src('src', 'my-addresses', 'my-addresses.html'), + src('src', 'new-address', 'new-address.html'), + src('src', 'transactions', 'transactions.html'), + src('src', 'dashboard', 'dashboard.html'), + src('src', 'send', 'send.html'), + src('src', 'footer.html'), + src('src', 'welcome', 'welcome.html'), + src('src', 'create-wallet', 'create-wallet.html'), + src('src', 'restore', 'restore.html'), + src('src', 'set-password', 'set-password.html'), + src('src', 'login', 'login.html'), + '-o', + dist('index.html'), +]); + +run('cleancss', [ + src('lib', 'sweetalert2.min.css'), + src('lib', 'dataTables.bootstrap4.min.css'), + src('lib', 'responsive.bootstrap4.min.css'), + src('lib', 'icomoon.css'), + src('src', 'custom.css'), + '-o', + dist('custom.min.css'), + '--skip-rebase', +]); + +console.log(`Built wallet assets in ${distFolder}`); diff --git a/scripts/dist-server.js b/scripts/dist-server.js new file mode 100644 index 0000000..34b4569 --- /dev/null +++ b/scripts/dist-server.js @@ -0,0 +1,5 @@ +const packageConfig = require('../package.json').config || {}; + +process.env.DIST_FOLDER = process.env.DIST_FOLDER || packageConfig.DIST_FOLDER; + +require('../local-server');