@applitools/socket
Version:
Applitools implementation for bidi-communication protocol
228 lines (227 loc) • 9.04 kB
JavaScript
;
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;