diff --git a/app/package.json b/app/package.json index 5e7e64a..c8927c3 100644 --- a/app/package.json +++ b/app/package.json @@ -11,7 +11,7 @@ "mochatest": "mocha --require ts-node/register src/**/*.spec.ts" }, "engines": { - "npm": "16" + "node": "16" }, "author": "", "license": "CC-BY-ND-4.0", diff --git a/app/src/actions/ConnectionManager.ts b/app/src/actions/ConnectionManager.ts index 898a05e..8d3c0dd 100644 --- a/app/src/actions/ConnectionManager.ts +++ b/app/src/actions/ConnectionManager.ts @@ -9,14 +9,13 @@ import { import { default as persistentStorage, StorageIdentifier } from '../utils/PersistentStorage' import { Dispatch } from 'redux' import { showError } from './Global' -import * as electron from 'electron' import { promises as fsPromise } from 'fs' import * as path from 'path' import { ActionTypes, Action } from '../reducers/ConnectionManager' import { Subscription } from '../../../backend/src/DataSource/MqttSource' import { connectionsMigrator } from './migrations/Connection' -import { EventDispatcher, openDialogResponse, OpenDialogResponse, rendererEvents, requestOpenDialog } from '../../../events' -import { v4 } from 'uuid' +import { rendererRpc } from '../../../events' +import { makeOpenDialogRpc } from '../../../events/OpenDialogRequest' export interface ConnectionDictionary { [s: string]: ConnectionOptions @@ -74,29 +73,11 @@ async function openCertificate(): Promise { certificateSizeDoesNotMatch: 'Certificate size larger/smaller then expected.', } - let requestId = v4(); - - const response = new Promise((resolve, reject) => { - let callback = (result: OpenDialogResponse) => { - rendererEvents.unsubscribe(openDialogResponse(), callback) - if (result.identifier == requestId) { - resolve(result) - } else { - reject(new Error("Unexpected file select")) - } - } - rendererEvents.subscribe(openDialogResponse(), callback) + const openDialogReturnValue = await rendererRpc.call(makeOpenDialogRpc(), { + properties: ['openFile'], + securityScopedBookmarks: true, }) - rendererEvents.emit(requestOpenDialog(), { - identifier: requestId, - options: { - properties: ['openFile'], - securityScopedBookmarks: true, - } - }) - const openDialogReturnValue = (await response).result; - const selectedFile = openDialogReturnValue.filePaths && openDialogReturnValue.filePaths[0] if (!selectedFile) { throw rejectReasons.noCertificateSelected diff --git a/app/src/components/ConnectionSetup/CertificateFileSelection.tsx b/app/src/components/ConnectionSetup/CertificateFileSelection.tsx index bbeea0d..788e799 100644 --- a/app/src/components/ConnectionSetup/CertificateFileSelection.tsx +++ b/app/src/components/ConnectionSetup/CertificateFileSelection.tsx @@ -1,7 +1,5 @@ import * as React from 'react' -import Add from '@material-ui/icons/Add' import ClearAdornment from '../helper/ClearAdornment' -import Delete from '@material-ui/icons/Delete' import Lock from '@material-ui/icons/Lock' import { bindActionCreators } from 'redux' import { Button, Theme, Tooltip, Typography } from '@material-ui/core' diff --git a/app/src/components/Demo/index.tsx b/app/src/components/Demo/index.tsx index 03e9e3a..63bef6c 100644 --- a/app/src/components/Demo/index.tsx +++ b/app/src/components/Demo/index.tsx @@ -5,7 +5,7 @@ let heapdump: any function writeHeapdump(path?: string) { if (!heapdump) { - //heapdump = require('heapdump') + // { super(props) this.state = { newerVersions: [] } - const ownVersion = electron.app.getVersion() - this.fetchReleases().then(releases => { - const newerVersions = releases - .filter(release => this.allowPrereleaseIfOwnVersionIsBeta(release, ownVersion)) - .filter(release => compareVersions(release.tag_name, ownVersion) > 0) - .sort((a, b) => compareVersions(b.tag_name, a.tag_name)) + this.checkForUpdates() + } - if (newerVersions.length > 0) { - this.setState({ newerVersions }) - this.props.actions.showUpdateNotification(true) - } - }) + private async checkForUpdates() { + const ownVersion = await rendererRpc.call(getAppVersion, undefined, 10000); + const releases = await this.fetchReleases(); + const newerVersions = releases + .filter(release => this.allowPrereleaseIfOwnVersionIsBeta(release, ownVersion)) + .filter(release => compareVersions(release.tag_name, ownVersion) > 0) + .sort((a, b) => compareVersions(b.tag_name, a.tag_name)) + + if (newerVersions.length > 0) { + this.setState({ newerVersions }) + this.props.actions.showUpdateNotification(true) + } } private allowPrereleaseIfOwnVersionIsBeta(release: GithubRelease, ownVersion: string) { diff --git a/app/src/utils/PersistentStorage.ts b/app/src/utils/PersistentStorage.ts index c704594..7346f34 100644 --- a/app/src/utils/PersistentStorage.ts +++ b/app/src/utils/PersistentStorage.ts @@ -1,12 +1,9 @@ -import { rendererEvents } from '../../../events' -import { v4 } from 'uuid' +import { rendererRpc } from '../../../events' import { storageStoreEvent, - makeStorageResponseEvent, storageLoadEvent, storageClearEvent, - makeStorageAcknowledgementEvent, } from '../../../events/StorageEvents' export interface StorageIdentifier { @@ -20,71 +17,23 @@ export interface PersistentStorage { } class RemoteStorage implements PersistentStorage { - private timeoutCallback(event: any, callback: any, reject: any) { - setTimeout(() => { - reject('remote storage timeout') - rendererEvents.unsubscribe(event, callback) - }, 10000) - } - - private expectAck(transactionId: string): Promise { - const ack = makeStorageAcknowledgementEvent(transactionId) - return new Promise((resolve, reject) => { - const callback = (msg: any) => { - if (msg && msg.error) { - reject(msg.error) - } else { - resolve() - } - rendererEvents.unsubscribe(ack, callback) - } - rendererEvents.subscribe(ack, callback) - this.timeoutCallback(ack, callback, reject) - }) - } - public store(identifier: StorageIdentifier, data: Model): Promise { - const transactionId = v4() - const expectation = this.expectAck(transactionId) - rendererEvents.emit(storageStoreEvent, { + return rendererRpc.call(storageStoreEvent, { data, - transactionId, store: identifier.id, }) - return expectation } - public load(identifier: StorageIdentifier): Promise { - const transactionId = v4() - const responseEvent = makeStorageResponseEvent(transactionId) - - const promise = new Promise((resolve, reject) => { - const callback = (msg: any) => { - if (msg.error) { - reject(msg.error) - } else { - resolve(msg.data) - } - rendererEvents.unsubscribe(responseEvent, callback) - } - rendererEvents.subscribe(responseEvent, callback) - this.timeoutCallback(responseEvent, callback, reject) - }) - - rendererEvents.emit(storageLoadEvent, { - transactionId, + public async load(identifier: StorageIdentifier): Promise { + const result = await rendererRpc.call(storageLoadEvent, { store: identifier.id, - }) + }, 10000) - return promise + return (result as any).data } public clear(): Promise { - const transactionId = v4() - const expectation = this.expectAck(transactionId) - - rendererEvents.emit(storageClearEvent, { transactionId }) - return expectation + return rendererRpc.call(storageClearEvent, undefined, 10000) } } diff --git a/app/webpack.config.js b/app/webpack.config.js index 09ccca7..a178569 100644 --- a/app/webpack.config.js +++ b/app/webpack.config.js @@ -30,6 +30,7 @@ module.exports = { priority: -10, }, default: { + name: 'default', minChunks: 2, priority: -20, reuseExistingChunk: true, diff --git a/backend/package.json b/backend/package.json index 3dbb785..c349f4c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -12,7 +12,7 @@ "postinstall": "yarn build" }, "engines": { - "npm": "16" + "node": "16" }, "author": "", "license": "CC-BY-ND-4.0", diff --git a/backend/src/ConfigStorage.ts b/backend/src/ConfigStorage.ts index 5e2e2ac..898941e 100644 --- a/backend/src/ConfigStorage.ts +++ b/backend/src/ConfigStorage.ts @@ -2,10 +2,8 @@ import * as FileAsync from 'lowdb/adapters/FileAsync' import * as fs from 'fs-extra' import * as lowdb from 'lowdb' import * as path from 'path' -import { backendEvents } from '../../events' +import { backendRpc } from '../../events' import { - makeStorageAcknowledgementEvent, - makeStorageResponseEvent, storageClearEvent, storageLoadEvent, storageStoreEvent, @@ -32,56 +30,26 @@ export default class ConfigStorage { } public async init() { - backendEvents.subscribe(storageStoreEvent, async event => { - const ack = makeStorageAcknowledgementEvent(event.transactionId) - try { - const db = await this.getDb() - await db.set(event.store, event.data).write() - backendEvents.emit(ack, undefined) - } catch (error) { - backendEvents.emit(ack, { - error, - transactionId: event.transactionId, - store: event.store, - }) - throw error + backendRpc.on(storageStoreEvent, async event => { + const db = await this.getDb() + await db.set(event.store, event.data).write() + return + }) + + backendRpc.on(storageLoadEvent, async event => { + const db = await this.getDb() + const data = await db.get(event.store).value() + return { + data, + store: event.store, } }) - backendEvents.subscribe(storageLoadEvent, async event => { - const responseEvent = makeStorageResponseEvent(event.transactionId) - try { - const db = await this.getDb() - const data = await db.get(event.store).value() - backendEvents.emit(responseEvent, { - data, - transactionId: event.transactionId, - store: event.store, - }) - } catch (error) { - backendEvents.emit(responseEvent, { - error, - transactionId: event.transactionId, - store: event.store, - }) - throw error - } - }) - - backendEvents.subscribe(storageClearEvent, async event => { - try { - const db = await this.getDb() - const keys = await db.keys().value() - for (const key of keys) { - await db.unset(key).write() - } - backendEvents.emit(makeStorageAcknowledgementEvent(event.transactionId), undefined) - } catch (error) { - backendEvents.emit(makeStorageAcknowledgementEvent(event.transactionId), { - error, - transactionId: event.transactionId, - }) - throw error + backendRpc.on(storageClearEvent, async event => { + const db = await this.getDb() + const keys = await db.keys().value() + for (const key of keys) { + await db.unset(key).write() } }) } diff --git a/backend/src/Model/Tree.ts b/backend/src/Model/Tree.ts index d3aa655..904001e 100644 --- a/backend/src/Model/Tree.ts +++ b/backend/src/Model/Tree.ts @@ -1,6 +1,6 @@ import { ChangeBuffer } from './ChangeBuffer' import { Destroyable } from './Destroyable' -import { EventBusInterface, EventDispatcher, makeConnectionMessageEvent, MqttMessage } from '../../../events' +import { EventDispatcher, makeConnectionMessageEvent, MqttMessage, EventBusInterface } from '../../../events' import { TreeNode } from './' import { TreeNodeFactory } from './TreeNodeFactory' @@ -31,7 +31,7 @@ export class Tree extends TreeNode { if (!this.paused && this.applyChangesHasCompleted) { this.applyChangesHasCompleted = false if ((window as any).requestIdleCallback) { - ;(window as any).requestIdleCallback(() => this.applyUnmergedChanges(), { timeout: 500 }) + ; (window as any).requestIdleCallback(() => this.applyUnmergedChanges(), { timeout: 500 }) } else { this.applyUnmergedChanges() } diff --git a/events/EventBus.ts b/events/EventBus.ts deleted file mode 100644 index 8a95df9..0000000 --- a/events/EventBus.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { IpcMain, ipcMain, ipcRenderer } from 'electron' - -import { Event } from './Events' -import { IpcRendererEventBus } from './IpcRendererEventBus' - -export interface EventBusInterface { - subscribe(event: Event, callback: (msg: MessageType) => void): void - unsubscribeAll(event: Event): void - emit(event: Event, msg: MessageType): void - unsubscribe(event: Event, callback: any): void -} - -export interface CallbackStore { - wrappedCallback: any - callback: any -} - -class IpcMainEventBus implements EventBusInterface { - private ipc: IpcMain - private client: any - constructor(ipc: IpcMain) { - this.ipc = ipc - } - - public subscribe(subscribeEvent: Event, callback: (msg: MessageType) => void) { - console.log('subscribing', subscribeEvent.topic) - this.ipc.on(subscribeEvent.topic, (event: any, arg: any) => { - this.client = event.sender - callback(arg) - }) - } - - public unsubscribeAll(event: Event) { - console.log('unsubscribeAll', event.topic) - this.ipc.removeAllListeners(event.topic) - } - - public unsubscribe(event: Event, callback: any) { - throw new Error('Not implemented') // Todo: implement - } - - public emit(event: Event, msg: MessageType) { - if (!this.client.isDestroyed()) { - this.client.send(event.topic, msg) - } - } -} - -export const rendererEvents = new IpcRendererEventBus(ipcRenderer) -export const backendEvents = new IpcMainEventBus(ipcMain) diff --git a/events/EventSystem/CallbackStore.ts b/events/EventSystem/CallbackStore.ts new file mode 100644 index 0000000..3d214ca --- /dev/null +++ b/events/EventSystem/CallbackStore.ts @@ -0,0 +1,4 @@ +export interface CallbackStore { + wrappedCallback: any; + callback: any; +} diff --git a/events/EventSystem/EventBus.ts b/events/EventSystem/EventBus.ts new file mode 100644 index 0000000..b033307 --- /dev/null +++ b/events/EventSystem/EventBus.ts @@ -0,0 +1,12 @@ +import { ipcMain, ipcRenderer } from 'electron' + +import { IpcMainEventBus } from './IpcMainEventBus' +import { IpcRendererEventBus } from './IpcRendererEventBus' +import { Rpc } from './Rpc' + +export const rendererEvents = new IpcRendererEventBus(ipcRenderer) +export const backendEvents = new IpcMainEventBus(ipcMain) + +// Preferred way to communicate typesafe +export const rendererRpc = new Rpc(rendererEvents) +export const backendRpc = new Rpc(backendEvents) diff --git a/events/EventSystem/EventBusInterface.ts b/events/EventSystem/EventBusInterface.ts new file mode 100644 index 0000000..bd574ee --- /dev/null +++ b/events/EventSystem/EventBusInterface.ts @@ -0,0 +1,8 @@ +import { Event } from '../Events'; + +export interface EventBusInterface { + subscribe(event: Event, callback: (msg: MessageType) => void): void; + unsubscribeAll(event: Event): void; + emit(event: Event, msg: MessageType): void; + unsubscribe(event: Event, callback: any): void; +} diff --git a/events/EventDispatcher.ts b/events/EventSystem/EventDispatcher.ts similarity index 100% rename from events/EventDispatcher.ts rename to events/EventSystem/EventDispatcher.ts diff --git a/events/EventSystem/IpcMainEventBus.ts b/events/EventSystem/IpcMainEventBus.ts new file mode 100644 index 0000000..406084b --- /dev/null +++ b/events/EventSystem/IpcMainEventBus.ts @@ -0,0 +1,34 @@ +import { IpcMain } from 'electron'; +import { Event } from '../Events'; +import { EventBusInterface } from "./EventBusInterface"; + +export class IpcMainEventBus implements EventBusInterface { + private ipc: IpcMain; + private client: any; + constructor(ipc: IpcMain) { + this.ipc = ipc; + } + + public subscribe(subscribeEvent: Event, callback: (msg: MessageType) => void) { + console.log('subscribing', subscribeEvent.topic); + this.ipc.on(subscribeEvent.topic, (event: any, arg: any) => { + this.client = event.sender; + callback(arg); + }); + } + + public unsubscribeAll(event: Event) { + console.log('unsubscribeAll', event.topic); + this.ipc.removeAllListeners(event.topic); + } + + public unsubscribe(event: Event, callback: any) { + throw new Error('Not implemented'); // Todo: implement + } + + public emit(event: Event, msg: MessageType) { + if (!this.client.isDestroyed()) { + this.client.send(event.topic, msg); + } + } +} diff --git a/events/IpcRendererEventBus.ts b/events/EventSystem/IpcRendererEventBus.ts similarity index 85% rename from events/IpcRendererEventBus.ts rename to events/EventSystem/IpcRendererEventBus.ts index 2d34293..8fc0bcd 100644 --- a/events/IpcRendererEventBus.ts +++ b/events/EventSystem/IpcRendererEventBus.ts @@ -1,26 +1,32 @@ -import { CallbackStore, EventBusInterface } from './EventBus' -import { Event } from './Events' +import { CallbackStore } from "./CallbackStore" +import { EventBusInterface } from "./EventBusInterface" +import { Event } from '../Events' import { IpcRenderer } from 'electron' export class IpcRendererEventBus implements EventBusInterface { private ipc: IpcRenderer private callbacks: Array = [] + constructor(ipc: IpcRenderer) { this.ipc = ipc } + public subscribe(event: Event, callback: (msg: MessageType) => void) { const wrappedCallback = (_: any, arg: any) => { callback(arg) } + console.log("subscribing", event.topic) this.ipc.on(event.topic, wrappedCallback) this.callbacks.push({ callback, wrappedCallback, }) } + public unsubscribeAll(event: Event) { this.ipc.removeAllListeners(event.topic) } + public unsubscribe(event: Event, callback: any) { const item = this.callbacks.find(store => store.callback === callback) if (!item) { @@ -29,6 +35,7 @@ export class IpcRendererEventBus implements EventBusInterface { this.ipc.removeListener(event.topic, item.wrappedCallback) this.callbacks = this.callbacks.filter(a => a !== item) } + public emit(event: Event, msg: MessageType) { this.ipc.send(event.topic, msg) } diff --git a/events/EventSystem/Rpc.ts b/events/EventSystem/Rpc.ts new file mode 100644 index 0000000..e6a59e3 --- /dev/null +++ b/events/EventSystem/Rpc.ts @@ -0,0 +1,54 @@ +import { Event } from '../Events'; +import { EventBusInterface } from './EventBusInterface' +import { v4 } from 'uuid'; + +export type RpcEvent = { + topic: string; +}; + +export class Rpc { + constructor(private participant: EventBusInterface) { } + + async call(event: RpcEvent, request: RpcRequest, timeout: number = 0): Promise { + return new Promise((resolve, reject) => { + let id = v4(); + + let responseEvent: Event = { topic: `${event.topic}/response` }; + let requestEvent: Event = { topic: `${event.topic}/request` }; + let callback = (result: { id: string; payload: RpcResponse; error: unknown }) => { + this.participant.unsubscribe(responseEvent as any, callback); + if (result.id === id) { + if (result.error) { + reject(result.error) + } else { + resolve(result.payload); + } + } + console.log("received", result) + }; + this.participant.subscribe(responseEvent, callback); + this.participant.emit(requestEvent, { id, payload: request }); + + if (timeout > 0) { + setTimeout(() => { + reject(new Error(`Did not respond to ${event.topic} within ${timeout}ms`)) + this.participant.unsubscribe(responseEvent as any, callback); + }, 10000) + } + }); + } + + async on(event: RpcEvent, handler: (request: RpcRequest) => Promise) { + this.participant.subscribe({ topic: `${event.topic}/request` } as RpcEvent, async (request) => { + let payload; + let error; + try { + payload = await handler((request as any).payload); + } catch (e) { + error = e + } + console.log("Responding with", payload, error) + this.participant.emit({ topic: `${event.topic}/response` }, { id: (request as any).id, payload, error }); + }); + } +} diff --git a/events/Events.ts b/events/Events.ts index 9bb4997..55fdfa7 100644 --- a/events/Events.ts +++ b/events/Events.ts @@ -1,7 +1,7 @@ import { Base64Message } from '../backend/src/Model/Base64Message' import { DataSourceState, MqttOptions } from '../backend/src/DataSource' import { UpdateInfo } from 'builder-util-runtime' -import { OpenDialogOptions, OpenDialogReturnValue } from 'electron' +import { RpcEvent } from './EventSystem/Rpc'; export type Event = { topic: string @@ -51,25 +51,6 @@ export function makeConnectionMessageEvent(connectionId: string): Event = { + topic: `getAppVersion` } - -export function requestOpenDialog(): Event { - return { - topic: `requestOpenDialog`, - } -} - -export interface OpenDialogResponse { - identifier: string - result: OpenDialogReturnValue -} - -export function openDialogResponse(): Event { - return { - topic: `openDialogResponse`, - } -} - diff --git a/events/OpenDialogRequest.ts b/events/OpenDialogRequest.ts new file mode 100644 index 0000000..f7e586a --- /dev/null +++ b/events/OpenDialogRequest.ts @@ -0,0 +1,8 @@ +import { OpenDialogOptions, OpenDialogReturnValue } from 'electron'; +import { RpcEvent } from './EventSystem/Rpc'; + +export function makeOpenDialogRpc(): RpcEvent { + return { + topic: `openDialog` + }; +} diff --git a/events/Server/index.ts b/events/Server/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/events/StorageEvents.ts b/events/StorageEvents.ts index 4c0bd7d..9cca5e8 100644 --- a/events/StorageEvents.ts +++ b/events/StorageEvents.ts @@ -1,39 +1,22 @@ -import { Event } from './' +import { RpcEvent } from './EventSystem/Rpc' -interface StorageEvent { - transactionId: string +export interface StoreCommand { + store: string + data: any } -export interface StoreCommand extends StorageEvent { - store?: string - data?: any - error?: any -} - -export interface LoadCommand extends StorageEvent { +export interface LoadCommand { store: string } -export const storageStoreEvent: Event = { +export const storageStoreEvent: RpcEvent = { topic: 'storage/store', } -export const storageLoadEvent: Event = { +export const storageLoadEvent: RpcEvent = { topic: 'storage/load', } -export function makeStorageAcknowledgementEvent(transactionId: string): Event { - return { - topic: `storage/ack/${transactionId}`, - } -} - -export function makeStorageResponseEvent(transactionId: string): Event { - return { - topic: `storage/response/${transactionId}`, - } -} - -export const storageClearEvent: Event = { +export const storageClearEvent: RpcEvent = { topic: 'storage/clear', } diff --git a/events/index.ts b/events/index.ts index b1e05e1..d067dee 100644 --- a/events/index.ts +++ b/events/index.ts @@ -1,3 +1,4 @@ export * from './Events' -export * from './EventDispatcher' -export * from './EventBus' +export * from './EventSystem/EventDispatcher' +export * from './EventSystem/EventBus' +export * from './EventSystem/EventBusInterface' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 65819f1..0977883 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "mime": "^2.4.4", "mqtt": "^3.0.0", "sha1": "^1.1.1", + "uuid": "^8.3.2", "yarn-run-all": "^3.1.1" }, "devDependencies": { @@ -35,6 +36,7 @@ "@types/node": "^12.6.8", "@types/semver": "7", "@types/sha1": "^1.1.1", + "@types/uuid": "^8.3.4", "builder-util-runtime": "^9", "chai": "^4.2.0", "cspell": "^4.0.28", @@ -52,6 +54,9 @@ "ts-node": "^10.5.0", "typescript": "^4.5.5", "webdriverio": "7.16" + }, + "engines": { + "node": "16" } }, "node_modules/@ampproject/remapping": { @@ -1133,6 +1138,12 @@ "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", "dev": true }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, "node_modules/@types/verror": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", @@ -3026,15 +3037,6 @@ "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", "dev": true }, - "node_modules/devtools/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -5113,6 +5115,16 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", @@ -8243,15 +8255,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spectron/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/spectron/node_modules/webdriver": { "version": "7.16.13", "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.13.tgz", @@ -8979,13 +8982,11 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "bin": { - "uuid": "bin/uuid" + "uuid": "dist/bin/uuid" } }, "node_modules/v8-compile-cache-lib": { @@ -10899,6 +10900,12 @@ "integrity": "sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==", "dev": true }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, "@types/verror": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", @@ -12384,12 +12391,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==", "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true } } }, @@ -13966,6 +13967,14 @@ "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "istanbul-lib-report": { @@ -16435,12 +16444,6 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, "webdriver": { "version": "7.16.13", "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-7.16.13.tgz", @@ -17019,10 +17022,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache-lib": { "version": "3.0.0", diff --git a/package.json b/package.json index ee042a0..a307ea4 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Explore your message queues", "main": "dist/src/electron.js", "engines": { - "npm": "16" + "node": "16" }, "scripts": { "start": "electron .", @@ -83,6 +83,7 @@ "@types/node": "^12.6.8", "@types/semver": "7", "@types/sha1": "^1.1.1", + "@types/uuid": "^8.3.4", "builder-util-runtime": "^9", "chai": "^4.2.0", "cspell": "^4.0.28", @@ -114,6 +115,7 @@ "mime": "^2.4.4", "mqtt": "^3.0.0", "sha1": "^1.1.1", + "uuid": "^8.3.2", "yarn-run-all": "^3.1.1" } -} \ No newline at end of file +} diff --git a/src/electron.ts b/src/electron.ts index 41715db..4b14a2a 100644 --- a/src/electron.ts +++ b/src/electron.ts @@ -1,7 +1,7 @@ import * as log from 'electron-log' import * as path from 'path' import ConfigStorage from '../backend/src/ConfigStorage' -import { ipcMain, app, BrowserWindow, Menu, dialog } from 'electron' +import { app, BrowserWindow, Menu, dialog } from 'electron' import { autoUpdater } from 'electron-updater' import { ConnectionManager } from '../backend/src/index' // import { electronTelemetryFactory } from 'electron-telemetry' @@ -10,7 +10,8 @@ import buildOptions from './buildOptions' import { waitForDevServer, isDev, runningUiTestOnCi, loadDevTools } from './development' import { shouldAutoUpdate, handleAutoUpdate } from './autoUpdater' import { registerCrashReporter } from './registerCrashReporter' -import { backendEvents, EventDispatcher, OpenDialogRequest, openDialogResponse, OpenDialogResponse, requestOpenDialog } from '../events' +import { makeOpenDialogRpc } from '../events/OpenDialogRequest' +import { backendRpc, getAppVersion } from '../events' registerCrashReporter() @@ -20,14 +21,10 @@ registerCrashReporter() app.commandLine.appendSwitch('--no-sandbox') app.whenReady().then(() => { - backendEvents.subscribe(requestOpenDialog(), async (request) => { - let result = await dialog.showOpenDialog(BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0], request.options) - - backendEvents.emit(openDialogResponse(), { - identifier: request.identifier, - result: result - }) + backendRpc.on(makeOpenDialogRpc(), async (request) => { + return dialog.showOpenDialog(BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0], request) }) + backendRpc.on(getAppVersion, async () => app.getVersion()) }) autoUpdater.logger = log diff --git a/yarn.lock b/yarn.lock index 9316e77..ecff659 100644 --- a/yarn.lock +++ b/yarn.lock @@ -661,6 +661,11 @@ "resolved" "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz" "version" "0.7.36" +"@types/uuid@^8.3.4": + "integrity" "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + "resolved" "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz" + "version" "8.3.4" + "@types/verror@^1.10.3": "integrity" "sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==" "resolved" "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz" @@ -5295,7 +5300,7 @@ "resolved" "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" "version" "3.4.0" -"uuid@^8.0.0": +"uuid@^8.0.0", "uuid@^8.3.2": "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" "version" "8.3.2"