Skip to content

Commit

Permalink
Simpler function binding
Browse files Browse the repository at this point in the history
  • Loading branch information
jdeniau committed Mar 4, 2024
1 parent 98e36e9 commit b2493fd
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 63 deletions.
19 changes: 19 additions & 0 deletions src/configuration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { dialog, safeStorage } from 'electron';
import { existsSync, mkdirSync, readFileSync, writeFile } from 'node:fs';
import { resolve } from 'node:path';
import envPaths from 'env-paths';
import { CONFIGURATION_CHANNEL } from '../preload/configurationChannel';
import { ConnectionObject } from '../sql/types';
import { DEFAULT_THEME } from './themes';
import {
Expand Down Expand Up @@ -164,4 +165,22 @@ export function updateConnectionState<K extends keyof ConnectionAppState>(
writeConfiguration(config);
}

const IPC_EVENT_BINDING = {
[CONFIGURATION_CHANNEL.GET]: getConfiguration,
[CONFIGURATION_CHANNEL.ADD_CONNECTION]: addConnectionToConfig,
[CONFIGURATION_CHANNEL.EDIT_CONNECTION]: editConnection,
[CONFIGURATION_CHANNEL.CHANGE_THEME]: changeTheme,
[CONFIGURATION_CHANNEL.UPDATE_CONNECTION_STATE]: updateConnectionState,
} as const;

export function bindIpcMain(ipcMain: Electron.IpcMain): void {
for (const [channel, handler] of Object.entries(IPC_EVENT_BINDING)) {
ipcMain.handle(channel, (event, ...args: unknown[]) =>
// convert the first argument to senderId and bind the rest
// @ts-expect-error issue with strict type in tsconfig, but seems to work at runtime
handler(...args)
);
}
}

export const testables = { getBaseConfig };
38 changes: 2 additions & 36 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ import installExtension, {
REACT_DEVELOPER_TOOLS,
} from 'electron-devtools-installer';
import { updateElectronApp } from 'update-electron-app';
import {
addConnectionToConfig,
changeTheme,
editConnection,
getConfiguration,
updateConnectionState,
} from './configuration';
import type { Configuration, ConnectionAppState } from './configuration/type';
import { bindIpcMain as bindIpcMainConfiguration } from './configuration';
import connectionStackInstance from './sql';
import type { ConnectionObject } from './sql/types';

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
Expand Down Expand Up @@ -82,33 +74,7 @@ app.whenReady().then(() => {

installReactDevToolsExtension();

ipcMain.handle('config:get', getConfiguration);
ipcMain.handle(
'config:connection:add',
(event: unknown, connection: ConnectionObject): Configuration =>
addConnectionToConfig(connection)
);
ipcMain.handle(
'config:connection:edit',
(
event: unknown,
connectionName: string,
connection: ConnectionObject
): Configuration => editConnection(connectionName, connection)
);
ipcMain.handle('config:theme:change', (event: unknown, name: string) =>
changeTheme(name)
);
ipcMain.handle(
'config:connection:updateState',
<K extends keyof ConnectionAppState>(
event: unknown,
connectionName: string,
key: K,
value: ConnectionAppState[K]
) => updateConnectionState(connectionName, key, value)
);

bindIpcMainConfiguration(ipcMain);
connectionStackInstance.bindIpcMain(ipcMain);

// createWindow();
Expand Down
7 changes: 7 additions & 0 deletions src/preload/bindChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ipcRenderer } from 'electron';

export function bindChannel(channel: string) {
return function (...args: unknown[]) {
return ipcRenderer.invoke(channel, ...args);
};
}
28 changes: 9 additions & 19 deletions src/preload/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ipcRenderer } from 'electron';
import type { Configuration, ConnectionAppState } from '../configuration/type';
import type { ConnectionObject } from '../sql/types';
import { bindChannel } from './bindChannel';
import { CONFIGURATION_CHANNEL } from './configurationChannel';

interface Config {
getConfiguration(): Promise<null | Configuration>;
Expand All @@ -22,22 +23,11 @@ interface Config {
}

export const config: Config = {
getConfiguration: () => ipcRenderer.invoke('config:get'),
addConnectionToConfig: (connection: ConnectionObject) =>
ipcRenderer.invoke('config:connection:add', connection),
editConnection: (connectionName: string, connection: ConnectionObject) =>
ipcRenderer.invoke('config:connection:edit', connectionName, connection),
changeTheme: (theme: string) =>
ipcRenderer.invoke('config:theme:change', theme),
updateConnectionState: <K extends keyof ConnectionAppState>(
connectionName: string,
key: K,
value: ConnectionAppState[K]
) =>
ipcRenderer.invoke(
'config:connection:updateState',
connectionName,
key,
value
),
getConfiguration: bindChannel(CONFIGURATION_CHANNEL.GET),
addConnectionToConfig: bindChannel(CONFIGURATION_CHANNEL.ADD_CONNECTION),
changeTheme: bindChannel(CONFIGURATION_CHANNEL.CHANGE_THEME),
updateConnectionState: bindChannel(
CONFIGURATION_CHANNEL.UPDATE_CONNECTION_STATE
),
editConnection: bindChannel(CONFIGURATION_CHANNEL.EDIT_CONNECTION),
};
7 changes: 7 additions & 0 deletions src/preload/configurationChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum CONFIGURATION_CHANNEL {
GET = 'config:get',
ADD_CONNECTION = 'config:connection:add',
EDIT_CONNECTION = 'config:connection:edit',
CHANGE_THEME = 'config:theme:change',
UPDATE_CONNECTION_STATE = 'config:connection:updateState',
}
10 changes: 5 additions & 5 deletions src/preload/sql.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { ipcRenderer } from 'electron';
import { Connection } from 'mysql2/promise';
import type {
ConnectionObject,
QueryResult,
QueryReturnType,
} from '../sql/types';
import { bindChannel } from './bindChannel';
import { SQL_CHANNEL } from './sqlChannel';

interface Sql {
openConnection(params: ConnectionObject): Promise<Connection>;
executeQuery<T extends QueryReturnType>(query: string): QueryResult<T>;
closeAllConnections(): Promise<void>;
}

// TODO : clone the binder object in sql/index.ts ?
export const sql: Sql = {
openConnection: (params) => ipcRenderer.invoke('sql:connect', params),
executeQuery: (query) => ipcRenderer.invoke('sql:executeQuery', query),
closeAllConnections: () => ipcRenderer.invoke('sql:closeAll'),
openConnection: bindChannel(SQL_CHANNEL.CONNECT),
executeQuery: bindChannel(SQL_CHANNEL.EXECUTE_QUERY),
closeAllConnections: bindChannel(SQL_CHANNEL.CLOSE_ALL),
};
5 changes: 5 additions & 0 deletions src/preload/sqlChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum SQL_CHANNEL {
CONNECT = 'sql:connect',
EXECUTE_QUERY = 'sql:executeQuery',
CLOSE_ALL = 'sql:closeAll',
}
7 changes: 4 additions & 3 deletions src/sql/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Connection, createConnection } from 'mysql2/promise';
import { SQL_CHANNEL } from '../preload/sqlChannel';
import { ConnectionObject, QueryResult } from './types';

class ConnectionStack {
private connections: Map<number, Connection> = new Map();

// List of IPC events and their handlers
#ipcEventBinding = {
'sql:connect': this.connect,
'sql:executeQuery': this.executeQuery,
'sql:closeAll': this.closeAllConnections,
[SQL_CHANNEL.CONNECT]: this.connect,
[SQL_CHANNEL.EXECUTE_QUERY]: this.executeQuery,
[SQL_CHANNEL.CLOSE_ALL]: this.closeAllConnections,
};

bindIpcMain(ipcMain: Electron.IpcMain): void {
Expand Down

0 comments on commit b2493fd

Please sign in to comment.