// Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import { ipcRenderer } from 'electron'; import { explodePromise } from './util/explodePromise'; import * as log from './logging/log'; type ResolveType = (data: unknown) => void; export const electronRequire = require; export class CI { private readonly eventListeners = new Map>(); private readonly completedEvents = new Map>(); constructor(public readonly deviceName: string) { ipcRenderer.on('ci:event', (_, event, data) => { this.handleEvent(event, data); }); } public async waitForEvent(event: string): Promise { const pendingCompleted = this.completedEvents.get(event) || []; const pending = pendingCompleted.shift(); if (pending) { log.info(`CI: resolving pending result for ${event}`, pending); if (pendingCompleted.length === 0) { this.completedEvents.delete(event); } return pending; } log.info(`CI: waiting for event ${event}`); const { resolve, promise } = explodePromise(); let list = this.eventListeners.get(event); if (!list) { list = []; this.eventListeners.set(event, list); } list.push(resolve); return promise; } public setProvisioningURL(url: string): void { this.handleEvent('provisioning-url', url); } public handleEvent(event: string, data: unknown): void { const list = this.eventListeners.get(event) || []; const resolve = list.shift(); if (resolve) { if (list.length === 0) { this.eventListeners.delete(event); } log.info(`CI: got event ${event} with data`, data); resolve(data); return; } log.info(`CI: postponing event ${event}`); let resultList = this.completedEvents.get(event); if (!resultList) { resultList = []; this.completedEvents.set(event, resultList); } resultList.push(data); } }