UNPKG

@applitools/socket

Version:

Applitools implementation for bidi-communication protocol

228 lines (227 loc) 9.04 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeSocket = void 0; const logger_1 = require("@applitools/logger"); const transports = __importStar(require("./transports")); const utils = __importStar(require("@applitools/utils")); function makeSocket(target, options) { let ready = false; const listeners = new Map(); const queue = new Set(); const offs = new Set(); const transport = utils.types.isString(options.transport) ? transports[options.transport] : options.transport; const logger = (0, logger_1.makeLogger)({ logger: options.logger, format: { label: 'socket' }, maskLog: options.maskLog }); use(target); return { get ready() { return ready; }, get target() { return target; }, use, cleanup, emit, on, once, off, request, command, wait, }; function use(socket) { cleanup(); target = socket; const offError = transport.onError(target, async (error) => { const fns = listeners.get('error'); if (fns) { for (const fn of fns) { await fn(error); } } }); offs.add(offError); if (transport.isReady(target)) { attach(); } else { const offReady = transport.onReady(target, () => { attach(); const fns = listeners.get('ready'); if (fns) fns.forEach(fn => fn()); }); offs.add(offReady); } function attach() { ready = true; queue.forEach(command => command()); queue.clear(); const offMessage = transport.onMessage(target, message => { var _a, _b, _c, _d, _e, _f; const { name, key, payload } = deserialize(message); if ((_a = payload === null || payload === void 0 ? void 0 : payload.settings) === null || _a === void 0 ? void 0 : _a.apiKey) logger.mask(payload.settings.apiKey); if ((_b = payload === null || payload === void 0 ? void 0 : payload.settings) === null || _b === void 0 ? void 0 : _b.eyesServerUrl) logger.mask(payload.settings.eyesServerUrl); if ((_d = (_c = payload === null || payload === void 0 ? void 0 : payload.config) === null || _c === void 0 ? void 0 : _c.open) === null || _d === void 0 ? void 0 : _d.apiKey) logger.mask(payload.config.open.apiKey); if ((_f = (_e = payload === null || payload === void 0 ? void 0 : payload.config) === null || _e === void 0 ? void 0 : _e.open) === null || _f === void 0 ? void 0 : _f.eyesServerUrl) logger.mask(payload.config.open.eyesServerUrl); logger.log(`Received event of type ${JSON.stringify({ name, key })} with payload`, payload && JSON.stringify(payload, null, 4).slice(0, 5000)); const fns = listeners.get(name); if (fns) fns.forEach(fn => fn(payload, key)); if (key) { const fns = listeners.get(`${name}/${key}`); if (fns) fns.forEach(fn => fn(payload, key)); } }); offs.add(offMessage); const offClose = transport.onClose(target, () => { const fns = listeners.get('close'); if (fns) fns.forEach(fn => fn()); }); offs.add(offClose); } } function cleanup() { offs.forEach(off => off()); offs.clear(); } function emit(type, payload) { const command = () => { logger.log(`Emit event of type ${JSON.stringify(type)} with payload`, payload && JSON.stringify(payload, null, 4).slice(0, 5000)); transport.send(target, serialize(type, payload)); }; if (ready) command(); else queue.add(command); return () => queue.delete(command); } function on(type, fn) { const name = utils.types.isString(type) ? type : `${type.name}/${type.key}`; let fns = listeners.get(name); if (!fns) { fns = new Set(); listeners.set(name, fns); } fns.add(fn); return () => off(name, fn); } function once(type, fn) { const off = on(type, (...args) => (fn(...args), off())); return off; } function off(type, fn) { const name = utils.types.isString(type) ? type : `${type.name}/${type.key}`; if (!fn) return listeners.delete(name); const fns = listeners.get(name); if (!fns) return false; const existed = fns.delete(fn); if (!fns.size) listeners.delete(name); return existed; } function request(name, payload) { return new Promise((resolve, reject) => { const key = utils.general.guid(); once({ name, key }, response => { var _a; if (response.error) { const error = new Error(response.error.message); error.reason = (_a = response.error.reason) !== null && _a !== void 0 ? _a : 'unknown'; error.info = response.error.info; error.stack = response.error.stack; return reject(error); } return resolve(response.result); }); emit({ name, key }, payload); }); } function command(name, fn) { return on(name, async (payload, key) => { var _a, _b; try { const result = await fn(payload); emit({ name, key }, { result }); } catch (error) { emit({ name, key }, { error: { message: error.message, stack: error.stack, reason: (_a = error.reason) !== null && _a !== void 0 ? _a : 'internal', ...(_b = error.toJSON) === null || _b === void 0 ? void 0 : _b.call(error), }, }); } }); } function wait(name, fnOrOptions, options) { const result = utils.promises.makeControlledPromise(); let fn; if (utils.types.isFunction(fnOrOptions)) fn = fnOrOptions; else options = fnOrOptions; const off = on(name, async (payload) => { try { result.resolve((await (fn === null || fn === void 0 ? void 0 : fn(payload)))); } catch (error) { result.reject(error); } }); if (options === null || options === void 0 ? void 0 : options.timeout) { utils.general.sleep(options.timeout).then(() => { off(); result.reject(new Error(`Event with name "${name}" wasn't emitted within ${options.timeout}ms`)); }); } return { then: (onResolved, onRejected) => result.then(onResolved, onRejected), }; } function serialize(type, payload) { var _a, _b; const message = utils.types.isString(type) ? { name: type, payload } : { name: type.name, key: type.key, payload }; return (_b = (_a = transport.serialize) === null || _a === void 0 ? void 0 : _a.call(transport, message)) !== null && _b !== void 0 ? _b : message; } function deserialize(message) { var _a, _b; return (_b = (_a = transport.deserialize) === null || _a === void 0 ? void 0 : _a.call(transport, message)) !== null && _b !== void 0 ? _b : message; } } exports.makeSocket = makeSocket;