const require_Action = require('./Action-CzhPMw2i.js'); let fs = require("fs"); fs = require_Action.__toESM(fs); let path = require("path"); path = require_Action.__toESM(path); let _module_federation_sdk = require("@module-federation/sdk"); let net = require("net"); net = require_Action.__toESM(net); let os = require("os"); os = require_Action.__toESM(os); let isomorphic_ws = require("isomorphic-ws"); isomorphic_ws = require_Action.__toESM(isomorphic_ws); let http = require("http"); let node_schedule = require("node-schedule"); node_schedule = require_Action.__toESM(node_schedule); let url = require("url"); //#region src/server/message/API/API.ts let APIKind = /* @__PURE__ */ function(APIKind) { APIKind["UPDATE_SUBSCRIBER"] = "UPDATE_SUBSCRIBER"; APIKind["RELOAD_WEB_CLIENT"] = "RELOAD_WEB_CLIENT"; APIKind["FETCH_TYPES"] = "FETCH_TYPES"; return APIKind; }({}); var API = class extends require_Action.Message { constructor(content, kind) { super("API", kind); const { code, payload } = content; this.code = code; this.payload = payload; } }; //#endregion //#region src/server/message/API/UpdateSubscriber.ts var UpdateSubscriberAPI = class extends API { constructor(payload) { super({ code: 0, payload }, APIKind.UPDATE_SUBSCRIBER); } }; //#endregion //#region src/server/message/API/ReloadWebClient.ts var ReloadWebClientAPI = class extends API { constructor(payload) { super({ code: 0, payload }, APIKind.RELOAD_WEB_CLIENT); } }; //#endregion //#region src/server/message/API/FetchTypes.ts var FetchTypesAPI = class extends API { constructor(payload) { super({ code: 0, payload }, APIKind.FETCH_TYPES); } }; //#endregion //#region src/server/message/Log/Log.ts let LogLevel = /* @__PURE__ */ function(LogLevel) { LogLevel["LOG"] = "LOG"; LogLevel["WARN"] = "WARN"; LogLevel["ERROR"] = "ERROR"; return LogLevel; }({}); let LogKind = /* @__PURE__ */ function(LogKind) { LogKind["BrokerExitLog"] = "BrokerExitLog"; LogKind["PublisherRegisteredLog"] = "PublisherRegisteredLog"; return LogKind; }({}); var Log = class extends require_Action.Message { constructor(level, kind, ignoreVerbose = false) { super("Log", kind); this.ignoreVerbose = false; this.level = level; this.ignoreVerbose = ignoreVerbose; } }; //#endregion //#region src/server/message/Log/BrokerExitLog.ts var BrokerExitLog = class extends Log { constructor() { super(LogLevel.LOG, LogKind.BrokerExitLog); } }; //#endregion //#region src/server/utils/log.ts const logger = (0, _module_federation_sdk.createLogger)(`[ ${require_Action.MF_SERVER_IDENTIFIER} ]`); function fileLog(msg, module, level) { if (!process?.env?.["FEDERATION_DEBUG"]) return; try { const logDir = ".mf"; const logFile = path.join(logDir, "typesGenerate.log"); const timestamp = (/* @__PURE__ */ new Date()).toISOString(); if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true }); fs.appendFileSync(logFile, `[${timestamp}] [${level.toUpperCase()}] ${module} - ${msg}\n`); } catch {} } function error(error, action, from) { const err = error instanceof Error ? error : /* @__PURE__ */ new Error(`${action} error`); fileLog(`[${action}] error: ${err}`, from, "fatal"); return err.toString(); } //#endregion //#region src/server/utils/getIPV4.ts const localIpv4 = "127.0.0.1"; const getIpv4Interfaces = () => { try { const interfaces = os.default.networkInterfaces(); const ipv4Interfaces = []; Object.values(interfaces).forEach((detail) => { detail?.forEach((detail) => { const familyV4Value = typeof detail.family === "string" ? "IPv4" : 4; if (detail.family === familyV4Value && detail.address !== localIpv4) ipv4Interfaces.push(detail); }); }); return ipv4Interfaces; } catch (_err) { return []; } }; const getIPV4 = () => { return (getIpv4Interfaces()[0] || { address: localIpv4 }).address; }; //#endregion //#region src/server/utils/index.ts function getIdentifier(options) { const { ip, name } = options; return `mf ${_module_federation_sdk.SEPARATOR}${name}${ip ? `${_module_federation_sdk.SEPARATOR}${ip}` : ""}`; } function fib(n) { let i = 2; const res = [ 0, 1, 1 ]; while (i <= n) { res[i] = res[i - 1] + res[i - 2]; i++; } return res[n]; } function getFreePort() { return new Promise((resolve, reject) => { const server = net.default.createServer(); server.unref(); server.on("error", reject); server.listen(0, () => { const { port } = server.address(); server.close(() => { resolve(port); }); }); }); } //#endregion //#region src/server/Publisher.ts var Publisher = class { constructor(ctx) { this._name = ctx.name; this._ip = ctx.ip; this._remoteTypeTarPath = ctx.remoteTypeTarPath; this._subscribers = /* @__PURE__ */ new Map(); this._ws = ctx.ws; this.dynamicRemoteMap = /* @__PURE__ */ new Map(); } get identifier() { return getIdentifier({ name: this._name, ip: this._ip }); } get name() { return this._name; } get ip() { return this._ip; } get remoteTypeTarPath() { return this._remoteTypeTarPath; } get hasSubscribes() { return Boolean(this._subscribers.size); } get subscribers() { return this._subscribers; } addSubscriber(identifier, subscriber) { fileLog(`${this.name} set subscriber: ${identifier}`, "Publisher", "info"); this._subscribers.set(identifier, subscriber); } removeSubscriber(identifier) { if (this._subscribers.has(identifier)) { fileLog(`${this.name} removeSubscriber: ${identifier}`, "Publisher", "warn"); this._subscribers.delete(identifier); } } notifySubscriber(subscriberIdentifier, options) { const subscriber = this._subscribers.get(subscriberIdentifier); if (!subscriber) { fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${subscriberIdentifier}, does not exits`, "Publisher", "error"); return; } const api = new UpdateSubscriberAPI(options); subscriber.send(JSON.stringify(api)); fileLog(`[notifySubscriber] ${this.name} notifySubscriber: ${JSON.stringify(subscriberIdentifier)}, message: ${JSON.stringify(api)}`, "Publisher", "info"); } fetchRemoteTypes(options) { fileLog(`[fetchRemoteTypes] ${this.name} fetchRemoteTypes, options: ${JSON.stringify(options)}, ws: ${Boolean(this._ws)}`, "Publisher", "info"); if (!this._ws) return; const api = new FetchTypesAPI(options); this._ws.send(JSON.stringify(api)); } notifySubscribers(options) { const api = new UpdateSubscriberAPI(options); this.broadcast(api); } broadcast(message) { if (this.hasSubscribes) this._subscribers.forEach((subscriber, key) => { fileLog(`[BroadCast] ${this.name} notifySubscriber: ${key}, PID: ${process.pid}, message: ${JSON.stringify(message)}`, "Publisher", "info"); subscriber.send(JSON.stringify(message)); }); else fileLog(`[BroadCast] ${this.name}'s subscribe is empty`, "Publisher", "warn"); } close() { this._ws = void 0; this._subscribers.forEach((_subscriber, identifier) => { fileLog(`[BroadCast] close ${this.name} remove: ${identifier}`, "Publisher", "warn"); this.removeSubscriber(identifier); }); } }; //#endregion //#region src/server/message/Action/Update.ts let UpdateKind = /* @__PURE__ */ function(UpdateKind) { UpdateKind["UPDATE_TYPE"] = "UPDATE_TYPE"; UpdateKind["RELOAD_PAGE"] = "RELOAD_PAGE"; return UpdateKind; }({}); //#endregion //#region src/server/broker/Broker.ts var Broker = class Broker { static { this.WEB_SOCKET_CONNECT_MAGIC_ID = require_Action.WEB_SOCKET_CONNECT_MAGIC_ID; } static { this.DEFAULT_WEB_SOCKET_PORT = require_Action.DEFAULT_WEB_SOCKET_PORT; } static { this.DEFAULT_SECURE_WEB_SOCKET_PORT = 16324; } static { this.DEFAULT_WAITING_TIME = 1.5 * 60 * 60 * 1e3; } constructor() { this._publisherMap = /* @__PURE__ */ new Map(); this._webClientMap = /* @__PURE__ */ new Map(); this._tmpSubscriberShelter = /* @__PURE__ */ new Map(); this._scheduleJob = null; this._setSchedule(); this._startWsServer(); this._stopWhenSIGTERMOrSIGINT(); this._handleUnexpectedExit(); } get hasPublishers() { return Boolean(this._publisherMap.size); } async _startWsServer() { const wsHandler = (ws, req) => { const { url: reqUrl = "" } = req; const { query } = (0, url.parse)(reqUrl, true); const { WEB_SOCKET_CONNECT_MAGIC_ID } = query; if (WEB_SOCKET_CONNECT_MAGIC_ID === Broker.WEB_SOCKET_CONNECT_MAGIC_ID) { ws.on("message", (message) => { try { const text = message.toString(); const action = JSON.parse(text); fileLog(`${action?.kind} action received `, "Broker", "info"); this._takeAction(action, ws); } catch (error) { fileLog(`parse action message error: ${error}`, "Broker", "error"); } }); ws.on("error", (e) => { fileLog(`parse action message error: ${e}`, "Broker", "error"); }); } else { ws.send("Invalid CONNECT ID."); fileLog("Invalid CONNECT ID.", "Broker", "warn"); ws.close(); } }; const server = (0, http.createServer)(); this._webSocketServer = new isomorphic_ws.default.Server({ noServer: true }); this._webSocketServer.on("error", (err) => { fileLog(`ws error: \n${err.message}\n ${err.stack}`, "Broker", "error"); }); this._webSocketServer.on("listening", () => { fileLog(`WebSocket server is listening on port ${Broker.DEFAULT_WEB_SOCKET_PORT}`, "Broker", "info"); }); this._webSocketServer.on("connection", wsHandler); this._webSocketServer.on("close", (code) => { fileLog(`WebSocket Server Close with Code ${code}`, "Broker", "warn"); this._webSocketServer && this._webSocketServer.close(); this._webSocketServer = void 0; }); server.on("upgrade", (req, socket, head) => { if (req.url) { const { pathname } = (0, url.parse)(req.url); if (pathname === "/") this._webSocketServer?.handleUpgrade(req, socket, head, (ws) => { this._webSocketServer?.emit("connection", ws, req); }); } }); server.listen(Broker.DEFAULT_WEB_SOCKET_PORT); } async _takeAction(action, client) { const { kind, payload } = action; if (kind === require_Action.ActionKind.ADD_PUBLISHER) await this._addPublisher(payload, client); if (kind === require_Action.ActionKind.UPDATE_PUBLISHER) await this._updatePublisher(payload, client); if (kind === require_Action.ActionKind.ADD_SUBSCRIBER) await this._addSubscriber(payload, client); if (kind === require_Action.ActionKind.EXIT_SUBSCRIBER) await this._removeSubscriber(payload, client); if (kind === require_Action.ActionKind.EXIT_PUBLISHER) await this._removePublisher(payload, client); if (kind === require_Action.ActionKind.ADD_WEB_CLIENT) await this._addWebClient(payload, client); if (kind === require_Action.ActionKind.NOTIFY_WEB_CLIENT) await this._notifyWebClient(payload, client); if (kind === require_Action.ActionKind.FETCH_TYPES) await this._fetchTypes(payload, client); if (kind === require_Action.ActionKind.ADD_DYNAMIC_REMOTE) this._addDynamicRemote(payload); } async _addPublisher(context, client) { const { name, ip, remoteTypeTarPath } = context ?? {}; const identifier = getIdentifier({ name, ip }); if (this._publisherMap.has(identifier)) { fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] ${identifier} has been added, this action will be ignored`, "Broker", "warn"); return; } try { const publisher = new Publisher({ name, ip, remoteTypeTarPath, ws: client }); this._publisherMap.set(identifier, publisher); fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] ${identifier} Adding Publisher Succeed`, "Broker", "info"); const tmpSubScribers = this._getTmpSubScribers(identifier); if (tmpSubScribers) { fileLog(`[${require_Action.ActionKind.ADD_PUBLISHER}] consumeTmpSubscriber set ${publisher.name}’s subscribers `, "Broker", "info"); this._consumeTmpSubScribers(publisher, tmpSubScribers); this._clearTmpSubScriberRelation(identifier); } } catch (err) { const msg = error(err, require_Action.ActionKind.ADD_PUBLISHER, "Broker"); client.send(msg); client.close(); } } async _updatePublisher(context, client) { const { name, updateMode, updateKind, updateSourcePaths, remoteTypeTarPath, ip } = context ?? {}; const identifier = getIdentifier({ name, ip }); if (!this._publisherMap.has(identifier)) { fileLog(`[${require_Action.ActionKind.UPDATE_PUBLISHER}] ${identifier} has not been started, this action will be ignored this._publisherMap: ${JSON.stringify(this._publisherMap.entries())} `, "Broker", "warn"); return; } try { const publisher = this._publisherMap.get(identifier); fileLog(`[${require_Action.ActionKind.UPDATE_PUBLISHER}] ${identifier} update, and notify subscribers to update`, "Broker", "info"); if (publisher) { publisher.notifySubscribers({ remoteTypeTarPath, name, updateMode, updateKind, updateSourcePaths: updateSourcePaths || [] }); this._publisherMap.forEach((p) => { if (p.name === publisher.name) return; const dynamicRemoteInfo = p.dynamicRemoteMap.get(identifier); if (dynamicRemoteInfo) { fileLog(`dynamicRemoteInfo: ${JSON.stringify(dynamicRemoteInfo)}, identifier:${identifier} publish: ${p.name}`, "Broker", "info"); p.fetchRemoteTypes({ remoteInfo: dynamicRemoteInfo, once: false }); } }); } } catch (err) { const msg = error(err, require_Action.ActionKind.UPDATE_PUBLISHER, "Broker"); client.send(msg); client.close(); } } async _fetchTypes(context, _client) { const { name, ip, remoteInfo } = context ?? {}; const identifier = getIdentifier({ name, ip }); try { const publisher = this._publisherMap.get(identifier); fileLog(`[${require_Action.ActionKind.FETCH_TYPES}] ${identifier} fetch types`, "Broker", "info"); if (publisher) publisher.fetchRemoteTypes({ remoteInfo, once: true }); } catch (err) { fileLog(`[${require_Action.ActionKind.FETCH_TYPES}] ${identifier} fetch types fail , error info: ${err}`, "Broker", "error"); } } _addDynamicRemote(context) { const { name, ip, remoteInfo, remoteIp } = context ?? {}; const identifier = getIdentifier({ name, ip }); const publisher = this._publisherMap.get(identifier); const remoteId = getIdentifier({ name: remoteInfo.name, ip: remoteIp }); fileLog(`[${require_Action.ActionKind.ADD_DYNAMIC_REMOTE}] identifier:${identifier},publisher: ${publisher.name}, remoteId:${remoteId}`, "Broker", "error"); if (!publisher || publisher.dynamicRemoteMap.has(remoteId)) return; publisher.dynamicRemoteMap.set(remoteId, remoteInfo); } async _addSubscriber(context, client) { const { publishers, name: subscriberName } = context ?? {}; publishers.forEach((publisher) => { const { name, ip } = publisher; const identifier = getIdentifier({ name, ip }); if (!this._publisherMap.has(identifier)) { fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: ${identifier} has not been started, ${subscriberName} will add the relation to tmp shelter`, "Broker", "warn"); this._addTmpSubScriberRelation({ name: getIdentifier({ name: context.name, ip: context.ip }), client }, publisher); return; } try { const registeredPublisher = this._publisherMap.get(identifier); if (registeredPublisher) { registeredPublisher.addSubscriber(getIdentifier({ name: subscriberName, ip: context.ip }), client); fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: ${identifier} has been started, Adding Subscriber ${subscriberName} Succeed, this.__publisherMap are: ${JSON.stringify(Array.from(this._publisherMap.entries()))}`, "Broker", "info"); registeredPublisher.notifySubscriber(getIdentifier({ name: subscriberName, ip: context.ip }), { updateKind: UpdateKind.UPDATE_TYPE, updateMode: require_Action.UpdateMode.PASSIVE, updateSourcePaths: [registeredPublisher.name], remoteTypeTarPath: registeredPublisher.remoteTypeTarPath, name: registeredPublisher.name }); fileLog(`[${require_Action.ActionKind.ADD_SUBSCRIBER}]: notifySubscriber Subscriber ${subscriberName}, updateMode: "PASSIVE", updateSourcePaths: ${registeredPublisher.name}`, "Broker", "info"); } } catch (err) { const msg = error(err, require_Action.ActionKind.ADD_SUBSCRIBER, "Broker"); client.send(msg); client.close(); } }); } async _removeSubscriber(context, client) { const { publishers } = context ?? {}; const subscriberIdentifier = getIdentifier({ name: context?.name, ip: context?.ip }); publishers.forEach((publisher) => { const { name, ip } = publisher; const identifier = getIdentifier({ name, ip }); const registeredPublisher = this._publisherMap.get(identifier); if (!registeredPublisher) { fileLog(`[${require_Action.ActionKind.EXIT_SUBSCRIBER}], ${identifier} does not exit `, "Broker", "warn"); return; } try { fileLog(`[${require_Action.ActionKind.EXIT_SUBSCRIBER}], ${identifier} will exit `, "Broker", "INFO"); registeredPublisher.removeSubscriber(subscriberIdentifier); this._clearTmpSubScriberRelation(identifier); if (!registeredPublisher.hasSubscribes) this._publisherMap.delete(identifier); if (!this.hasPublishers) this.exit(); } catch (err) { const msg = error(err, require_Action.ActionKind.EXIT_SUBSCRIBER, "Broker"); client.send(msg); client.close(); } }); } async _removePublisher(context, client) { const { name, ip } = context ?? {}; const identifier = getIdentifier({ name, ip }); const publisher = this._publisherMap.get(identifier); if (!publisher) { fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier}} has not been added, this action will be ingored`, "Broker", "warn"); return; } try { const { subscribers } = publisher; subscribers.forEach((subscriber, subscriberIdentifier) => { this._addTmpSubScriberRelation({ name: subscriberIdentifier, client: subscriber }, { name: publisher.name, ip: publisher.ip }); fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier} is removing , subscriber: ${subscriberIdentifier} will be add tmpSubScriberRelation`, "Broker", "info"); }); this._publisherMap.delete(identifier); fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: ${identifier} is removed `, "Broker", "info"); if (!this.hasPublishers) { fileLog(`[${require_Action.ActionKind.EXIT_PUBLISHER}]: _publisherMap is empty, all server will exit `, "Broker", "warn"); this.exit(); } } catch (err) { const msg = error(err, require_Action.ActionKind.EXIT_PUBLISHER, "Broker"); client.send(msg); client.close(); } } async _addWebClient(context, client) { const { name } = context ?? {}; const identifier = getIdentifier({ name }); if (this._webClientMap.has(identifier)) fileLog(`${identifier}} has been added, this action will override prev WebClient`, "Broker", "warn"); try { this._webClientMap.set(identifier, client); fileLog(`${identifier} adding WebClient Succeed`, "Broker", "info"); } catch (err) { const msg = error(err, require_Action.ActionKind.ADD_WEB_CLIENT, "Broker"); client.send(msg); client.close(); } } async _notifyWebClient(context, client) { const { name, updateMode } = context ?? {}; const identifier = getIdentifier({ name }); const webClient = this._webClientMap.get(identifier); if (!webClient) { fileLog(`[${require_Action.ActionKind.NOTIFY_WEB_CLIENT}] ${identifier} has not been added, this action will be ignored`, "Broker", "warn"); return; } try { const api = new ReloadWebClientAPI({ name, updateMode }); webClient.send(JSON.stringify(api)); fileLog(`[${require_Action.ActionKind.NOTIFY_WEB_CLIENT}] Notify ${name} WebClient Succeed`, "Broker", "info"); } catch (err) { const msg = error(err, require_Action.ActionKind.NOTIFY_WEB_CLIENT, "Broker"); client.send(msg); client.close(); } } _addTmpSubScriberRelation(subscriber, publisher) { const publisherIdentifier = getIdentifier({ name: publisher.name, ip: publisher.ip }); const subscriberIdentifier = subscriber.name; const shelter = this._tmpSubscriberShelter.get(publisherIdentifier); if (!shelter) { const map = /* @__PURE__ */ new Map(); map.set(subscriberIdentifier, subscriber); this._tmpSubscriberShelter.set(publisherIdentifier, { subscribers: map, timestamp: Date.now() }); fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier}'s subscriber has ${subscriberIdentifier} `, "Broker", "info"); return; } if (shelter.subscribers.get(subscriberIdentifier)) { fileLog(`[AddTmpSubscriberRelation] ${publisherIdentifier} and ${subscriberIdentifier} relation has been added`, "Broker", "warn"); shelter.subscribers.set(subscriberIdentifier, subscriber); shelter.timestamp = Date.now(); } else { fileLog(`AddTmpSubscriberLog ${publisherIdentifier}'s shelter has been added, update shelter.subscribers ${subscriberIdentifier}`, "Broker", "warn"); shelter.subscribers.set(subscriberIdentifier, subscriber); } } _getTmpSubScribers(publisherIdentifier) { return this._tmpSubscriberShelter.get(publisherIdentifier)?.subscribers; } _consumeTmpSubScribers(publisher, tmpSubScribers) { tmpSubScribers.forEach((tmpSubScriber, identifier) => { fileLog(`notifyTmpSubScribers ${publisher.name} will be add a subscriber: ${identifier} `, "Broker", "warn"); publisher.addSubscriber(identifier, tmpSubScriber.client); publisher.notifySubscriber(identifier, { updateKind: UpdateKind.UPDATE_TYPE, updateMode: require_Action.UpdateMode.PASSIVE, updateSourcePaths: [publisher.name], remoteTypeTarPath: publisher.remoteTypeTarPath, name: publisher.name }); }); } _clearTmpSubScriberRelation(identifier) { this._tmpSubscriberShelter.delete(identifier); } _clearTmpSubScriberRelations() { this._tmpSubscriberShelter.clear(); } _disconnect() { this._publisherMap.forEach((publisher) => { publisher.close(); }); } _setSchedule() { const rule = new node_schedule.default.RecurrenceRule(); if (Number(process.env["FEDERATION_SERVER_TEST"])) { const interval = Number(process.env["FEDERATION_SERVER_TEST"]) / 1e3; const second = []; for (let i = 0; i < 60; i = i + interval) second.push(i); rule.second = second; } else { rule.second = 0; rule.hour = [ 0, 3, 6, 9, 12, 15, 18 ]; rule.minute = 0; } const serverTest = Number(process.env["FEDERATION_SERVER_TEST"]); this._scheduleJob = node_schedule.default.scheduleJob(rule, () => { this._tmpSubscriberShelter.forEach((tmpSubscriber, identifier) => { fileLog(` _clearTmpSubScriberRelation ${identifier}, ${Date.now() - tmpSubscriber.timestamp >= (process.env["GARFISH_MODULE_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)}`, "Broker", "info"); if (Date.now() - tmpSubscriber.timestamp >= (process.env["FEDERATION_SERVER_TEST"] ? serverTest : Broker.DEFAULT_WAITING_TIME)) this._clearTmpSubScriberRelation(identifier); }); }); } _clearSchedule() { if (!this._scheduleJob) return; this._scheduleJob.cancel(); this._scheduleJob = null; } _stopWhenSIGTERMOrSIGINT() { process.on("SIGTERM", () => { this.exit(); }); process.on("SIGINT", () => { this.exit(); }); } _handleUnexpectedExit() { process.on("unhandledRejection", (error) => { console.error("Unhandled Rejection Error: ", error); fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal"); process.exit(1); }); process.on("uncaughtException", (error) => { console.error("Unhandled Exception Error: ", error); fileLog(`Unhandled Rejection Error: ${error}`, "Broker", "fatal"); process.exit(1); }); } async start() {} exit() { const brokerExitLog = new BrokerExitLog(); this.broadcast(JSON.stringify(brokerExitLog)); this._disconnect(); this._clearSchedule(); this._clearTmpSubScriberRelations(); this._webSocketServer && this._webSocketServer.close(); this._secureWebSocketServer && this._secureWebSocketServer.close(); process.exit(0); } broadcast(message) { fileLog(`[broadcast] exit info : ${JSON.stringify(message)}`, "Broker", "warn"); this._webSocketServer?.clients.forEach((client) => { client.send(JSON.stringify(message)); }); this._secureWebSocketServer?.clients.forEach((client) => { client.send(JSON.stringify(message)); }); } }; //#endregion Object.defineProperty(exports, 'APIKind', { enumerable: true, get: function () { return APIKind; } }); Object.defineProperty(exports, 'Broker', { enumerable: true, get: function () { return Broker; } }); Object.defineProperty(exports, 'LogKind', { enumerable: true, get: function () { return LogKind; } }); Object.defineProperty(exports, 'UpdateKind', { enumerable: true, get: function () { return UpdateKind; } }); Object.defineProperty(exports, 'fib', { enumerable: true, get: function () { return fib; } }); Object.defineProperty(exports, 'fileLog', { enumerable: true, get: function () { return fileLog; } }); Object.defineProperty(exports, 'getFreePort', { enumerable: true, get: function () { return getFreePort; } }); Object.defineProperty(exports, 'getIPV4', { enumerable: true, get: function () { return getIPV4; } }); Object.defineProperty(exports, 'getIdentifier', { enumerable: true, get: function () { return getIdentifier; } }); Object.defineProperty(exports, 'logger', { enumerable: true, get: function () { return logger; } });