Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactor Electron main process #9

Merged
merged 1 commit into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ testem.log
.DS_Store
Thumbs.db

.nx/cache
.angular
.database.sqlite3
*nx
File renamed without changes.
19 changes: 19 additions & 0 deletions hooks.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { join } = require('path');
const { runCommand } = require('./main-process/command-utils.cjs');

(async () => {
try {
// Run npm install in the specified directory
await runCommand(
'npm install --prefer-offline --no-audit --progress=false --omit=dev && npm install sqlite3 --prefer-offline --no-audit --progress=false --omit=dev',
{
cwd: join(__dirname, 'dist/nest-backend'),
stdio: 'inherit',
}
);

console.log('npm install completed successfully');
} catch (err) {
console.error(`Error: ${err.message}`);
}
})();
38 changes: 0 additions & 38 deletions hooks.js

This file was deleted.

101 changes: 101 additions & 0 deletions main-process/backend.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';
// const { utilityProcess } = require('electron');
const { fork } = require('child_process');
const { join } = require('path');
const constants = require('./constants.cjs');
const environmentUtils = require('./environment-utils.cjs');
const fileUtils = require('./file-utils.cjs');
const pathUtils = require('./path-utils.cjs');

function startBackend(resourcesPath) {
let env;
const rootBackendFolderPath = pathUtils.getRootBackendFolderPath(
environmentUtils.getEnvironment(),
resourcesPath
);
const serverPath = join(rootBackendFolderPath, 'main.js');
const databasePath = join(
rootBackendFolderPath,
constants.ROOT_DATABASE_NAME
);
switch (environmentUtils.getEnvironment()) {
case 'dev':
env = {
NODE_ENV: 'dev',
DATABASE_PATH: databasePath,
PORT: 3000,
};
break;
case 'staging':
env = {
NODE_ENV: 'staging',
DATABASE_PATH: databasePath,
PORT: 3000,
};
break;
case 'prod':
env = {
NODE_ENV: 'prod',
DATABASE_PATH: databasePath,
PORT: 5000,
};
break;
default:
env = {
NODE_ENV: 'prod',
DATABASE_PATH: databasePath,
PORT: 5000,
};
break;
}

fileUtils.writePath(
join(
pathUtils.getRootBackendFolderPath(
environmentUtils.getEnvironment(),
resourcesPath
),
'env.txt'
),
JSON.stringify(env, null, 2)
);

fileUtils.writePath(
join(
pathUtils.getRootBackendFolderPath(
environmentUtils.getEnvironment(),
resourcesPath
),
'serverPath.txt'
),
serverPath
);

// return utilityProcess.fork(serverPath, { env });
return fork(serverPath, { env });
}

async function checkIfPortIsOpen(urls, maxAttempts = 20, timeout = 2000) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
for (const url of urls) {
try {
const response = await fetch(url);
if (response) {
console.log('Server is ready');
return true; // Port is open
}
} catch (error) {
console.log(`Attempt ${attempt}: Waiting for server to start...`);
}
}
await new Promise((resolve) => setTimeout(resolve, timeout)); // Wait for 2 seconds before retrying
}
throw new Error(
`Failed to connect to the server after ${maxAttempts} attempts`
);
}

module.exports = {
startBackend,
checkIfPortIsOpen,
};
25 changes: 25 additions & 0 deletions main-process/command-utils.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';
const { spawn } = require('child_process');

// Helper function to run a command and return a promise
const runCommand = (command, options) => {
return new Promise((resolve, reject) => {
const process = spawn(command, { ...options, shell: true });

process.on('close', (code) => {
if (code !== 0) {
reject(new Error(`${command} failed with code ${code}`));
} else {
resolve();
}
});

process.on('error', (err) => {
reject(err);
});
});
};

module.exports = {
runCommand,
};
9 changes: 9 additions & 0 deletions main-process/constants.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

const URLs = ['http://localhost:5000', 'http://localhost:3000'];
const ROOT_DATABASE_NAME = 'database.sqlite3';

module.exports = {
URLs,
ROOT_DATABASE_NAME,
};
6 changes: 6 additions & 0 deletions main-process/environment-utils.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict';
function getEnvironment() {
return process.env.NODE_ENV || 'prod';
}

module.exports = { getEnvironment };
10 changes: 10 additions & 0 deletions main-process/file-utils.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';
const { writeFileSync } = require('fs');

function writePath(filePath, content) {
writeFileSync(filePath, content, 'utf8');
}

module.exports = {
writePath,
};
77 changes: 77 additions & 0 deletions main-process/frontend.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict';
const { BrowserWindow } = require('electron');
const { join } = require('path');
const pathUtils = require('./path-utils.cjs');
const fileUtils = require('./file-utils.cjs');

let loadingWindow = null;

function createLoadingWindow() {
console.log('Creating loading window');
if (loadingWindow) {
console.log('Loading window already exists');
return loadingWindow;
}

try {
loadingWindow = new BrowserWindow({
width: 400,
height: 200,
frame: false,
transparent: true,
alwaysOnTop: true,
webPreferences: {
nodeIntegration: true,
},
});

loadingWindow.loadFile(join(__dirname, 'loading.html'));
loadingWindow.center();

loadingWindow.on('closed', () => {
loadingWindow = null;
});

return loadingWindow;
} catch (error) {
console.error('Error creating loading window:', error);
return null;
}
}

function createWindow(env, resourcesPath) {
const mainWindow = new BrowserWindow({
width: 1400,
height: 900,
webPreferences: {
nodeIntegration: true,
},
});

try {
const entryPath = pathUtils.getFrontendPath(env, resourcesPath);
fileUtils.writePath(
join(
pathUtils.getRootBackendFolderPath(env, resourcesPath),
'entryPath.txt'
),
entryPath
);
mainWindow.loadFile(entryPath);
mainWindow.webContents.openDevTools(); // Open DevTools in development
} catch (e) {
console.error(e);
fileUtils.writePath(
join(
pathUtils.getRootBackendFolderPath(env, resourcesPath),
'entryPathError.txt'
),
e.message
);
}
}

module.exports = {
createLoadingWindow,
createWindow,
};
36 changes: 36 additions & 0 deletions main-process/loading.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<title>Loading...</title>
<style>
body {
background: transparent;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
font-family: Arial, sans-serif;
}
.loader {
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="loader"></div>
</body>
</html>
41 changes: 41 additions & 0 deletions main-process/path-utils.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict';
const { join } = require('path');

function getRootBackendFolderPath(env, resourcesPath) {
switch (env) {
case 'dev':
case 'staging':
return join('dist', 'nest-backend');
case 'prod':
return resourcesPath;
default:
// Default to production path
return resourcesPath;
}
}

function getFrontendPath(env, resourcesPath) {
const devFrontendPath = join('dist', 'ng-tracker', 'browser', 'index.html');

const prodFrontendPath = join(
resourcesPath,
'ng-tracker',
'browser',
'index.html'
);

switch (env) {
case 'dev':
case 'staging':
return devFrontendPath;
case 'prod':
return prodFrontendPath;
default:
return prodFrontendPath;
}
}

module.exports = {
getRootBackendFolderPath,
getFrontendPath,
};
Loading