/** * * Agora Real Time Engagement * Created by Wei Hu in 2021-09. * Copyright (c) 2022 Agora IO. All rights reserved. * */ import * as fs from 'fs'; import * as log from '../common/logger'; import { MetadataInfo } from '../metadata/metadata'; import { RTE } from '../rte/rte'; import rte_addon from '../rte_addon'; type CloseCbType = ((rte: RTE) => void | Promise) | undefined; export class App { constructor(isDefault = false, closeCb: CloseCbType = undefined) { rte_addon.rte_nodejs_app_create(this, isDefault); this.#closeCb = closeCb; } private async _onInit( rte: RTE, manifest: MetadataInfo, property: MetadataInfo, ): Promise { try { await this.onInit(rte, manifest, property); } catch (e) { log.error(`App onInit throws an exception: ${e}`); } finally { // Notify RTE runtime that app::onInit is completed. rte_addon.rte_nodejs_rte_on_init_done(rte, manifest, property); } } async onInit( _rte: RTE, _manifest: MetadataInfo, _property: MetadataInfo, ): Promise { // Stub for override. } private async _onClose(rte: RTE): Promise { try { await this.onClose(rte); } catch (e) { log.error(`App onClose throws an exception: ${e}`); } finally { // Notify RTE runtime that app::onClose is completed. rte_addon.rte_nodejs_rte_on_deinit_done(rte); // JS app prepare to be destroyed. rte_addon.rte_nodejs_app_deinit(this); } } async onClose(rte: RTE): Promise { if (this.#closeCb) { await this.#closeCb(rte); } } run(): void { if (rte_addon.rte_nodejs_addon_is_ready()) { rte_addon.rte_nodejs_app_run(this); return; } // Postpone the running of the app until all the extensions complete // their on_addon_init(). const intervalId = setInterval(() => { if (rte_addon.rte_nodejs_addon_is_ready()) { clearInterval(intervalId); rte_addon.rte_nodejs_app_run(this); } }, 20); } stop(): void { rte_addon.rte_nodejs_app_stop(this); } wait(): void { rte_addon.rte_nodejs_app_wait(this); } #closeCb: CloseCbType; } /** * This is a convenient function that enables users to setup app property * _before_ creating a app instance. That's why this function resides outside * the App class. */ export function setAppProp( appRoot: string, property: Record, ): void { const data = fs.readFileSync(`${appRoot}/property.json`, 'utf8'); let property_json = JSON.parse(data); property_json = { ...property_json, ...property }; fs.writeFileSync(`${appRoot}/property.json`, JSON.stringify(property_json)); }