api running in electron main process

This commit is contained in:
Jan Prochazka
2021-12-25 09:23:03 +01:00
parent 2ff9e8c452
commit 24071ebde7
11 changed files with 173 additions and 104 deletions

View File

@@ -90,7 +90,7 @@
},
"homepage": "./",
"scripts": {
"start": "cross-env ELECTRON_START_URL=http://localhost:5000 electron .",
"start": "cross-env ELECTRON_START_URL=http://localhost:5000 ELECTRON_DEBUG=1 DEVMODE=1 electron .",
"start:local": "cross-env electron .",
"dist": "electron-builder",
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",

View File

@@ -101,25 +101,25 @@ function buildMenu() {
{
label: 'dbgate.org',
click() {
require('electron').shell.openExternal('https://dbgate.org');
electron.shell.openExternal('https://dbgate.org');
},
},
{
label: 'DbGate on GitHub',
click() {
require('electron').shell.openExternal('https://github.com/dbgate/dbgate');
electron.shell.openExternal('https://github.com/dbgate/dbgate');
},
},
{
label: 'DbGate on docker hub',
click() {
require('electron').shell.openExternal('https://hub.docker.com/r/dbgate/dbgate');
electron.shell.openExternal('https://hub.docker.com/r/dbgate/dbgate');
},
},
{
label: 'Report problem or feature request',
click() {
require('electron').shell.openExternal('https://github.com/dbgate/dbgate/issues/new');
electron.shell.openExternal('https://github.com/dbgate/dbgate/issues/new');
},
},
commandItem('tabs.changelog'),
@@ -182,6 +182,7 @@ function createWindow() {
// enableRemoteModule: true,
},
});
mainWindow.webContents.openDevTools();
// require('@electron/remote/main').enable(mainWindow.webContents);
if (store.get('winIsMaximized')) {
mainWindow.maximize();
@@ -190,7 +191,7 @@ function createWindow() {
mainMenu = buildMenu();
mainWindow.setMenu(mainMenu);
function loadMainWindow(initArgs) {
function loadMainWindow() {
const startUrl =
process.env.ELECTRON_START_URL ||
url.format({
@@ -198,18 +199,18 @@ function createWindow() {
protocol: 'file:',
slashes: true,
});
mainWindow.webContents.on('did-finish-load', function () {
mainWindow.webContents.executeJavaScript(
`runInit=()=>{
try{
dbgate_initializeElectron(${JSON.stringify(initArgs)});
}catch(e){
setTimeout(runInit,100)
}
};
runInit()`
);
});
// mainWindow.webContents.on('did-finish-load', function () {
// mainWindow.webContents.executeJavaScript(
// `runInit=()=>{
// try{
// dbgate_initializeElectron(${JSON.stringify(initArgs)});
// }catch(e){
// setTimeout(runInit,100)
// }
// };
// runInit()`
// );
// });
mainWindow.on('close', () => {
store.set('winBounds', mainWindow.getBounds());
store.set('winIsMaximized', mainWindow.isMaximized());
@@ -220,27 +221,35 @@ function createWindow() {
}
}
if (process.env.ELECTRON_START_URL) {
loadMainWindow({});
} else {
const apiProcess = fork(path.join(__dirname, '../packages/api/dist/bundle.js'), [
'--dynport',
'--is-electron-bundle',
'--native-modules',
path.join(__dirname, 'nativeModules'),
// '../../../src/nativeModules'
]);
apiProcess.on('message', msg => {
if (msg.msgtype == 'listening') {
const { port, authorization } = msg;
const api = require(path.join(
__dirname,
process.env.ELECTRON_DEBUG ? '../../packages/api' : '../packages/api/dist/bundle.js'
));
api.getMainModule().useAllControllers(null, electron);
loadMainWindow({
port,
authorization,
});
}
});
}
loadMainWindow();
// if (process.env.ELECTRON_START_URL) {
// loadMainWindow({});
// } else {
// const apiProcess = fork(path.join(__dirname, '../packages/api/dist/bundle.js'), [
// '--dynport',
// '--is-electron-bundle',
// '--native-modules',
// path.join(__dirname, 'nativeModules'),
// // '../../../src/nativeModules'
// ]);
// apiProcess.on('message', msg => {
// if (msg.msgtype == 'listening') {
// const { port, authorization } = msg;
// loadMainWindow({
// port,
// authorization,
// });
// }
// });
// }
// and load the index.html of the app.
// mainWindow.loadURL('http://localhost:3000');

View File

@@ -39,6 +39,7 @@
"fs-reverse": "^0.0.3",
"get-port": "^5.1.1",
"http": "^0.0.0",
"is-electron": "^2.2.1",
"js-yaml": "^4.1.0",
"json-stable-stringify": "^1.0.1",
"line-reader": "^0.4.0",

View File

@@ -8,12 +8,14 @@ if (processArgs.startProcess) {
const proc = require('./proc');
const module = proc[processArgs.startProcess];
module.start();
} else if (!module['parent'] && !processArgs.checkParent) {
const main = require('./main');
main.start();
}
// else if (!module['parent'] && !processArgs.checkParent) {
// const main = require('./main');
// main.start();
// }
module.exports = {
...shell,
getMainModule: () => require('./main'),

View File

@@ -102,20 +102,7 @@ function start() {
})
);
useController(app, '/connections', connections);
useController(app, '/server-connections', serverConnections);
useController(app, '/database-connections', databaseConnections);
useController(app, '/metadata', metadata);
useController(app, '/sessions', sessions);
useController(app, '/runners', runners);
useController(app, '/jsldata', jsldata);
useController(app, '/config', config);
useController(app, '/archive', archive);
useController(app, '/uploads', uploads);
useController(app, '/plugins', plugins);
useController(app, '/files', files);
useController(app, '/scheduler', scheduler);
useController(app, '/query-history', queryHistory);
useAllControllers(app, null);
// if (process.env.PAGES_DIRECTORY) {
// app.use('/pages', express.static(process.env.PAGES_DIRECTORY));
@@ -158,4 +145,21 @@ function start() {
}
}
module.exports = { start };
function useAllControllers(app, electron) {
useController(app, electron, '/connections', connections);
useController(app, electron, '/server-connections', serverConnections);
useController(app, electron, '/database-connections', databaseConnections);
useController(app, electron, '/metadata', metadata);
useController(app, electron, '/sessions', sessions);
useController(app, electron, '/runners', runners);
useController(app, electron, '/jsldata', jsldata);
useController(app, electron, '/config', config);
useController(app, electron, '/archive', archive);
useController(app, electron, '/uploads', uploads);
useController(app, electron, '/plugins', plugins);
useController(app, electron, '/files', files);
useController(app, electron, '/scheduler', scheduler);
useController(app, electron, '/query-history', queryHistory);
}
module.exports = { start, useAllControllers };

View File

@@ -2,6 +2,7 @@ const fs = require('fs');
const os = require('os');
const path = require('path');
const processArgs = require('./processArgs');
const isElectron = require('is-electron');
const platform = process.env.OS_OVERRIDE ? process.env.OS_OVERRIDE : process.platform;
const isWindows = platform === 'win32';
@@ -28,6 +29,7 @@ const platformInfo = {
isLinux,
isDocker,
isElectronBundle,
isElectron: isElectron(),
isDevMode,
isNpmDist,
isSnap: process.env.ELECTRON_SNAP == 'true',

View File

@@ -4,7 +4,7 @@ const express = require('express');
/**
* @param {string} route
*/
module.exports = function useController(app, route, controller) {
module.exports = function useController(app, electron, route, controller) {
const router = express.Router();
if (controller._init) {
@@ -23,6 +23,21 @@ module.exports = function useController(app, route, controller) {
const meta = controller[`${key}_meta`];
if (!meta) continue;
const routeAction = `/${_.kebabCase(key)}`;
if (electron) {
if (meta === true) {
const handler = `${route.substring(1)}-${_.kebabCase(key)}`;
console.log('REGISTERING HANDLER', handler);
electron.ipcMain.handle(handler, async (event, args) => {
const data = await controller[key](args);
return data;
});
}
continue;
}
let method = 'post';
let raw = false;
let rawParams = false;
@@ -36,11 +51,10 @@ module.exports = function useController(app, route, controller) {
rawParams = meta.rawParams;
}
const route = `/${_.kebabCase(key)}`;
if (raw) {
router[method](route, controller[key]);
router[method](routeAction, controller[key]);
} else {
router[method](route, async (req, res) => {
router[method](routeAction, async (req, res) => {
// if (controller._init && !controller._init_called) {
// await controller._init();
// controller._init_called = true;
@@ -58,5 +72,7 @@ module.exports = function useController(app, route, controller) {
}
}
app.use(route, router);
if (app) {
app.use(route, router);
}
};

View File

@@ -11,7 +11,7 @@
import { setAppLoaded } from './utility/appLoadManager';
import ErrorHandler from './utility/ErrorHandler.svelte';
import OpenTabsOnStartup from './utility/OpenTabsOnStartup.svelte';
import { shouldWaitForElectronInitialize } from './utility/getElectron';
// import { shouldWaitForElectronInitialize } from './utility/getElectron';
import { subscribeConnectionPingers } from './utility/connectionsPinger';
import { subscribePermissionCompiler } from './utility/hasPermission';
import { apiCall } from './utility/api';
@@ -19,10 +19,10 @@
let loadedApi = false;
async function loadApi() {
if (shouldWaitForElectronInitialize()) {
setTimeout(loadApi, 100);
return;
}
// if (shouldWaitForElectronInitialize()) {
// setTimeout(loadApi, 100);
// return;
// }
try {
// console.log('************** LOADING API');

View File

@@ -1,6 +1,7 @@
import resolveApi, { resolveApiHeaders } from './resolveApi';
import { writable } from 'svelte/store';
import { cacheClean } from './cache';
import getElectron from './getElectron';
// import socket from './socket';
let eventSource;
@@ -13,37 +14,53 @@ function wantEventSource() {
}
export async function apiCall(route: string, args: {} = undefined) {
const resp = await fetch(`${resolveApi()}/${route}`, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
...resolveApiHeaders(),
},
body: JSON.stringify(args),
});
return resp.json();
const electron = getElectron();
if (electron) {
const resp = await electron.invoke(route.replace('/', '-'), args);
return resp;
} else {
const resp = await fetch(`${resolveApi()}/${route}`, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
...resolveApiHeaders(),
},
body: JSON.stringify(args),
});
return resp.json();
}
}
const apiHandlers = new WeakMap();
export function apiOn(event: string, handler: Function) {
wantEventSource();
if (!apiHandlers.has(handler)) {
const handlerProxy = e => {
// console.log('RECEIVED', e.type, JSON.parse(e.data));
handler(JSON.parse(e.data));
};
apiHandlers.set(handler, handlerProxy);
}
const electron = getElectron();
if (electron) {
electron.addEventListener(event, handler);
} else {
wantEventSource();
if (!apiHandlers.has(handler)) {
const handlerProxy = e => {
// console.log('RECEIVED', e.type, JSON.parse(e.data));
handler(JSON.parse(e.data));
};
apiHandlers.set(handler, handlerProxy);
}
eventSource.addEventListener(event, apiHandlers.get(handler));
eventSource.addEventListener(event, apiHandlers.get(handler));
}
}
export function apiOff(event: string, handler: Function) {
wantEventSource();
if (apiHandlers.has(handler)) {
eventSource.removeEventListener(event, apiHandlers.get(handler));
const electron = getElectron();
if (electron) {
electron.removeEventListener(event, handler);
} else {
wantEventSource();
if (apiHandlers.has(handler)) {
eventSource.removeEventListener(event, apiHandlers.get(handler));
}
}
}

View File

@@ -1,11 +1,11 @@
class ElectronApi {
public port?: number;
public authorization?: string;
// public port?: number;
// public authorization?: string;
private ipcRenderer = getIpcRenderer();
constructor(args) {
this.port = args.port;
this.authorization = args.authorization;
constructor() {
// this.port = args.port;
// this.authorization = args.authorization;
}
send(msg, args = null) {
@@ -30,18 +30,29 @@ class ElectronApi {
async openExternal(url) {
await this.ipcRenderer.invoke('openExternal', url);
}
}
let apiInstance = null;
async invoke(route, args) {
const res = await this.ipcRenderer.invoke(route, args);
return res;
}
function initializeElectron(args) {
apiInstance = new ElectronApi(args);
if (window['dbgate_recreateSocket']) {
window['dbgate_recreateSocket']();
addEventListener(channel: string, listener: Function) {
this.ipcRenderer.on(channel, listener);
}
removeEventListener(channel: string, listener: Function) {
this.ipcRenderer.removeEventListener(channel, listener);
}
}
window['dbgate_initializeElectron'] = initializeElectron;
// function initializeElectron(args) {
// apiInstance = new ElectronApi(args);
// if (window['dbgate_recreateSocket']) {
// window['dbgate_recreateSocket']();
// }
// }
// window['dbgate_initializeElectron'] = initializeElectron;
function getIpcRenderer() {
if (window['require']) {
@@ -51,14 +62,16 @@ function getIpcRenderer() {
return null;
}
export function shouldWaitForElectronInitialize() {
return !!getIpcRenderer() && !apiInstance;
}
// export function shouldWaitForElectronInitialize() {
// return !!getIpcRenderer() && !apiInstance;
// }
export function isElectronAvailable() {
return !!getIpcRenderer();
}
const apiInstance = isElectronAvailable() ? new ElectronApi() : null;
export default function getElectron(): ElectronApi {
return apiInstance;
// try {

View File

@@ -5316,6 +5316,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
is-electron@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.1.tgz#751b1dd8a74907422faa5c35aaa0cf66d98086e9"
integrity sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==
is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"