diff --git a/.gitignore b/.gitignore index 98db37c172..f104fcdb43 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ lerna-debug.log* .vscode # App packaged +redisinsight/electron/preload.js release main.prod.js main.prod.js.map @@ -56,6 +57,9 @@ dll main.js main.js.map vendor +redisinsight/main.js.LICENSE.txt +redisinsight/main.prod.js.LICENSE.txt + # E2E tests report /tests/e2e/report diff --git a/configs/paths.js b/configs/paths.js deleted file mode 100644 index 2a08f20afa..0000000000 --- a/configs/paths.js +++ /dev/null @@ -1,17 +0,0 @@ -// paths.js - -// Paths will export some path variables that we'll -// use in other Webpack config and server files - -const path = require('path'); -const fs = require('fs'); - -const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath); - -module.exports = { - appAssets: resolveApp('ui/src/assets'), // For images and other assets - appBuild: resolveApp('ui/dist'), // Prod built files end up here - appConfig: resolveApp('ui/config'), // App config files - appSrc: resolveApp('ui/src'), // App source -}; diff --git a/configs/webpack.config.base.js b/configs/webpack.config.base.ts similarity index 71% rename from configs/webpack.config.base.js rename to configs/webpack.config.base.ts index a58581b672..a9f5779a29 100644 --- a/configs/webpack.config.base.js +++ b/configs/webpack.config.base.ts @@ -1,11 +1,13 @@ -import path from 'path'; import webpack from 'webpack'; -import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; +import TsconfigPathsPlugins from 'tsconfig-paths-webpack-plugin'; +import webpackPaths from './webpack.paths'; import { dependencies as externals } from '../redisinsight/package.json'; -export default { +const configuration: webpack.Configuration = { externals: [...Object.keys(externals || {})], + stats: 'errors-only', + module: { rules: [ { @@ -22,28 +24,27 @@ export default { }, output: { - path: path.join(__dirname, '..'), - // commonjs2 https://github.com/webpack/webpack/issues/1114 - libraryTarget: 'commonjs2', + path: webpackPaths.riPath, + // https://github.com/webpack/webpack/issues/1114 + library: { + type: 'commonjs2', + }, }, resolve: { extensions: ['.js', '.jsx', '.json', '.ts', '.tsx', '.scss'], - plugins: [ - new TsconfigPathsPlugin({ - configFile: path.join(__dirname, '..', 'tsconfig.json'), - }), - ], + modules: [webpackPaths.apiPath, 'node_modules'], + plugins: [new TsconfigPathsPlugins()], alias: { - src: path.resolve(__dirname, '../redisinsight/api/src'), - apiSrc: path.resolve(__dirname, '../redisinsight/api/src'), - uiSrc: path.resolve(__dirname, '../redisinsight/ui/src'), + src: webpackPaths.apiSrcPath, + apiSrc: webpackPaths.apiSrcPath, + uiSrc: webpackPaths.uiSrcPath, }, - modules: [path.join(__dirname, '../redisinsight/api'), 'node_modules'], }, plugins: [ new webpack.EnvironmentPlugin({ + NODE_ENV: 'production', }), new webpack.IgnorePlugin({ @@ -81,3 +82,5 @@ export default { }), ], }; + +export default configuration; diff --git a/configs/webpack.config.eslint.js b/configs/webpack.config.eslint.js index b1cf088a40..d7dac976b0 100644 --- a/configs/webpack.config.eslint.js +++ b/configs/webpack.config.eslint.js @@ -2,4 +2,4 @@ /* eslint import/no-unresolved: off, import/no-self-import: off */ require('@babel/register'); -module.exports = require('./webpack.config.renderer.dev.babel').default; +module.exports = require('./webpack.config.renderer.dev').default; diff --git a/configs/webpack.config.main.prod.babel.js b/configs/webpack.config.main.prod.ts similarity index 78% rename from configs/webpack.config.main.prod.babel.js rename to configs/webpack.config.main.prod.ts index 2a4857c0c7..bf7d0be134 100644 --- a/configs/webpack.config.main.prod.babel.js +++ b/configs/webpack.config.main.prod.ts @@ -1,11 +1,11 @@ import path from 'path'; import webpack from 'webpack'; import { merge } from 'webpack-merge'; -import { toString } from 'lodash' import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import baseConfig from './webpack.config.base'; import DeleteSourceMaps from '../scripts/DeleteSourceMaps'; import { version } from '../redisinsight/package.json'; +import webpackPaths from './webpack.paths'; DeleteSourceMaps(); @@ -23,19 +23,25 @@ export default merge(baseConfig, { target: 'electron-main', - entry: './redisinsight/main.dev.ts', + entry: { + main: path.join(webpackPaths.electronPath, 'main.dev.ts'), + preload: path.join(webpackPaths.electronPath, 'preload.ts'), + }, resolve: { alias: { - ['apiSrc']: path.resolve(__dirname, '../redisinsight/api/src'), - ['src']: path.resolve(__dirname, '../redisinsight/api/src'), + ['apiSrc']: webpackPaths.apiSrcPath, + ['src']: webpackPaths.apiSrcPath, }, extensions: ['.tsx', '.ts', '.js', '.jsx'], }, output: { - path: path.join(__dirname, '../redisinsight'), - filename: 'main.prod.js', + path: webpackPaths.distMainPath, + filename: '[name].js', + library: { + type: 'umd', + }, }, // optimization: { @@ -46,10 +52,6 @@ export default merge(baseConfig, { // ], // }, - // alias: { - // 'apiSrc': path.resolve(__dirname, '../redisinsight/api/src/') - // }, - plugins: [ new BundleAnalyzerPlugin({ analyzerMode: process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled', @@ -71,9 +73,10 @@ export default merge(baseConfig, { APP_VERSION: version, AWS_BUCKET_NAME: 'AWS_BUCKET_NAME' in process.env ? process.env.AWS_BUCKET_NAME : '', SEGMENT_WRITE_KEY: 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec + }), + + new webpack.DefinePlugin({ + 'process.type': '"browser"', }), ], diff --git a/configs/webpack.config.main.stage.babel.js b/configs/webpack.config.main.stage.ts similarity index 81% rename from configs/webpack.config.main.stage.babel.js rename to configs/webpack.config.main.stage.ts index 42956ea34a..88654a7cb3 100644 --- a/configs/webpack.config.main.stage.babel.js +++ b/configs/webpack.config.main.stage.ts @@ -1,8 +1,7 @@ import webpack from 'webpack'; import { merge } from 'webpack-merge'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import { toString } from 'lodash' -import mainProdConfig from './webpack.config.main.prod.babel'; +import mainProdConfig from './webpack.config.main.prod'; import DeleteSourceMaps from '../scripts/DeleteSourceMaps'; import { version } from '../redisinsight/package.json'; @@ -31,9 +30,6 @@ export default merge(mainProdConfig, { APP_VERSION: version, AWS_BUCKET_NAME: 'AWS_BUCKET_NAME' in process.env ? process.env.AWS_BUCKET_NAME : '', SEGMENT_WRITE_KEY: 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec }), ], }); diff --git a/configs/webpack.config.preload.dev.ts b/configs/webpack.config.preload.dev.ts new file mode 100644 index 0000000000..bccb43c805 --- /dev/null +++ b/configs/webpack.config.preload.dev.ts @@ -0,0 +1,64 @@ +import path from 'path'; +import webpack from 'webpack'; +import { merge } from 'webpack-merge'; +import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; +import baseConfig from './webpack.config.base'; +import webpackPaths from './webpack.paths'; + +const configuration: webpack.Configuration = { + devtool: 'inline-source-map', + + mode: 'development', + + target: 'electron-preload', + + entry: path.join(webpackPaths.electronPath, 'preload.ts'), + + output: { + path: webpackPaths.dllPath, + filename: 'preload.js', + library: { + type: 'umd', + }, + }, + + plugins: [ + new BundleAnalyzerPlugin({ + analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled', + }), + + /** + * Create global constants which can be configured at compile time. + * + * Useful for allowing different behaviour between development builds and + * release builds + * + * NODE_ENV should be production so that modules do not perform certain + * development checks + * + * By default, use 'development' as NODE_ENV. This can be overriden with + * 'staging', for example, by changing the ENV variables in the npm scripts + */ + new webpack.EnvironmentPlugin({ + NODE_ENV: 'development', + }), + + new webpack.LoaderOptionsPlugin({ + debug: true, + }), + ], + + /** + * Disables webpack processing of __dirname and __filename. + * If you run the bundle in node.js it falls back to these values of node.js. + * https://github.com/webpack/webpack/issues/2010 + */ + node: { + __dirname: false, + __filename: false, + }, + + watch: true, +}; + +export default merge(baseConfig, configuration); diff --git a/configs/webpack.config.renderer.dev.dll.babel.js b/configs/webpack.config.renderer.dev.dll.ts similarity index 55% rename from configs/webpack.config.renderer.dev.dll.babel.js rename to configs/webpack.config.renderer.dev.dll.ts index 2518a6f4e2..a0f419fc0a 100644 --- a/configs/webpack.config.renderer.dev.dll.babel.js +++ b/configs/webpack.config.renderer.dev.dll.ts @@ -1,17 +1,17 @@ import webpack from 'webpack'; import path from 'path'; import { merge } from 'webpack-merge'; -import { toString } from 'lodash' import baseConfig from './webpack.config.base'; +import webpackPaths from './webpack.paths'; import { dependencies } from '../package.json'; import { dependencies as dependenciesApi } from '../redisinsight/package.json'; console.log('dependenciesApi', dependenciesApi); -const dist = path.join(__dirname, '../dll'); +const dist = webpackPaths.dllPath; export default merge(baseConfig, { - context: path.join(__dirname, '..'), + context: webpackPaths.rootPath, devtool: 'eval', @@ -24,17 +24,19 @@ export default merge(baseConfig, { /** * Use `module` from `webpack.config.renderer.dev.js` */ - module: require('./webpack.config.renderer.dev.babel').default.module, + module: require('./webpack.config.renderer.dev').default.module, entry: { renderer: [...Object.keys(dependencies || {}), ...Object.keys(dependenciesApi || {})], }, output: { - library: 'renderer', path: dist, filename: '[name].dev.dll.js', - libraryTarget: 'var', + library: { + name: 'renderer', + type: 'var', + }, }, stats: 'errors-only', @@ -47,29 +49,16 @@ export default merge(baseConfig, { new webpack.EnvironmentPlugin({ NODE_ENV: 'development', - APP_ENV: 'electron', - API_PREFIX: 'api', - BASE_API_URL: 'http://localhost', - RESOURCES_BASE_URL: 'http://localhost', - SCAN_COUNT_DEFAULT: '500', - SCAN_TREE_COUNT_DEFAULT: '10000', - PIPELINE_COUNT_DEFAULT: '5', - SEGMENT_WRITE_KEY: - 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec }), new webpack.LoaderOptionsPlugin({ debug: true, options: { - context: path.join(__dirname, '..'), + context: webpackPaths.electronPath, output: { - path: path.join(__dirname, '../dll'), + path: webpackPaths.dllPath, }, }, }), - ], }); diff --git a/configs/webpack.config.renderer.dev.babel.js b/configs/webpack.config.renderer.dev.ts similarity index 55% rename from configs/webpack.config.renderer.dev.babel.js rename to configs/webpack.config.renderer.dev.ts index 19726262dd..95321071f9 100644 --- a/configs/webpack.config.renderer.dev.babel.js +++ b/configs/webpack.config.renderer.dev.ts @@ -1,45 +1,69 @@ +import 'webpack-dev-server'; import path from 'path'; +import { execSync, spawn } from 'child_process'; +import fs from 'fs'; +import chalk from 'chalk'; import webpack from 'webpack'; import { merge } from 'webpack-merge'; -import { spawn } from 'child_process'; -import { toString } from 'lodash' import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; import baseConfig from './webpack.config.base'; +import webpackPaths from './webpack.paths'; import { version } from '../redisinsight/package.json'; const port = process.env.PORT || 1212; -const publicPath = `http://localhost:${port}/dist`; -const dllDir = path.join(__dirname, '../dll'); -const manifest = path.resolve(dllDir, 'renderer.json'); -const requiredByDLLConfig = module.parent.filename.includes('webpack.config.renderer.dev.dll'); +const manifest = path.resolve(webpackPaths.dllPath, 'renderer.json'); +const skipDLLs = + module.parent?.filename.includes('webpack.config.renderer.dev.dll') || + module.parent?.filename.includes('webpack.config.eslint'); + +/** + * Warn if the DLL is not built + */ +if ( + !skipDLLs && + !(fs.existsSync(webpackPaths.dllPath) && fs.existsSync(manifest)) +) { + console.log( + chalk.black.bgYellow.bold( + 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"' + ) + ); + execSync('npm run postinstall'); +} function employCache(loaders) { return ['cache-loader'].concat(loaders); } -export default merge(baseConfig, { - devtool: 'inline-source-map', +const configuration: webpack.Configuration = { + devtool: 'source-map', mode: 'development', - target: 'electron-renderer', + target: ['web', 'electron-renderer'], entry: [ - 'core-js', - 'regenerator-runtime/runtime', - // require.resolve('../redisinsight/main.renderer.ts'), - require.resolve('../redisinsight/ui/indexElectron.tsx'), + `webpack-dev-server/client?http://localhost:${port}/dist`, + 'webpack/hot/only-dev-server', + path.join(webpackPaths.uiPath, 'indexElectron.tsx'), ], output: { - publicPath: `http://localhost:${port}/dist/`, + path: webpackPaths.electronPath, + publicPath: '/', filename: 'renderer.dev.js', + library: { + type: 'umd', + }, }, resolve: { alias: { - apiSrc: path.resolve(__dirname, '../redisinsight/api/src'), + src: webpackPaths.apiSrcPath, + apiSrc: webpackPaths.apiSrcPath, + uiSrc: webpackPaths.uiSrcPath, }, }, @@ -193,32 +217,20 @@ export default merge(baseConfig, { ], }, plugins: [ - requiredByDLLConfig - ? null - : new webpack.DllReferencePlugin({ - context: path.join(__dirname, '../dll'), - manifest: require(manifest), - sourceType: 'var', - }), + ...(skipDLLs + ? [] + : [ + new webpack.DllReferencePlugin({ + context: webpackPaths.dllPath, + manifest: require(manifest), + sourceType: 'var', + }), + ]), new webpack.NoEmitOnErrorsPlugin(), new webpack.EnvironmentPlugin({ NODE_ENV: 'development', - APP_ENV: 'electron', - API_PREFIX: 'api', - BASE_API_URL: 'http://localhost', - RESOURCES_BASE_URL: 'http://localhost', - SCAN_COUNT_DEFAULT: '500', - SCAN_TREE_COUNT_DEFAULT: '10000', - PIPELINE_COUNT_DEFAULT: '5', - BUILD_TYPE: 'ELECTRON', - APP_VERSION: version, - SEGMENT_WRITE_KEY: - 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec }), new webpack.LoaderOptionsPlugin({ @@ -228,6 +240,39 @@ export default merge(baseConfig, { new ReactRefreshWebpackPlugin(), new MonacoWebpackPlugin({ languages: ['json'], features: ['!rename'] }), + + new HtmlWebpackPlugin({ + filename: path.join('index.html'), + template: path.join(webpackPaths.electronPath, 'index.ejs'), + minify: { + collapseWhitespace: true, + removeAttributeQuotes: true, + removeComments: true, + }, + isBrowser: false, + env: process.env.NODE_ENV, + isDevelopment: process.env.NODE_ENV !== 'production', + nodeModules: webpackPaths.appNodeModulesPath, + }), + + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify('development'), + 'process.env.APP_ENV': JSON.stringify('web'), + 'process.env.API_PREFIX': JSON.stringify('api'), + 'process.env.BASE_API_URL': JSON.stringify('http://localhost'), + 'process.env.RESOURCES_BASE_URL': JSON.stringify('http://localhost'), + 'process.env.SCAN_COUNT_DEFAULT': JSON.stringify('500'), + 'process.env.SCAN_TREE_COUNT_DEFAULT': JSON.stringify('10000'), + 'process.env.PIPELINE_COUNT_DEFAULT': JSON.stringify('5'), + 'process.env.BUILD_TYPE': JSON.stringify('ELECTRON'), + 'process.env.APP_VERSION': JSON.stringify(version), + 'process.env.CONNECTIONS_TIMEOUT_DEFAULT': 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env + ? JSON.stringify(process.env.CONNECTIONS_TIMEOUT_DEFAULT) + : JSON.stringify(30 * 1000), + 'process.env.SEGMENT_WRITE_KEY': 'SEGMENT_WRITE_KEY' in process.env + ? JSON.stringify(process.env.SEGMENT_WRITE_KEY) + : JSON.stringify('SOURCE_WRITE_KEY'), + }), ], node: { @@ -237,33 +282,44 @@ export default merge(baseConfig, { devServer: { port, - publicPath, compress: true, - noInfo: false, - stats: 'errors-only', - inline: true, - lazy: false, hot: true, headers: { 'Access-Control-Allow-Origin': '*' }, - contentBase: path.join(__dirname, 'dist'), - watchOptions: { - aggregateTimeout: 300, - ignored: /node_modules/, - poll: 100, + static: { + publicPath: '/', }, historyApiFallback: { verbose: true, - disableDotRule: false, + disableDotRule: true, }, - before() { - console.log('Starting Main Process...'); - spawn('npm', ['run', 'start:main'], { + setupMiddlewares(middlewares) { + console.log('Starting preload.js builder...'); + const preloadProcess = spawn('npm', ['run', 'start:preload'], { shell: true, - env: process.env, stdio: 'inherit', }) .on('close', (code) => process.exit(code)) .on('error', (spawnError) => console.error(spawnError)); + + console.log('Starting Main Process...'); + let args = ['run', 'start:main']; + if (process.env.MAIN_ARGS) { + args = args.concat( + ['--', ...process.env.MAIN_ARGS.matchAll(/"[^"]+"|[^\s"]+/g)].flat() + ); + } + spawn('npm', args, { + shell: true, + stdio: 'inherit', + }) + .on('close', (code) => { + preloadProcess.kill(); + process.exit(code); + }) + .on('error', (spawnError) => console.error(spawnError)); + return middlewares; }, }, -}); +}; + +export default merge(baseConfig, configuration); diff --git a/configs/webpack.config.renderer.prod.babel.js b/configs/webpack.config.renderer.prod.ts similarity index 68% rename from configs/webpack.config.renderer.prod.babel.js rename to configs/webpack.config.renderer.prod.ts index f0c894b9c1..8cd97fc7d3 100644 --- a/configs/webpack.config.renderer.prod.babel.js +++ b/configs/webpack.config.renderer.prod.ts @@ -1,14 +1,13 @@ import path from 'path'; import webpack from 'webpack'; -import { toString } from 'lodash' import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin'; import { merge } from 'webpack-merge'; -import TerserPlugin from 'terser-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; import baseConfig from './webpack.config.base'; import DeleteSourceMaps from '../scripts/DeleteSourceMaps'; +import webpackPaths from './webpack.paths'; +import { version } from '../redisinsight/package.json'; DeleteSourceMaps(); @@ -19,24 +18,24 @@ const devtoolsConfig = } : {}; -export default merge(baseConfig, { +const configuration: webpack.Configuration = { ...devtoolsConfig, + devtool: 'source-map', + mode: 'production', - target: 'electron-renderer', + target: ['web', 'electron-renderer'], - entry: [ - 'core-js', - 'regenerator-runtime/runtime', - // path.join(__dirname, '../redisinsight/main.renderer.ts'), - path.join(__dirname, '../redisinsight/ui/indexElectron.tsx'), - ], + entry: [path.join(webpackPaths.uiPath, 'indexElectron.tsx')], output: { - path: path.join(__dirname, '../redisinsight/dist'), - publicPath: './dist/', - filename: 'renderer.prod.js', + path: webpackPaths.distRendererPath, + publicPath: './', + filename: 'renderer.js', + library: { + type: 'umd', + }, }, module: { @@ -177,43 +176,44 @@ export default merge(baseConfig, { ], }, - optimization: { - minimize: true, - minimizer: [ - new TerserPlugin({ - parallel: true, - }), - new CssMinimizerPlugin(), - ], - }, - plugins: [ new MonacoWebpackPlugin({ languages: ['json'], features: ['!rename'] }), new webpack.EnvironmentPlugin({ NODE_ENV: 'production', - DEBUG_PROD: false, - API_PREFIX: 'api', - BASE_API_URL: process.env.SERVER_TLS_CERT && process.env.SERVER_TLS_KEY ? 'https://localhost' : 'http://localhost', - RESOURCES_BASE_URL: process.env.SERVER_TLS_CERT && process.env.SERVER_TLS_KEY ? 'https://localhost' : 'http://localhost', - APP_ENV: 'electron', - SCAN_COUNT_DEFAULT: '500', - SCAN_TREE_COUNT_DEFAULT: '10000', - PIPELINE_COUNT_DEFAULT: '5', - SEGMENT_WRITE_KEY: - 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec }), new MiniCssExtractPlugin({ filename: 'style.css', }), - new BundleAnalyzerPlugin({ - analyzerMode: process.env.OPEN_ANALYZER === 'true' ? 'server' : 'disabled', - openAnalyzer: process.env.OPEN_ANALYZER === 'true', + new HtmlWebpackPlugin({ + filename: 'index.html', + template: path.join(webpackPaths.electronPath, 'index.ejs'), + isBrowser: false, + isDevelopment: false, + }), + + new webpack.DefinePlugin({ + 'process.type': '"renderer"', + 'process.env.NODE_ENV': JSON.stringify('development'), + 'process.env.APP_ENV': JSON.stringify('electron'), + 'process.env.API_PREFIX': JSON.stringify('api'), + 'process.env.BASE_API_URL': JSON.stringify('http://localhost'), + 'process.env.RESOURCES_BASE_URL': JSON.stringify('http://localhost'), + 'process.env.SCAN_COUNT_DEFAULT': JSON.stringify('500'), + 'process.env.SCAN_TREE_COUNT_DEFAULT': JSON.stringify('10000'), + 'process.env.PIPELINE_COUNT_DEFAULT': JSON.stringify('5'), + 'process.env.BUILD_TYPE': JSON.stringify('ELECTRON'), + 'process.env.APP_VERSION': JSON.stringify(version), + 'process.env.CONNECTIONS_TIMEOUT_DEFAULT': 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env + ? JSON.stringify(process.env.CONNECTIONS_TIMEOUT_DEFAULT) + : JSON.stringify(30 * 1000), + 'process.env.SEGMENT_WRITE_KEY': 'SEGMENT_WRITE_KEY' in process.env + ? JSON.stringify(process.env.SEGMENT_WRITE_KEY) + : JSON.stringify('SOURCE_WRITE_KEY'), }), ], -}); +}; + +export default merge(baseConfig, configuration); diff --git a/configs/webpack.config.renderer.stage.babel.js b/configs/webpack.config.renderer.stage.babel.js deleted file mode 100644 index b549b4e980..0000000000 --- a/configs/webpack.config.renderer.stage.babel.js +++ /dev/null @@ -1,32 +0,0 @@ -import webpack from 'webpack'; -import { merge } from 'webpack-merge'; -import { toString } from 'lodash' -import baseConfig from './webpack.config.base'; -import rendererProdConfig from './webpack.config.renderer.prod.babel'; -import DeleteSourceMaps from '../scripts/DeleteSourceMaps'; - -DeleteSourceMaps(); - -export default merge(baseConfig, { - ...rendererProdConfig, - - plugins: [ - ...rendererProdConfig.plugins, - - new webpack.EnvironmentPlugin({ - NODE_ENV: 'staging', - DEBUG_PROD: false, - API_PREFIX: 'api', - BASE_API_URL: process.env.SERVER_TLS_CERT && process.env.SERVER_TLS_KEY ? 'https://localhost' : 'http://localhost', - RESOURCES_BASE_URL: process.env.SERVER_TLS_CERT && process.env.SERVER_TLS_KEY ? 'https://localhost' : 'http://localhost', - APP_ENV: 'electron', - SCAN_COUNT_DEFAULT: '500', - SCAN_COUNT_MEMORY_ANALYSES: '10000', - SEGMENT_WRITE_KEY: - 'SEGMENT_WRITE_KEY' in process.env ? process.env.SEGMENT_WRITE_KEY : 'SOURCE_WRITE_KEY', - CONNECTIONS_TIMEOUT_DEFAULT: 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env - ? process.env.CONNECTIONS_TIMEOUT_DEFAULT - : toString(30 * 1000), // 30 sec - }), - ], -}); diff --git a/configs/webpack.config.renderer.stage.ts b/configs/webpack.config.renderer.stage.ts new file mode 100644 index 0000000000..30530fc877 --- /dev/null +++ b/configs/webpack.config.renderer.stage.ts @@ -0,0 +1,36 @@ +import webpack from 'webpack'; +import { merge } from 'webpack-merge'; +import baseConfig from './webpack.config.base'; +import rendererProdConfig from './webpack.config.renderer.prod'; +import DeleteSourceMaps from '../scripts/DeleteSourceMaps'; +import { version } from '../redisinsight/package.json'; + +DeleteSourceMaps(); + +export default merge(baseConfig, { + ...rendererProdConfig, + + plugins: [ + ...rendererProdConfig.plugins, + + new webpack.DefinePlugin({ + 'process.type': '"renderer"', + 'process.env.NODE_ENV': JSON.stringify('staging'), + 'process.env.APP_ENV': JSON.stringify('electron'), + 'process.env.API_PREFIX': JSON.stringify('api'), + 'process.env.BASE_API_URL': JSON.stringify('http://localhost'), + 'process.env.RESOURCES_BASE_URL': JSON.stringify('http://localhost'), + 'process.env.SCAN_COUNT_DEFAULT': JSON.stringify('500'), + 'process.env.SCAN_TREE_COUNT_DEFAULT': JSON.stringify('10000'), + 'process.env.PIPELINE_COUNT_DEFAULT': JSON.stringify('5'), + 'process.env.BUILD_TYPE': JSON.stringify('ELECTRON'), + 'process.env.APP_VERSION': JSON.stringify(version), + 'process.env.CONNECTIONS_TIMEOUT_DEFAULT': 'CONNECTIONS_TIMEOUT_DEFAULT' in process.env + ? JSON.stringify(process.env.CONNECTIONS_TIMEOUT_DEFAULT) + : JSON.stringify(30 * 1000), + 'process.env.SEGMENT_WRITE_KEY': 'SEGMENT_WRITE_KEY' in process.env + ? JSON.stringify(process.env.SEGMENT_WRITE_KEY) + : JSON.stringify('SOURCE_WRITE_KEY'), + }), + ], +}); diff --git a/configs/webpack.config.web.common.babel.js b/configs/webpack.config.web.common.ts similarity index 91% rename from configs/webpack.config.web.common.babel.js rename to configs/webpack.config.web.common.ts index 973b9ea30c..295dc0b26e 100644 --- a/configs/webpack.config.web.common.babel.js +++ b/configs/webpack.config.web.common.ts @@ -22,12 +22,8 @@ export default { include: [path.resolve(__dirname, '../redisinsight/ui')], exclude: [ /node_modules/, - path.resolve(__dirname, '../menu.ts'), - path.resolve(__dirname, 'menu.ts'), - path.resolve(__dirname, '../Menu.ts'), - path.resolve(__dirname, 'Menu.ts'), - path.resolve(__dirname, '../redisinsight/main.dev.ts'), path.resolve(__dirname, '../redisinsight/api'), + path.resolve(__dirname, '../redisinsight/electron'), ], use: { loader: 'babel-loader', @@ -69,6 +65,10 @@ export default { }, plugins: [ + new webpack.DefinePlugin({ + 'window.ENV_VARS.API_PORT': JSON.stringify('5000'), + }), + new HtmlWebpackPlugin({ template: 'index.html.ejs' }), new MonacoWebpackPlugin({ languages: ['json'], features: ['!rename'] }), diff --git a/configs/webpack.config.web.dev.babel.js b/configs/webpack.config.web.dev.ts similarity index 96% rename from configs/webpack.config.web.dev.babel.js rename to configs/webpack.config.web.dev.ts index 556918c9f8..952a08321b 100644 --- a/configs/webpack.config.web.dev.babel.js +++ b/configs/webpack.config.web.dev.ts @@ -10,7 +10,7 @@ import webpack from 'webpack'; import { merge } from 'webpack-merge'; import ip from 'ip'; import { toString } from 'lodash' -import commonConfig from './webpack.config.web.common.babel'; +import commonConfig from './webpack.config.web.common'; function employCache(loaders) { return ['cache-loader'].concat(loaders); @@ -18,7 +18,7 @@ function employCache(loaders) { const HOST = process.env.PUBLIC_DEV ? ip.address(): 'localhost' -export default merge(commonConfig, { +const configuration: webpack.Configuration = { target: 'web', mode: 'development', @@ -176,9 +176,9 @@ export default merge(commonConfig, { host: HOST, allowedHosts: 'all', port: 8080, - hot: true, // enable HMR on the server historyApiFallback: true, }, + plugins: [ new webpack.HotModuleReplacementPlugin({ multiStep: true, @@ -202,7 +202,6 @@ export default merge(commonConfig, { NODE_ENV: 'development', APP_ENV: 'web', API_PREFIX: 'api', - API_PORT: '5000', BASE_API_URL: `http://${HOST}`, RESOURCES_BASE_URL: `http://${HOST}`, PIPELINE_COUNT_DEFAULT: '5', @@ -223,6 +222,8 @@ export default merge(commonConfig, { ], externals: { - react: 'React', + // react: 'React', }, -}); +}; + +export default merge(commonConfig, configuration); diff --git a/configs/webpack.config.web.prod.babel.js b/configs/webpack.config.web.prod.ts similarity index 97% rename from configs/webpack.config.web.prod.babel.js rename to configs/webpack.config.web.prod.ts index b3d6101aa5..517e0518bb 100644 --- a/configs/webpack.config.web.prod.babel.js +++ b/configs/webpack.config.web.prod.ts @@ -6,7 +6,7 @@ import TerserPlugin from 'terser-webpack-plugin'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -import commonConfig from './webpack.config.web.common.babel'; +import commonConfig from './webpack.config.web.common'; import DeleteDistWeb from '../scripts/DeleteDistWeb'; DeleteDistWeb(); @@ -18,7 +18,7 @@ const devtoolsConfig = } : {}; -export default merge(commonConfig, { +const configuration: webpack.Configuration = { ...devtoolsConfig, mode: 'production', @@ -208,4 +208,6 @@ export default merge(commonConfig, { ], }, externals: {}, -}); +}; + +export default merge(commonConfig, configuration); diff --git a/configs/webpack.paths.ts b/configs/webpack.paths.ts new file mode 100644 index 0000000000..e4ccb48681 --- /dev/null +++ b/configs/webpack.paths.ts @@ -0,0 +1,46 @@ +const path = require('path'); + +const rootPath = path.join(__dirname, '..'); + +const riPath = path.join(rootPath, 'redisinsight'); + +const apiPath = path.join(riPath, 'api'); +const uiPath = path.join(riPath, 'ui'); +const apiSrcPath = path.join(apiPath, 'src'); +const uiSrcPath = path.join(uiPath, 'src'); +const electronPath = path.join(riPath, 'electron'); +const srcMainPath = path.join(electronPath, 'main'); + +const dllPath = path.join(electronPath, 'dll'); + +const releasePath = path.join(rootPath, 'release'); +const appPackagePath = path.join(riPath, 'package.json'); +const appNodeModulesPath = path.join(releasePath, 'node_modules'); +const buildAppPackagePath = path.join(releasePath, 'package.json'); +const srcNodeModulesPath = path.join(apiPath, 'node_modules'); + +const distPath = path.join(riPath, 'dist'); +const distMainPath = path.join(distPath, 'main'); +const distRendererPath = path.join(distPath, 'renderer'); + + +export default { + rootPath, + dllPath, + apiPath, + uiPath, + riPath, + apiSrcPath, + uiSrcPath, + srcMainPath, + releasePath, + electronPath, + appPackagePath, + appNodeModulesPath, + srcNodeModulesPath, + distPath, + distMainPath, + distRendererPath, + buildAppPackagePath, + buildPath: releasePath, +}; diff --git a/electron-builder.json b/electron-builder.json index b451d01b6e..5b1b54547a 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -3,12 +3,8 @@ "appId": "org.RedisLabs.RedisInsight-V2", "copyright": "Copyright © 2023 Redis Ltd.", "files": [ - "dist/", - "node_modules/", - "index.html", - "splash.html", - "main.prod.js", - "main.prod.js.map", + "dist", + "node_modules", "package.json" ], "afterSign": "electron-builder-notarize", diff --git a/package.json b/package.json index f2a458f433..97c684bd2e 100644 --- a/package.json +++ b/package.json @@ -6,26 +6,26 @@ "private": true, "scripts": { "build": "cross-env NODE_ENV=development concurrently \"yarn build:main\" \"yarn build:renderer\"", - "build:stage": "cross-env NODE_ENV=staging concurrently \"yarn build:api:stage && yarn build:main:stage\" \"yarn build:renderer:stage\"", + "build:stage": "cross-env NODE_ENV=staging TS_NODE_TRANSPILE_ONLY=true concurrently \"yarn build:api:stage && yarn build:main:stage\" \"yarn build:renderer:stage\"", "build:prod": "cross-env NODE_ENV=production concurrently \"yarn build:api && yarn build:main\" \"yarn build:renderer\"", "build:api": "yarn --cwd redisinsight/api/ build:prod", "build:api:stage": "yarn --cwd redisinsight/api/ build:stage", - "build:main": "webpack --config ./configs/webpack.config.main.prod.babel.js", - "build:main:stage": "webpack --config ./configs/webpack.config.main.stage.babel.js", - "build:web": "webpack --config ./configs/webpack.config.web.prod.babel.js", + "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.main.prod.ts", + "build:main:stage": "cross-env TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.main.stage.ts", + "build:web": "cross-env TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.web.prod.ts", "build:defaults": "yarn --cwd redisinsight/api build:defaults", "build:statics": "yarn build:defaults && sh ./scripts/build-statics.sh", "build:statics:win": "yarn build:defaults && ./scripts/build-statics.cmd", - "build:renderer": "webpack --config ./configs/webpack.config.renderer.prod.babel.js", - "build:renderer:stage": "webpack --config ./configs/webpack.config.renderer.stage.babel.js", - "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir redisinsight/ui", + "build:renderer": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.renderer.prod.ts", + "build:renderer:stage": "cross-env NODE_ENV=staging TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.renderer.stage.ts", + "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir redisinsight", "lint": "eslint . --ext .js,.jsx,.ts,.tsx", "lint:ui": "eslint ./redisinsight/ui --ext .js,.jsx,.ts,.tsx", "lint:api": "yarn --cwd redisinsight/api lint", "lint:e2e": "yarn --cwd tests/e2e lint", "package": "yarn package:dev", - "package:prod": "yarn build:prod && electron-builder build -p never", - "package:stage": "yarn build:stage && electron-builder build -p never", + "package:prod": "ts-node ./scripts/prebuild.js dist && yarn build:prod && electron-builder build -p never", + "package:stage": "ts-node ./scripts/prebuild.js dist && yarn build:stage && electron-builder build -p never", "package:mas": "electron-builder build -p never -m mas:universal -c ./electron-builder-mas.js", "package:mas:dev": "electron-builder build -p never -m mas-dev:universal -c ./electron-builder-mas.js", "package:dev": "yarn build && cross-env DEBUG=electron-builder electron-builder build -p never", @@ -33,11 +33,13 @@ "package:mac": "yarn build:prod && electron-builder build --mac -p never", "package:mac:arm": "yarn build:prod && electron-builder build --mac --arm64 -p never", "package:linux": "yarn build:prod && electron-builder build --linux -p never", - "postinstall": "skip-postinstall || (electron-builder install-app-deps && yarn webpack --config ./configs/webpack.config.renderer.dev.dll.babel.js && opencollective-postinstall && yarn-deduplicate yarn.lock)", - "start": "cross-env NODE_ENV=development webpack serve --config ./configs/webpack.config.renderer.dev.babel.js", - "start:main": "cross-env NODE_ENV=development electron -r ./scripts/BabelRegister redisinsight/main.dev.ts", - "start:web": "webpack serve --config ./configs/webpack.config.web.dev.babel.js", - "start:web:public": "cross-env PUBLIC_DEV=true webpack serve --config ./configs/webpack.config.web.dev.babel.js", + "postinstall": "skip-postinstall || (electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.renderer.dev.dll.ts && opencollective-postinstall && yarn-deduplicate yarn.lock)", + "start": "ts-node ./scripts/check-port-in-use.js && yarn start:renderer", + "start:renderer": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./configs/webpack.config.renderer.dev.ts", + "start:preload": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./configs/webpack.config.preload.dev.ts", + "start:main": "cross-env NODE_ENV=development electron -r ./scripts/BabelRegister redisinsight/electron/main.dev.ts", + "start:web": "cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./configs/webpack.config.web.dev.ts", + "start:web:public": "cross-env PUBLIC_DEV=true NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack serve --config ./configs/webpack.config.web.dev.ts", "test": "jest ./redisinsight/ui -w 1", "test:watch": "jest ./redisinsight/ui --watch -w 1", "test:cov": "jest ./redisinsight/ui --coverage -w 1", @@ -137,6 +139,7 @@ "@types/segment-analytics": "^0.0.34", "@types/supertest": "^2.0.8", "@types/uuid": "^8.3.4", + "@types/webpack-bundle-analyzer": "^4.6.0", "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "^4.8.1", "@typescript-eslint/parser": "^4.8.1", @@ -171,7 +174,7 @@ "eslint-plugin-react-hooks": "^4.0.8", "eslint-plugin-sonarjs": "^0.10.0", "file-loader": "^6.0.0", - "html-webpack-plugin": "^4.5.0", + "html-webpack-plugin": "^5.5.0", "husky": "^4.2.5", "identity-obj-proxy": "^3.0.0", "ioredis-mock": "^5.5.4", @@ -180,7 +183,7 @@ "jest-runner-groups": "^2.2.0", "jest-when": "^3.2.1", "lint-staged": "^10.2.11", - "mini-css-extract-plugin": "^1.3.1", + "mini-css-extract-plugin": "2.7.2", "moment": "^2.29.3", "monaco-editor-webpack-plugin": "^6.0.0", "msw": "^0.45.0", @@ -201,13 +204,13 @@ "ts-jest": "27.1.5", "ts-loader": "^6.2.1", "ts-mockito": "^2.6.1", - "ts-node": "^8.6.2", + "ts-node": "^10.9.1", "tsconfig-paths": "^3.9.0", - "tsconfig-paths-webpack-plugin": "^3.3.0", + "tsconfig-paths-webpack-plugin": "^4.0.1", "typescript": "^4.0.5", "url-loader": "^4.1.0", "webpack": "^5.5.1", - "webpack-bundle-analyzer": "^4.1.0", + "webpack-bundle-analyzer": "^4.8.0", "webpack-cli": "^4.3.0", "webpack-dev-server": "^4.13.3", "webpack-merge": "^5.4.0", diff --git a/redisinsight/about-panel.ts b/redisinsight/electron/about-panel.ts similarity index 100% rename from redisinsight/about-panel.ts rename to redisinsight/electron/about-panel.ts diff --git a/redisinsight/electron/index.ejs b/redisinsight/electron/index.ejs new file mode 100644 index 0000000000..bb61a1b52d --- /dev/null +++ b/redisinsight/electron/index.ejs @@ -0,0 +1,10 @@ + + +
+ +