diff --git a/scripts/devRunner.js b/scripts/devRunner.js index 89da976b..98f3fd3b 100644 --- a/scripts/devRunner.js +++ b/scripts/devRunner.js @@ -63,43 +63,39 @@ async function restartElectron () { if (!manualRestart) process.exit(0); }); } +function startWorkers () { + const compiler = webpack(workersConfig); + const { name } = compiler; -function startMain () { - const webpackSetup = webpack([mainConfig, workersConfig]); - - webpackSetup.compilers.forEach((compiler) => { - const { name } = compiler; - - switch (name) { - case 'workers': - compiler.hooks.afterEmit.tap('afterEmit', async () => { - console.log(chalk.gray(`\nCompiled ${name} script!`)); - console.log( - chalk.gray(`\nWatching file changes for ${name} script...`) - ); - }); - break; - case 'main': - default: - compiler.hooks.afterEmit.tap('afterEmit', async () => { - console.log(chalk.gray(`\nCompiled ${name} script!`)); - - manualRestart = true; - await restartElectron(); - - setTimeout(() => { - manualRestart = false; - }, 2500); - - console.log( - chalk.gray(`\nWatching file changes for ${name} script...`) - ); - }); - break; - } + compiler.hooks.afterEmit.tap('afterEmit', () => { + console.log(chalk.gray(`\nCompiled ${name} script!`)); + console.log(chalk.gray(`\nWatching file changes for ${name} script...`)); }); - webpackSetup.watch({ aggregateTimeout: 500 }, err => { + compiler.watch({ aggregateTimeout: 500 }, err => { + if (err) console.error(chalk.red(err)); + }); +} + +function startMain () { + const compiler = webpack(mainConfig); + const { name } = compiler; + + compiler.hooks.afterEmit.tap('afterEmit', async () => { + console.log(chalk.gray(`\nCompiled ${name} script!`)); + + manualRestart = true; + await restartElectron(); + startWorkers(); + + setTimeout(() => { + manualRestart = false; + }, 2500); + + console.log(chalk.gray(`\nWatching file changes for ${name} script...`)); + }); + + compiler.watch({ aggregateTimeout: 500 }, err => { if (err) console.error(chalk.red(err)); }); } diff --git a/src/main/ipc-handlers/schema.ts b/src/main/ipc-handlers/schema.ts index e4ac55aa..826635bd 100644 --- a/src/main/ipc-handlers/schema.ts +++ b/src/main/ipc-handlers/schema.ts @@ -1,17 +1,14 @@ -import { ChildProcess, fork, spawn } from 'child_process'; import * as antares from 'common/interfaces/antares'; import * as workers from 'common/interfaces/workers'; import { dialog, ipcMain } from 'electron'; import * as fs from 'fs'; +import { Worker } from 'worker_threads'; import { validateSender } from '../libs/misc/validateSender'; -const isDevelopment = process.env.NODE_ENV !== 'production'; -const isFlatpak = process.platform === 'linux' && process.env.DISTRIBUTION === 'flatpak'; - export default (connections: {[key: string]: antares.Client}) => { - let exporter: ChildProcess = null; - let importer: ChildProcess = null; + let exporter: Worker = null; + let importer: Worker = null; ipcMain.handle('create-schema', async (event, params) => { if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; @@ -202,7 +199,7 @@ export default (connections: {[key: string]: antares.Client}) => { if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (exporter !== null) { - exporter.kill(); + exporter.terminate(); return; } @@ -227,21 +224,12 @@ export default (connections: {[key: string]: antares.Client}) => { } } - // Init exporter process - if (isFlatpak) { - exporter = spawn('flatpak-spawn', ['--watch-bus', '--host', 'node', './exporter.js'], { - shell: true - }); - } - else { - exporter = fork(isDevelopment ? './dist/exporter.js' : './exporter.js', [], { - execArgv: isDevelopment ? ['--inspect=9224'] : undefined, - silent: true - }); - // exporter = spawn('node', [isDevelopment ? '--inspect=9224' : '', isDevelopment ? './dist/exporter.js' : './exporter.js']); - } + // Init exporter thread + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + exporter = new Worker(new URL('../workers/exporter', import.meta.url)); - exporter.stdin.write(JSON.stringify({ + exporter.postMessage({ type: 'init', client: { name: type, @@ -269,21 +257,19 @@ export default (connections: {[key: string]: antares.Client}) => { event.sender.send('export-progress', payload); break; case 'end': - setTimeout(() => { // Ensures that writing process has finished - if (exporter) { - exporter.kill(); - exporter = null; - } + setTimeout(() => { // Ensures that writing thread has finished + exporter?.terminate(); + exporter = null; }, 2000); resolve({ status: 'success', response: payload }); break; case 'cancel': - exporter.kill(); + exporter?.terminate(); exporter = null; resolve({ status: 'error', response: 'Operation cancelled' }); break; case 'error': - exporter.kill(); + exporter?.terminate(); exporter = null; resolve({ status: 'error', response: payload }); break; @@ -314,7 +300,7 @@ export default (connections: {[key: string]: antares.Client}) => { if (result.response === 1) { willAbort = true; - exporter.stdin.write(JSON.stringify({ type: 'cancel' })); + exporter.postMessage({ type: 'cancel' }); } } @@ -325,7 +311,7 @@ export default (connections: {[key: string]: antares.Client}) => { if (!validateSender(event.senderFrame)) return { status: 'error', response: 'Unauthorized process' }; if (importer !== null) { - importer.kill(); + importer.terminate(); return; } @@ -333,20 +319,12 @@ export default (connections: {[key: string]: antares.Client}) => { (async () => { const dbConfig = await connections[options.uid].getDbConfig(); - // Init importer process - if (isFlatpak) { - importer = spawn('flatpak-spawn', ['--watch-bus', 'node', './importer.js'], { - cwd: __dirname - }); - } - else { - importer = fork(isDevelopment ? './dist/importer.js' : './importer.js', [], { - execArgv: isDevelopment ? ['--inspect=9224'] : undefined, - silent: true - }); - } + // Init importer thread + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + importer = new Worker(new URL('../workers/importer', import.meta.url)); - importer.stdin.write(JSON.stringify({ + importer.postMessage({ type: 'init', dbConfig, options @@ -374,18 +352,18 @@ export default (connections: {[key: string]: antares.Client}) => { break; case 'end': setTimeout(() => { // Ensures that writing process has finished - importer?.kill(); + importer?.terminate(); importer = null; }, 2000); resolve({ status: 'success', response: payload }); break; case 'cancel': - importer.kill(); + importer.terminate(); importer = null; resolve({ status: 'error', response: 'Operation cancelled' }); break; case 'error': - importer.kill(); + importer.terminate(); importer = null; resolve({ status: 'error', response: payload }); break; @@ -416,7 +394,7 @@ export default (connections: {[key: string]: antares.Client}) => { if (result.response === 1) { willAbort = true; - importer.stdin.write(JSON.stringify({ type: 'cancel' })); + importer.postMessage({ type: 'cancel' }); } } diff --git a/src/main/workers/exporter.ts b/src/main/workers/exporter.ts index 64ba8ae3..599b480b 100644 --- a/src/main/workers/exporter.ts +++ b/src/main/workers/exporter.ts @@ -1,7 +1,7 @@ import * as antares from 'common/interfaces/antares'; import * as log from 'electron-log/main'; import * as fs from 'fs'; -import { nextTick } from 'process'; +import { parentPort } from 'worker_threads'; import { MySQLClient } from '../libs/clients/MySQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; @@ -14,8 +14,9 @@ log.transports.file.fileName = 'workers.log'; log.transports.console = null; log.errorHandler.startCatching(); -process.stdin.on('data', async buff => { - const { type, client, tables, options } = JSON.parse(buff.toString()); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const exportHandler = async (data: any) => { + const { type, client, tables, options } = data; if (type === 'init') { try { @@ -35,7 +36,7 @@ process.stdin.on('data', async buff => { exporter = new PostgreSQLExporter(connection as PostgreSQLClient, tables, options); break; default: - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: `"${client.name}" exporter not aviable` })); @@ -44,31 +45,26 @@ process.stdin.on('data', async buff => { exporter.once('error', err => { log.error(err.toString()); - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: err.toString() })); }); exporter.once('end', () => { - nextTick(() => { - process.stdout.write(JSON.stringify({ - type: 'end', - payload: { cancelled: exporter.isCancelled } - })); - connection.destroy(); + parentPort.postMessage({ + type: 'end', + payload: { cancelled: exporter.isCancelled } }); }); exporter.once('cancel', () => { - nextTick(() => { - fs.unlinkSync(exporter.outputFile); - process.stdout.write(JSON.stringify({ type: 'cancel' })); - }); + fs.unlinkSync(exporter.outputFile); + parentPort.postMessage({ type: 'cancel' }); }); exporter.on('progress', state => { - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'export-progress', payload: state })); @@ -78,7 +74,7 @@ process.stdin.on('data', async buff => { } catch (err) { log.error(err.toString()); - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: err.toString() })); @@ -86,4 +82,6 @@ process.stdin.on('data', async buff => { } else if (type === 'cancel') exporter.cancel(); -}); +}; + +parentPort.on('message', exportHandler); diff --git a/src/main/workers/importer.ts b/src/main/workers/importer.ts index c7c5a702..0d7992ab 100644 --- a/src/main/workers/importer.ts +++ b/src/main/workers/importer.ts @@ -2,6 +2,7 @@ import * as antares from 'common/interfaces/antares'; import * as log from 'electron-log/main'; import * as mysql from 'mysql2'; import * as pg from 'pg'; +import { parentPort } from 'worker_threads'; import { MySQLClient } from '../libs/clients/MySQLClient'; import { PostgreSQLClient } from '../libs/clients/PostgreSQLClient'; @@ -14,9 +15,14 @@ log.transports.file.fileName = 'workers.log'; log.transports.console = null; log.errorHandler.startCatching(); -process.stdin.on('data', async (buff: Buffer) => { - const { type, dbConfig, options } = JSON.parse(buff.toString()); - +const importHandler = async (data: { + type: string; + dbConfig: mysql.ConnectionOptions & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } + | pg.ClientConfig & { schema: string; ssl?: mysql.SslOptions; ssh?: SSHConfig; readonly: boolean } + | { databasePath: string; readonly: boolean }; + options: ImportOptions; +}) => { + const { type, dbConfig, options } = data; if (type === 'init') { try { const connection = await ClientsFactory.getClient({ @@ -39,7 +45,7 @@ process.stdin.on('data', async (buff: Buffer) => { importer = new PostgreSQLImporter(pool as unknown as pg.PoolClient, options); break; default: - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: `"${options.type}" importer not aviable` })); @@ -48,32 +54,32 @@ process.stdin.on('data', async (buff: Buffer) => { importer.once('error', err => { log.error(err.toString()); - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: err.toString() })); }); importer.once('end', () => { - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'end', payload: { cancelled: importer.isCancelled } })); }); importer.once('cancel', () => { - process.stdout.write(JSON.stringify({ type: 'cancel' })); + parentPort.postMessage({ type: 'cancel' }); }); importer.on('progress', state => { - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'import-progress', payload: state })); }); importer.on('query-error', state => { - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'query-error', payload: state })); @@ -83,7 +89,7 @@ process.stdin.on('data', async (buff: Buffer) => { } catch (err) { log.error(err.toString()); - process.stdout.write(JSON.stringify({ + parentPort.postMessage({ type: 'error', payload: err.toString() })); @@ -91,4 +97,6 @@ process.stdin.on('data', async (buff: Buffer) => { } else if (type === 'cancel') importer.cancel(); -}); +}; + +parentPort.on('message', importHandler); diff --git a/webpack.main.config.js b/webpack.main.config.js index c95c1fc0..e0505418 100644 --- a/webpack.main.config.js +++ b/webpack.main.config.js @@ -19,7 +19,15 @@ module.exports = { // Main output: { libraryTarget: 'commonjs2', path: path.join(__dirname, 'dist'), - filename: '[name].js' + filename: '[name].js', + assetModuleFilename: (pathData) => { + const { filename } = pathData; + + if (filename.endsWith('.ts')) + return '[name].js'; + else + return '[name][ext]'; + } }, node: { global: true,