UNPKG

signalk-server

Version:

An implementation of a [Signal K](http://signalk.org) server for boats.

172 lines 6.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.startEvents = startEvents; exports.startServerEvents = startServerEvents; exports.wrapEmitter = wrapEmitter; const debug_1 = require("./debug"); function startEvents(app, spark, onEvent, eventsFromQuery = '') { const events = eventsFromQuery.split(','); events.forEach((event) => { app.on(event, (data) => onEvent({ event, data })); spark.onDisconnects.push(() => app.removeListener(event, onEvent)); }); } function startServerEvents(app, spark, onServerEvent) { app.on('serverevent', onServerEvent); spark.onDisconnects.push(() => { app.removeListener('serverevent', onServerEvent); }); try { spark.write({ type: 'VESSEL_INFO', data: { name: app.config.vesselName, mmsi: app.config.vesselMMSI, uuid: app.config.vesselUUID } }); } catch (e) { if (e.code !== 'ENOENT') { console.error(e); } } Object.keys(app.lastServerEvents).forEach((propName) => { spark.write(app.lastServerEvents[propName]); }); spark.write({ type: 'DEBUG_SETTINGS', data: app.logging.getDebugSettings() }); if (app.securityStrategy.canAuthorizeWS()) { spark.write({ type: 'RECEIVE_LOGIN_STATUS', data: app.securityStrategy.getLoginStatus(spark.request) }); } spark.write({ type: 'SOURCEPRIORITIES', data: app.config.settings.sourcePriorities || {} }); } function safeApply(handler, context, args) { try { Reflect.apply(handler, context, args); } catch (err) { // Throw error after timeout so as not to interrupt the stack setTimeout(() => { throw err; }); } } function arrayClone(arr) { const n = arr.length; const copy = new Array(n); for (let i = 0; i < n; i += 1) { copy[i] = arr[i]; } return copy; } function wrapEmitter(targetEmitter) { const targetAddListener = targetEmitter.addListener.bind(targetEmitter); const eventDebugs = {}; const eventsData = {}; let emittedCount = 0; function safeEmit(eventName, ...args) { if (eventName !== 'serverlog') { let eventDebug = eventDebugs[eventName]; if (!eventDebug) { eventDebugs[eventName] = eventDebug = (0, debug_1.createDebug)(`signalk-server:events:${eventName}`); } if (eventDebug.enabled) { //there is ever only one rest argument, outputting args results in a 1 element array eventDebug(args[0]); } } // from https://github.com/MetaMask/safe-event-emitter/blob/main/index.t let doError = eventName === 'error'; const events = targetEmitter._events; if (events !== undefined) { doError = doError && events.error === undefined; } else if (!doError) { return false; } // If there is no 'error' event listener then throw. if (doError) { let er; if (args.length > 0) { ; [er] = args; } if (er instanceof Error) { // Note: The comments on the `throw` lines are intentional, they show // up in Node's output if this results in an unhandled exception. throw er; // Unhandled 'error' event } // At least give some kind of context to the user const err = new Error(`Unhandled error.${er ? ` (${er.message})` : ''}`); err.context = er; throw err; // Unhandled 'error' event } const handler = events[eventName]; if (handler === undefined) { return false; } emittedCount++; if (typeof handler === 'function') { safeApply(handler, this, args); } else { const len = handler.length; const listeners = arrayClone(handler); for (let i = 0; i < len; i += 1) { safeApply(listeners[i], this, args); } } return true; } function emitWithEmitterId(emitterId, eventName, ...args) { const emittersForEvent = (eventsData[eventName] ?? (eventsData[eventName] = { emitters: {}, listeners: {} })).emitters; if (!emittersForEvent[emitterId]) { emittersForEvent[emitterId] = 0; } emittersForEvent[emitterId]++; safeEmit(`${emitterId}:${eventName}`, ...args); return safeEmit(eventName, ...args); } const addListenerWithId = function (listenerId, eventName, listener) { const listenersForEvent = (eventsData[eventName] ?? (eventsData[eventName] = { emitters: {}, listeners: {} })).listeners; if (!listenersForEvent[listenerId]) { listenersForEvent[listenerId] = true; } return targetAddListener(eventName, listener); }; return { getEmittedCount: () => emittedCount, getEventRoutingData: () => ({ events: Object.entries(eventsData).map(([event, data]) => ({ event, ...data })) }), emit: function (eventName, ...args) { return emitWithEmitterId('NO_EMITTER_ID', eventName, ...args); }, addListener: (eventName, listener) => addListenerWithId('NO_LISTENER_ID', eventName, listener), bindMethodsById: (actorId) => { const addListener = (eventName, listener) => addListenerWithId(actorId, eventName, listener); return { emit: function (eventName, ...args) { return emitWithEmitterId(actorId, eventName, ...args); }, addListener, on: addListener }; } }; } //# sourceMappingURL=events.js.map