Socket
Socket
Sign inDemoInstall

@push-rpc/core

Package Overview
Dependencies
Maintainers
1
Versions
62
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@push-rpc/core - npm Package Compare versions

Comparing version 1.7.1 to 1.8.0

2

dist/client.d.ts

@@ -51,4 +51,4 @@ import { RpcSession } from "./RpcSession";

*/
connectionLoop(): Promise<unknown>;
connectionLoop(): Promise<void>;
}
export declare function createRpcClient<R = any>(createSocket: () => Promise<Socket>, options?: Partial<RpcClientOptions>): Promise<RpcClient<R>>;
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRpcClient = exports.RpcClient = void 0;
var RpcSession_1 = require("./RpcSession");
var logger_1 = require("./logger");
var utils_1 = require("./utils");
var defaultOptions = {
const RpcSession_1 = require("./RpcSession");
const logger_1 = require("./logger");
const utils_1 = require("./utils");
const defaultOptions = {
local: {},
listeners: {
connected: function () { },
disconnected: function () { },
messageIn: function () { },
messageOut: function () { },
subscribed: function () { },
unsubscribed: function () { },
connected: () => { },
disconnected: () => { },
messageIn: () => { },
messageOut: () => { },
subscribed: () => { },
unsubscribed: () => { },
},

@@ -67,6 +20,6 @@ reconnect: false,

errorDelayMaxDuration: 15 * 1000,
createContext: function () { return ({ remoteId: null }); },
localMiddleware: function (ctx, next, params, messageType) { return next(params); },
remoteMiddleware: function (ctx, next, params, messageType) { return next(params); },
messageParser: function (data) { return JSON.parse(data, utils_1.dateReviver); },
createContext: () => ({ remoteId: null }),
localMiddleware: (ctx, next, params, messageType) => next(params),
remoteMiddleware: (ctx, next, params, messageType) => next(params),
messageParser: data => JSON.parse(data, utils_1.dateReviver),
pingSendTimeout: null,

@@ -79,4 +32,4 @@ keepAliveTimeout: null,

};
var RpcClient = /** @class */ (function () {
function RpcClient(session, createSocket, opts) {
class RpcClient {
constructor(session, createSocket, opts) {
this.session = session;

@@ -88,16 +41,6 @@ this.createSocket = createSocket;

}
RpcClient.prototype.disconnect = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
this.disconnectedMark = true;
return [4 /*yield*/, this.session.disconnect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
async disconnect() {
this.disconnectedMark = true;
await this.session.disconnect();
}
/**

@@ -108,66 +51,49 @@ * Connect this to server

*/
RpcClient.prototype.connect = function (onDisconnected) {
if (onDisconnected === void 0) { onDisconnected = function () { }; }
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var socket_1, connected_1, timer, e_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.createSocket()];
case 1:
socket_1 = _a.sent();
connected_1 = false;
if (this.opts.connectionTimeout) {
timer = setTimeout(function () {
if (!connected_1) {
socket_1.disconnect();
reject(new Error("Connection timeout"));
}
}, this.opts.connectionTimeout);
if (timer.unref) {
timer.unref();
}
}
socket_1.onOpen(function () {
connected_1 = true;
utils_1.safeListener(function () { return _this.opts.listeners.connected(); });
_this.session.open(socket_1);
resolve();
});
socket_1.onDisconnected(function (code, reason) {
_this.session.handleDisconnected();
if (connected_1) {
onDisconnected();
utils_1.safeListener(function () { return _this.opts.listeners.disconnected({ code: code, reason: reason }); });
}
});
socket_1.onError(function (e) {
if (!connected_1) {
reject(e);
}
logger_1.log.warn("RPC connection error", e.message);
try {
socket_1.disconnect();
}
catch (e) {
// ignore
}
});
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
reject(e_1);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); })];
});
async connect(onDisconnected = () => { }) {
return new Promise(async (resolve, reject) => {
try {
const socket = await this.createSocket();
let connected = false;
if (this.opts.connectionTimeout) {
const timer = setTimeout(() => {
if (!connected) {
socket.disconnect();
reject(new Error("Connection timeout"));
}
}, this.opts.connectionTimeout);
if (timer.unref) {
timer.unref();
}
}
socket.onOpen(() => {
connected = true;
(0, utils_1.safeListener)(() => this.opts.listeners.connected());
this.session.open(socket);
resolve();
});
socket.onDisconnected((code, reason) => {
this.session.handleDisconnected();
if (connected) {
onDisconnected();
(0, utils_1.safeListener)(() => this.opts.listeners.disconnected({ code, reason }));
}
});
socket.onError(e => {
if (!connected) {
reject(e);
}
logger_1.log.warn("RPC connection error", e.message);
try {
socket.disconnect();
}
catch (e) {
// ignore
}
});
}
catch (e) {
reject(e);
}
});
};
}
/**

@@ -178,80 +104,51 @@ * Connect to the server, on each disconnect try to disconnect.

*/
RpcClient.prototype.connectionLoop = function () {
var _this = this;
return new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () {
var onFirstConnection, errorDelay;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
onFirstConnection = resolve;
connectionLoop() {
return new Promise(async (resolve) => {
let onFirstConnection = resolve;
let errorDelay = 0;
while (true) {
// connect, and wait for ...
await new Promise(resolve => {
// 1. ...disconnected
const connectionPromise = this.connect(resolve);
connectionPromise.then(() => {
// first reconnect after successful connection is done without delay
errorDelay = 0;
_a.label = 1;
case 1:
if (!true) return [3 /*break*/, 4];
// connect, and wait for ...
return [4 /*yield*/, new Promise(function (resolve) {
// 1. ...disconnected
var connectionPromise = _this.connect(resolve);
connectionPromise.then(function () {
// first reconnect after successful connection is done without delay
errorDelay = 0;
// signal about first connection
onFirstConnection();
onFirstConnection = function () { };
}, function () {
// 2. ... unable to establish connection
resolve();
});
})];
case 2:
// connect, and wait for ...
_a.sent();
if (this.disconnectedMark) {
return [2 /*return*/];
}
return [4 /*yield*/, new Promise(function (r) {
setTimeout(r, _this.opts.reconnectDelay + errorDelay);
})];
case 3:
_a.sent();
errorDelay = Math.round(Math.random() * this.opts.errorDelayMaxDuration);
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
// signal about first connection
onFirstConnection();
onFirstConnection = () => { };
}, () => {
// 2. ... unable to establish connection
resolve();
});
});
if (this.disconnectedMark) {
return;
}
});
}); });
};
return RpcClient;
}());
exports.RpcClient = RpcClient;
function createRpcClient(createSocket, options) {
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var opts, session, client;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
opts = __assign(__assign({}, defaultOptions), options);
session = new RpcSession_1.RpcSession(opts.local, {
messageIn: function (data) { return utils_1.safeListener(function () { return opts.listeners.messageIn(data); }); },
messageOut: function (data) { return utils_1.safeListener(function () { return opts.listeners.messageOut(data); }); },
subscribed: function (subs) { return utils_1.safeListener(function () { return opts.listeners.subscribed(subs); }); },
unsubscribed: function (subs) { return utils_1.safeListener(function () { return opts.listeners.unsubscribed(subs); }); },
}, opts.createContext(), opts.localMiddleware, opts.remoteMiddleware, opts.messageParser, opts.pingSendTimeout, opts.keepAliveTimeout, opts.callTimeout, opts.syncRemoteCalls, opts.delayCalls);
client = new RpcClient(session, createSocket, opts);
if (!opts.reconnect) return [3 /*break*/, 2];
return [4 /*yield*/, client.connectionLoop()];
case 1:
_a.sent();
return [3 /*break*/, 4];
case 2: return [4 /*yield*/, client.connect()];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/, client];
await new Promise(r => {
setTimeout(r, this.opts.reconnectDelay + errorDelay);
});
errorDelay = Math.round(Math.random() * this.opts.errorDelayMaxDuration);
}
});
});
}
}
exports.RpcClient = RpcClient;
async function createRpcClient(createSocket, options = {}) {
const opts = { ...defaultOptions, ...options };
const session = new RpcSession_1.RpcSession(opts.local, {
messageIn: data => (0, utils_1.safeListener)(() => opts.listeners.messageIn(data)),
messageOut: data => (0, utils_1.safeListener)(() => opts.listeners.messageOut(data)),
subscribed: subs => (0, utils_1.safeListener)(() => opts.listeners.subscribed(subs)),
unsubscribed: subs => (0, utils_1.safeListener)(() => opts.listeners.unsubscribed(subs)),
}, opts.createContext(), opts.localMiddleware, opts.remoteMiddleware, opts.messageParser, opts.pingSendTimeout, opts.keepAliveTimeout, opts.callTimeout, opts.syncRemoteCalls, opts.delayCalls);
const client = new RpcClient(session, createSocket, opts);
if (opts.reconnect) {
await client.connectionLoop();
}
else {
await client.connect();
}
return client;
}
exports.createRpcClient = createRpcClient;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PONG_MESSAGE = exports.PING_MESSAGE = exports.createDomWebsocket = exports.mapTopic = exports.setCreateMessageId = exports.createMessageId = exports.composeMiddleware = exports.dateReviver = exports.setLogger = exports.createRpcServer = exports.RpcClient = exports.createRpcClient = exports.LocalTopicImpl = exports.MessageType = void 0;
var rpc_1 = require("./rpc");

@@ -4,0 +5,0 @@ Object.defineProperty(exports, "MessageType", { enumerable: true, get: function () { return rpc_1.MessageType; } });

"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareLocal = exports.LocalTopicImpl = exports.groupReducer = void 0;
var rpc_1 = require("./rpc");
var throttle_1 = require("./throttle");
var utils_1 = require("./utils");
const rpc_1 = require("./rpc");
const throttle_1 = require("./throttle");
const utils_1 = require("./utils");
// Intentionally skipped type checks b/c types are checked with isArray

@@ -78,30 +11,28 @@ function groupReducer(prevValue, newValue) {

throw new Error("groupReducer should only be used with topics that return arrays");
return prevValue ? __spreadArrays(prevValue, newValue) : newValue;
return prevValue ? [...prevValue, ...newValue] : newValue;
}
exports.groupReducer = groupReducer;
/** LocalTopicImpl should implement Topic (and RemoteTopic) so it could be used in ServiceImpl */
var LocalTopicImpl = /** @class */ (function (_super) {
__extends(LocalTopicImpl, _super);
function LocalTopicImpl(supplier, opts) {
if (opts === void 0) { opts = {}; }
var _this = _super.call(this) || this;
_this.supplier = supplier;
_this.opts = opts;
_this.dataSupplierCache = new utils_1.PromiseCache();
_this.subscriptions = {};
_this.opts = __assign({ triggerMapper: function (d) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, d];
}); }); }, throttleReducer: throttle_1.lastValueReducer, throttleTimeout: 500 }, _this.opts);
return _this;
class LocalTopicImpl extends rpc_1.TopicImpl {
constructor(supplier, opts = {}) {
super();
this.supplier = supplier;
this.opts = opts;
this.dataSupplierCache = new utils_1.PromiseCache();
this.subscriptions = {};
this.opts = {
triggerMapper: async (d) => d,
throttleReducer: throttle_1.lastValueReducer,
throttleTimeout: 500,
...this.opts,
};
}
LocalTopicImpl.prototype.getTopicName = function () {
getTopicName() {
return this.name;
};
LocalTopicImpl.prototype.setTopicName = function (s) {
}
setTopicName(s) {
this.name = s;
};
LocalTopicImpl.prototype.trigger = function (filter, suppliedData) {
if (filter === void 0) { filter = {}; }
for (var _i = 0, _a = Object.values(this.subscriptions); _i < _a.length; _i++) {
var subscription = _a[_i];
}
trigger(filter = {}, suppliedData) {
for (const subscription of Object.values(this.subscriptions)) {
if (filterContains(filter, subscription.filter)) {

@@ -111,72 +42,37 @@ subscription.trigger(suppliedData);

}
};
LocalTopicImpl.prototype.getData = function (filter, callContext, connectionContext) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.dataSupplierCache.invoke({ filter: filter, connectionContext: connectionContext }, function () {
return _this.supplier(filter, callContext);
})];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
LocalTopicImpl.prototype.throttled = function (f) {
}
async getData(filter, callContext, connectionContext) {
return await this.dataSupplierCache.invoke({ filter, connectionContext }, () => this.supplier(filter, callContext));
}
throttled(f) {
if (!this.opts.throttleTimeout)
return f;
return throttle_1.throttle(f, this.opts.throttleTimeout, this.opts.throttleReducer);
};
LocalTopicImpl.prototype.subscribeSession = function (session, filter, messageId, ctx) {
return __awaiter(this, void 0, void 0, function () {
var key, thisTopic, subscription;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
key = JSON.stringify(filter);
thisTopic = this;
subscription = this.subscriptions[key] || {
filter: filter,
sessions: [],
trigger: this.throttled(function (suppliedData) {
var _this = this;
// data cannot be cached between subscribers, b/c for different subscriber there could be a different context
this.sessions.forEach(function (session) { return __awaiter(_this, void 0, void 0, function () {
var data, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(suppliedData !== undefined)) return [3 /*break*/, 2];
return [4 /*yield*/, thisTopic.opts.triggerMapper(suppliedData, filter)];
case 1:
_a = _b.sent();
return [3 /*break*/, 4];
case 2: return [4 /*yield*/, thisTopic.getData(filter, session.createContext(), session.getConnectionContext())];
case 3:
_a = _b.sent();
_b.label = 4;
case 4:
data = _a;
session.send(rpc_1.MessageType.Data, utils_1.createMessageId(), thisTopic.getTopicName(), filter, data);
return [2 /*return*/];
}
});
}); });
}),
};
subscription.sessions.push(session);
this.subscriptions[key] = subscription;
return [4 /*yield*/, this.getData(filter, ctx, session.getConnectionContext())];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
LocalTopicImpl.prototype.unsubscribeSession = function (session, filter) {
var key = JSON.stringify(filter);
var subscription = this.subscriptions[key];
return (0, throttle_1.throttle)(f, this.opts.throttleTimeout, this.opts.throttleReducer);
}
async subscribeSession(session, filter, messageId, ctx) {
const key = JSON.stringify(filter);
const thisTopic = this;
const subscription = this.subscriptions[key] || {
filter,
sessions: [],
trigger: this.throttled(function (suppliedData) {
// data cannot be cached between subscribers, b/c for different subscriber there could be a different context
this.sessions.forEach(async (session) => {
const data = suppliedData !== undefined
? await thisTopic.opts.triggerMapper(suppliedData, filter)
: await thisTopic.getData(filter, session.createContext(), session.getConnectionContext());
session.send(rpc_1.MessageType.Data, (0, utils_1.createMessageId)(), thisTopic.getTopicName(), filter, data);
});
}),
};
subscription.sessions.push(session);
this.subscriptions[key] = subscription;
return await this.getData(filter, ctx, session.getConnectionContext());
}
unsubscribeSession(session, filter) {
const key = JSON.stringify(filter);
const subscription = this.subscriptions[key];
if (!subscription)
return;
var index = subscription.sessions.indexOf(session);
const index = subscription.sessions.indexOf(session);
subscription.sessions.splice(index, 1);

@@ -186,18 +82,13 @@ if (!subscription.sessions.length) {

}
};
LocalTopicImpl.prototype.isSubscribed = function () {
}
isSubscribed() {
return !!this.subscriptions.length;
};
}
// dummy implementations, see class comment
LocalTopicImpl.prototype.get = function (params) {
get(params) {
return undefined;
};
LocalTopicImpl.prototype.subscribe = function (consumer, params, subscriptionKey) {
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/];
}); });
};
LocalTopicImpl.prototype.unsubscribe = function (params, subscriptionKey) { };
return LocalTopicImpl;
}(rpc_1.TopicImpl));
}
async subscribe(consumer, params, subscriptionKey) { }
unsubscribe(params, subscriptionKey) { }
}
exports.LocalTopicImpl = LocalTopicImpl;

@@ -209,4 +100,3 @@ function filterContains(triggerFilter, subscriptionFilter) {

return true; // all data modified
for (var _i = 0, _a = Object.keys(subscriptionFilter); _i < _a.length; _i++) {
var key = _a[_i];
for (const key of Object.keys(subscriptionFilter)) {
if (triggerFilter[key] == undefined)

@@ -229,13 +119,11 @@ continue;

*/
function prepareLocal(services, prefix, visited) {
if (prefix === void 0) { prefix = ""; }
if (visited === void 0) { visited = new Set(); }
function prepareLocal(services, prefix = "", visited = new Set()) {
if (visited.has(services))
return;
visited.add(services);
var keys = getObjectProps(services);
keys.forEach(function (key) {
var item = services[key];
const keys = getObjectProps(services);
keys.forEach(key => {
const item = services[key];
if (item && typeof item == "object") {
var name = prefix + key;
const name = prefix + key;
if ("setTopicName" in item) {

@@ -251,3 +139,3 @@ item.setTopicName(name);

function getObjectProps(obj) {
var props = [];
let props = [];
while (!!obj && obj != Object.prototype) {

@@ -257,3 +145,3 @@ props = props.concat(Object.getOwnPropertyNames(obj));

}
return Array.from(new Set(props)).filter(function (p) { return p != "constructor"; });
return Array.from(new Set(props)).filter(p => p != "constructor");
}
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRemote = exports.RemoteTopicImpl = void 0;
var rpc_1 = require("./rpc");
var RpcSession_1 = require("./RpcSession");
var utils_1 = require("./utils");
var RemoteTopicImpl = /** @class */ (function (_super) {
__extends(RemoteTopicImpl, _super);
function RemoteTopicImpl(topicName, session) {
var _this = _super.call(this) || this;
_this.topicName = topicName;
_this.session = session;
_this.consumers = {};
_this.cached = {};
return _this;
const rpc_1 = require("./rpc");
const RpcSession_1 = require("./RpcSession");
const utils_1 = require("./utils");
class RemoteTopicImpl extends rpc_1.TopicImpl {
constructor(topicName, session) {
super();
this.topicName = topicName;
this.session = session;
this.consumers = {};
this.cached = {};
}
RemoteTopicImpl.prototype.subscribe = function (consumer, filter, subscriptionKey, callOpts) {
if (filter === void 0) { filter = {}; }
if (subscriptionKey === void 0) { subscriptionKey = consumer; }
return __awaiter(this, void 0, void 0, function () {
var paramsKey, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (filter === null) {
throw new Error("Subscribe with null filter is not supported, use empty object to get all data");
}
paramsKey = JSON.stringify(filter);
// already have cached value with this params?
if (this.cached[paramsKey] !== undefined) {
consumer(this.cached[paramsKey]);
}
this.consumers[paramsKey] = __spreadArrays((this.consumers[paramsKey] || []), [{ consumer: consumer, subscriptionKey: subscriptionKey }]);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.session.callRemote(this.topicName, filter, rpc_1.MessageType.Subscribe, callOpts)];
case 2:
_a.sent();
return [3 /*break*/, 4];
case 3:
e_1 = _a.sent();
this.unsubscribe(filter, subscriptionKey);
throw e_1;
case 4: return [2 /*return*/, subscriptionKey];
}
});
});
};
RemoteTopicImpl.prototype.unsubscribe = function (params, subscriptionKey) {
if (params === void 0) { params = {}; }
if (subscriptionKey === void 0) { subscriptionKey = undefined; }
var paramsKey = JSON.stringify(params);
async subscribe(consumer, filter = {}, subscriptionKey = consumer, callOpts) {
if (filter === null) {
throw new Error("Subscribe with null filter is not supported, use empty object to get all data");
}
const paramsKey = JSON.stringify(filter);
// already have cached value with this params?
if (this.cached[paramsKey] !== undefined) {
consumer(this.cached[paramsKey]);
}
this.consumers[paramsKey] = [...(this.consumers[paramsKey] || []), { consumer, subscriptionKey }];
try {
await this.session.callRemote(this.topicName, filter, rpc_1.MessageType.Subscribe, callOpts);
}
catch (e) {
this.unsubscribe(filter, subscriptionKey);
throw e;
}
return subscriptionKey;
}
unsubscribe(params = {}, subscriptionKey = undefined) {
const paramsKey = JSON.stringify(params);
if (!this.consumers[paramsKey])
return;
// session.send and not session.callRemote because unsubscribe doesn't yield any response from the server side
this.session.send(rpc_1.MessageType.Unsubscribe, utils_1.createMessageId(), this.topicName, params);
var subscriptions = this.consumers[paramsKey];
var idx = subscriptions.findIndex(function (s) { return s.subscriptionKey == subscriptionKey; });
this.session.send(rpc_1.MessageType.Unsubscribe, (0, utils_1.createMessageId)(), this.topicName, params);
const subscriptions = this.consumers[paramsKey];
const idx = subscriptions.findIndex(s => s.subscriptionKey == subscriptionKey);
if (idx >= 0) {

@@ -124,53 +50,43 @@ if (subscriptions.length > 1) {

}
};
RemoteTopicImpl.prototype.deleteAllSubscriptions = function (paramsKey) {
}
deleteAllSubscriptions(paramsKey) {
delete this.consumers[paramsKey];
delete this.cached[paramsKey];
};
RemoteTopicImpl.prototype.get = function (params, callOpts) {
if (params === void 0) { params = {}; }
}
get(params = {}, callOpts) {
return this.session.callRemote(this.topicName, params, rpc_1.MessageType.Get, callOpts);
};
RemoteTopicImpl.prototype.resubscribe = function () {
var _this = this;
Object.keys(this.consumers).forEach(function (paramsKey) {
var params = JSON.parse(paramsKey);
}
resubscribe() {
Object.keys(this.consumers).forEach(paramsKey => {
const params = JSON.parse(paramsKey);
// session.send and not session.callRemote b/c we don't want resubscribes to be pass thru middleware
_this.session.send(rpc_1.MessageType.Subscribe, utils_1.createMessageId(), _this.topicName, params);
this.session.send(rpc_1.MessageType.Subscribe, (0, utils_1.createMessageId)(), this.topicName, params);
});
};
RemoteTopicImpl.prototype.receiveData = function (params, data) {
var paramsKey = JSON.stringify(params);
var subscriptions = this.consumers[paramsKey] || [];
}
receiveData(params, data) {
const paramsKey = JSON.stringify(params);
const subscriptions = this.consumers[paramsKey] || [];
this.cached[paramsKey] = data;
subscriptions.forEach(function (subscription) { return subscription.consumer(data); });
};
subscriptions.forEach(subscription => subscription.consumer(data));
}
// this is only to easy using for remote services during tests
RemoteTopicImpl.prototype.trigger = function (p, data) { };
return RemoteTopicImpl;
}(rpc_1.TopicImpl));
trigger(p, data) { }
}
exports.RemoteTopicImpl = RemoteTopicImpl;
function createRemote(session, name) {
if (name === void 0) { name = ""; }
function createRemote(session, name = "") {
// start with method
var remoteItem = function (params, callOpts) {
const remoteItem = (params, callOpts) => {
return session.callRemote(name, params, rpc_1.MessageType.Call, callOpts);
};
// then add topic methods
var remoteTopic = new RemoteTopicImpl(name, session);
const remoteTopic = new RemoteTopicImpl(name, session);
// make remoteItem both topic and remoteMethod
var remoteTopicProps = utils_1.getClassMethodNames(remoteTopic);
remoteTopicProps.forEach(function (methodName) {
remoteItem[methodName] = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return remoteTopic[methodName].apply(remoteTopic, args);
};
const remoteTopicProps = (0, utils_1.getClassMethodNames)(remoteTopic);
remoteTopicProps.forEach(methodName => {
remoteItem[methodName] = (...args) => remoteTopic[methodName].apply(remoteTopic, args);
});
// then add proxy creating subitems
var cachedItems = {};
const cachedItems = {};
return new Proxy(remoteItem, {
get: function (target, propName) {
get(target, propName) {
// skip internal props

@@ -180,3 +96,3 @@ if (typeof propName != "string")

// skip other system props
if (__spreadArrays(["then", "catch", "toJSON"], RpcSession_1.skippedRemoteProps).includes(propName))
if (["then", "catch", "toJSON", ...RpcSession_1.skippedRemoteProps].includes(propName))
return target[propName];

@@ -191,3 +107,3 @@ // skip topic methods

},
set: function (target, propName, value) {
set(target, propName, value) {
cachedItems[propName] = value;

@@ -197,4 +113,4 @@ return true;

// Used in resubscribe
ownKeys: function () {
return __spreadArrays(RpcSession_1.skippedRemoteProps, Object.keys(cachedItems));
ownKeys() {
return [...RpcSession_1.skippedRemoteProps, ...Object.keys(cachedItems)];
},

@@ -201,0 +117,0 @@ });

@@ -13,4 +13,4 @@ /**

}
export declare type ServiceItem = Topic<any, any> | Method;
export declare type Method = (req?: any, ctx?: any) => Promise<any>;
export type ServiceItem = Topic<any, any> | Method;
export type Method = (req?: any, ctx?: any) => Promise<any>;
export declare function getServiceItem(services: Services, name: string): {

@@ -28,4 +28,4 @@ item: ServiceItem;

}
export declare type DataConsumer<D> = (d: D) => void;
export declare type DataSupplier<D, P> = (p: P, ctx: any) => Promise<D>;
export type DataConsumer<D> = (d: D) => void;
export type DataSupplier<D, P> = (p: P, ctx: any) => Promise<D>;
export interface LocalTopic<D, P, TD = D> {

@@ -58,2 +58,2 @@ trigger(p?: Partial<P>, data?: TD): void;

}
export declare type Middleware = (ctx: any, next: (params: any) => Promise<any>, params: any, messageType: MessageType.Call | MessageType.Get | MessageType.Subscribe) => Promise<any>;
export type Middleware = (ctx: any, next: (params: any) => Promise<any>, params: any, messageType: MessageType.Call | MessageType.Get | MessageType.Subscribe) => Promise<any>;

@@ -5,4 +5,4 @@ "use strict";

function getServiceItem(services, name) {
var names = name.split("/");
var item = services[names[0]];
const names = name.split("/");
const item = services[names[0]];
if (!item) {

@@ -33,9 +33,6 @@ return { item: null, object: null };

MessageType[MessageType["Data"] = 13] = "Data";
})(MessageType = exports.MessageType || (exports.MessageType = {}));
var TopicImpl = /** @class */ (function () {
function TopicImpl() {
}
return TopicImpl;
}());
})(MessageType || (exports.MessageType = MessageType = {}));
class TopicImpl {
}
exports.TopicImpl = TopicImpl;
// id generator

@@ -38,3 +38,3 @@ import { CallOptions, MessageType, Middleware, RpcConnectionContext, RpcContext } from "./rpc";

private resolveDisconnect;
disconnect(): Promise<unknown>;
disconnect(): Promise<void>;
handleDisconnected(): Promise<void>;

@@ -41,0 +41,0 @@ sendPing: () => Promise<void>;

"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.skippedRemoteProps = exports.PONG_MESSAGE = exports.PING_MESSAGE = exports.RpcSession = void 0;
var logger_1 = require("./logger");
var remote_1 = require("./remote");
var rpc_1 = require("./rpc");
var utils_1 = require("./utils");
var jsonCircularStringify = require("json-stringify-safe");
var RpcSession = /** @class */ (function () {
function RpcSession(local, listeners, connectionContext, localMiddleware, remoteMiddleware, messageParser, pingSendTimeout, keepAliveTimeout, callTimeout, syncRemoteCalls, delayCalls) {
var _this = this;
const logger_1 = require("./logger");
const remote_1 = require("./remote");
const rpc_1 = require("./rpc");
const utils_1 = require("./utils");
const json_stringify_safe_1 = __importDefault(require("json-stringify-safe"));
class RpcSession {
constructor(local, listeners, connectionContext, localMiddleware, remoteMiddleware, messageParser, pingSendTimeout, keepAliveTimeout, callTimeout, syncRemoteCalls, delayCalls) {
this.local = local;

@@ -82,42 +30,31 @@ this.listeners = listeners;

this.lastSendAt = 0;
this.resolveDisconnect = function () { };
this.sendPing = function () { return __awaiter(_this, void 0, void 0, function () {
var e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, this.callRemote("", "ping", "ping", null)];
case 1:
_a.sent();
this.pingTimer = setTimeout(this.sendPing, this.pingSendTimeout);
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
logger_1.log.debug("Ping send failed " + this.connectionContext.remoteId);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); };
this.remote = remote_1.createRemote(this);
this.resolveDisconnect = () => { };
this.sendPing = async () => {
try {
await this.callRemote("", "ping", "ping", null);
this.pingTimer = setTimeout(this.sendPing, this.pingSendTimeout);
}
catch (e) {
logger_1.log.debug(`Ping send failed ${this.connectionContext.remoteId}`);
}
};
this.remote = (0, remote_1.createRemote)(this);
}
RpcSession.prototype.open = function (socket) {
var _this = this;
open(socket) {
this.socket = socket;
this.lastMessageAt = Date.now();
resubscribeTopics(this.remote);
socket.onMessage(function (message) {
_this.handleMessage(message);
socket.onMessage(message => {
this.handleMessage(message);
});
socket.onPing(function () {
_this.trackMessageReceived("PING");
socket.onPing(() => {
this.trackMessageReceived("PING");
});
socket.onPong(function () {
_this.trackMessageReceived("PONG");
if (_this.runningCalls[PING_MESSAGE_ID]) {
_this.runningCalls[PING_MESSAGE_ID].resolve();
delete _this.runningCalls[PING_MESSAGE_ID];
socket.onPong(() => {
this.trackMessageReceived("PONG");
if (this.runningCalls[PING_MESSAGE_ID]) {
this.runningCalls[PING_MESSAGE_ID].resolve();
delete this.runningCalls[PING_MESSAGE_ID];
}
_this.flushPendingCalls();
this.flushPendingCalls();
});

@@ -128,68 +65,55 @@ if (this.pingSendTimeout) {

if (this.keepAliveTimeout) {
this.keepAliveTimer = setInterval(function () { return _this.checkKeepAlive(); }, 1000);
this.keepAliveTimer = setInterval(() => this.checkKeepAlive(), 1000);
}
this.callTimeoutTimer = setInterval(function () { return _this.timeoutCalls(); }, 1000); // every 1s
this.callTimeoutTimer = setInterval(() => this.timeoutCalls(), 1000); // every 1s
this.flushPendingCalls();
};
RpcSession.prototype.trackMessageReceived = function (msg) {
}
trackMessageReceived(msg) {
this.lastMessageAt = Date.now();
this.listeners.messageIn(msg);
};
RpcSession.prototype.disconnect = function () {
var _this = this;
return new Promise(function (resolve) {
if (!_this.socket) {
}
disconnect() {
return new Promise(resolve => {
if (!this.socket) {
resolve();
return;
}
var timer = setTimeout(function () {
const timer = setTimeout(() => {
// if not disconnected in 5s, just ignore it
logger_1.log.debug("Wait for disconnect timed out for " + _this.connectionContext.remoteId);
logger_1.log.debug(`Wait for disconnect timed out for ${this.connectionContext.remoteId}`);
resolve();
}, 5 * 1000);
_this.resolveDisconnect = function () {
this.resolveDisconnect = () => {
clearTimeout(timer);
setTimeout(resolve, 0);
};
_this.socket.disconnect();
this.socket.disconnect();
});
};
RpcSession.prototype.handleDisconnected = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// stop timers
clearTimeout(this.pingTimer);
clearInterval(this.keepAliveTimer);
clearInterval(this.callTimeoutTimer);
// clear subscriptions
return [4 /*yield*/, Promise.all(this.subscriptions.map(function (s) { return s.topic.unsubscribeSession(_this, s.params); }))];
case 1:
// clear subscriptions
_a.sent();
this.subscriptions = [];
this.listeners.unsubscribed(0);
__spreadArrays(this.queue, Object.values(this.runningCalls)).forEach(function (call) {
call.reject(new Error("Timeout " + call.type + ", " + call.name));
});
this.queue = [];
this.runningCalls = {};
this.resolveDisconnect();
this.resolveDisconnect = function () { };
this.socket = null;
return [2 /*return*/];
}
});
}
async handleDisconnected() {
// stop timers
clearTimeout(this.pingTimer);
clearInterval(this.keepAliveTimer);
clearInterval(this.callTimeoutTimer);
// clear subscriptions
await Promise.all(this.subscriptions.map(s => s.topic.unsubscribeSession(this, s.params)));
this.subscriptions = [];
this.listeners.unsubscribed(0);
[...this.queue, ...Object.values(this.runningCalls)].forEach(call => {
call.reject(new Error("Timeout " + call.type + ", " + call.name));
});
};
RpcSession.prototype.checkKeepAlive = function () {
var now = Date.now();
this.queue = [];
this.runningCalls = {};
this.resolveDisconnect();
this.resolveDisconnect = () => { };
this.socket = null;
}
checkKeepAlive() {
const now = Date.now();
if (this.lastMessageAt < now - this.keepAliveTimeout) {
logger_1.log.debug("Keep alive period expired, closing socket " + this.connectionContext.remoteId);
logger_1.log.debug(`Keep alive period expired, closing socket ${this.connectionContext.remoteId}`);
this.disconnect();
}
};
RpcSession.prototype.handleMessage = function (data) {
}
handleMessage(data) {
try {

@@ -204,18 +128,18 @@ this.trackMessageReceived(data);

else {
logger_1.log.debug("Received PING but socket is not open " + this.connectionContext.remoteId);
logger_1.log.debug(`Received PING but socket is not open ${this.connectionContext.remoteId}`);
}
return;
}
var message_1 = this.messageParser(data);
if (message_1[0] == rpc_1.MessageType.Result || message_1[0] == rpc_1.MessageType.Error) {
return this.callRemoteResponse(message_1);
const message = this.messageParser(data);
if (message[0] == rpc_1.MessageType.Result || message[0] == rpc_1.MessageType.Error) {
return this.callRemoteResponse(message);
}
var type = message_1[0], id = message_1[1], name = message_1[2], other = message_1.slice(3);
var _a = rpc_1.getServiceItem(this.local, name), item = _a.item, object = _a.object;
var localTopic = item;
var method = item;
const [type, id, name, ...other] = message;
const { item, object } = (0, rpc_1.getServiceItem)(this.local, name);
const localTopic = item;
const method = item;
switch (type) {
case rpc_1.MessageType.Subscribe:
if (!localTopic) {
this.send(rpc_1.MessageType.Error, id, null, "Topic '" + name + "' not implemented", null);
this.send(rpc_1.MessageType.Error, id, null, `Topic '${name}' not implemented`, null);
break;

@@ -227,3 +151,3 @@ }

if (!localTopic) {
this.send(rpc_1.MessageType.Error, id, null, "Topic '" + name + "' not implemented", null);
this.send(rpc_1.MessageType.Error, id, null, `Topic '${name}' not implemented`, null);
break;

@@ -235,3 +159,3 @@ }

if (!localTopic) {
this.send(rpc_1.MessageType.Error, id, null, "Topic '" + name + "' not implemented", null);
this.send(rpc_1.MessageType.Error, id, null, `Topic '${name}' not implemented`, null);
break;

@@ -243,3 +167,3 @@ }

if (!method) {
this.send(rpc_1.MessageType.Error, id, null, "Item '" + name + "' not implemented", null);
this.send(rpc_1.MessageType.Error, id, null, `Item '${name}' not implemented`, null);
break;

@@ -250,5 +174,5 @@ }

case rpc_1.MessageType.Data:
var remoteTopic = rpc_1.getServiceItem(this.remote, name).item;
const remoteTopic = (0, rpc_1.getServiceItem)(this.remote, name).item;
if (!remoteTopic) {
logger_1.log.debug("Can't find remote topic with name '" + name + "'");
logger_1.log.debug(`Can't find remote topic with name '${name}'`);
break;

@@ -258,3 +182,3 @@ }

if (this.runningCalls[id]) {
this.callRemoteResponse(message_1);
this.callRemoteResponse(message);
}

@@ -267,22 +191,15 @@ // and deliver to callback

catch (e) {
logger_1.log.error("Failed to handle RPC message " + data + "\n, remote id " + this.connectionContext.remoteId, e);
logger_1.log.error(`Failed to handle RPC message ${data}\n, remote id ${this.connectionContext.remoteId}`, e);
}
};
RpcSession.prototype.sendError = function (id, error) {
var err = Object.getOwnPropertyNames(error)
.filter(function (prop) { return prop != "stack" && prop != "message" && prop != "code"; })
.reduce(function (r, key) {
var _a;
return (__assign(__assign({}, r), (_a = {}, _a[key] = error[key], _a)));
}, {});
}
sendError(id, error) {
const err = Object.getOwnPropertyNames(error)
.filter(prop => prop != "stack" && prop != "message" && prop != "code")
.reduce((r, key) => ({ ...r, [key]: error[key] }), {});
this.send(rpc_1.MessageType.Error, id, error["code"], error.message, err);
};
RpcSession.prototype.send = function (type, id) {
var params = [];
for (var _i = 2; _i < arguments.length; _i++) {
params[_i - 2] = arguments[_i];
}
}
send(type, id, ...params) {
if (this.socket) {
this.lastSendAt = Date.now();
var data = utils_1.message.apply(void 0, __spreadArrays([type, id], params));
const data = (0, utils_1.message)(type, id, ...params);
this.listeners.messageOut(data);

@@ -292,12 +209,11 @@ this.socket.send(data);

else {
logger_1.log.debug("Can't send message, socket is not connected");
logger_1.log.debug(`Can't send message, socket is not connected`);
}
};
RpcSession.prototype.timeoutCalls = function () {
var now = Date.now();
for (var _i = 0, _a = Object.keys(this.runningCalls); _i < _a.length; _i++) {
var messageId = _a[_i];
var expireCallBefore = now - this.runningCalls[messageId].timeout;
}
timeoutCalls() {
const now = Date.now();
for (const messageId of Object.keys(this.runningCalls)) {
const expireCallBefore = now - this.runningCalls[messageId].timeout;
if (this.runningCalls[messageId].startedAt < expireCallBefore) {
var reject = this.runningCalls[messageId].reject;
const { reject } = this.runningCalls[messageId];
delete this.runningCalls[messageId];

@@ -307,26 +223,24 @@ reject(new Error("Timeout"));

}
};
RpcSession.prototype.callRemote = function (name, params, type, callOpts) {
var _this = this;
var sendMessage = function (p) {
return new Promise(function (resolve, reject) {
_this.queue.push({
type: type,
name: name,
}
callRemote(name, params, type, callOpts) {
const sendMessage = p => {
return new Promise((resolve, reject) => {
this.queue.push({
type,
name,
params: cloneParams(p),
resolve: resolve,
reject: reject,
timeout: (callOpts === null || callOpts === void 0 ? void 0 : callOpts.timeout) || _this.callTimeout,
resolve,
reject,
timeout: callOpts?.timeout || this.callTimeout,
});
_this.flushPendingCalls();
this.flushPendingCalls();
});
};
return this.remoteMiddleware(null, sendMessage, params, type);
};
RpcSession.prototype.flushPendingCalls = function () {
var _this = this;
}
flushPendingCalls() {
if (this.delayCalls) {
var delay = this.lastSendAt + this.delayCalls - Date.now();
const delay = this.lastSendAt + this.delayCalls - Date.now();
if (delay > 0) {
setTimeout(function () { return _this.flushPendingCalls(); }, delay);
setTimeout(() => this.flushPendingCalls(), delay);
return;

@@ -341,3 +255,3 @@ }

while (this.queue.length > 0) {
var call = this.queue.shift();
const call = this.queue.shift();
call.startedAt = Date.now();

@@ -351,3 +265,3 @@ if (call.type == "ping") {

else {
var messageId = utils_1.createMessageId();
const messageId = (0, utils_1.createMessageId)();
this.runningCalls[messageId] = call;

@@ -359,16 +273,20 @@ this.send(call.type, "" + messageId, call.name, call.params);

}
};
}
/** Creates call context - context to be used in calls */
RpcSession.prototype.createContext = function (messageId, itemName, item) {
return __assign(__assign({}, this.connectionContext), { remote: this.remote, item: item,
messageId: messageId,
itemName: itemName });
};
RpcSession.prototype.getConnectionContext = function () {
createContext(messageId, itemName, item) {
return {
...this.connectionContext,
remote: this.remote,
item,
messageId,
itemName,
};
}
getConnectionContext() {
return this.connectionContext;
};
RpcSession.prototype.callRemoteResponse = function (data) {
var messageType = data[0], id = data[1], other = data.slice(2);
}
callRemoteResponse(data) {
const [messageType, id, ...other] = data;
if (this.runningCalls[id]) {
var _a = this.runningCalls[id], resolve = _a.resolve, reject = _a.reject;
const { resolve, reject } = this.runningCalls[id];
delete this.runningCalls[id];

@@ -384,4 +302,4 @@ if (messageType == rpc_1.MessageType.Result || messageType == rpc_1.MessageType.Data) {

else {
var res = other[0], description = other[1], details = other[2];
var error = new Error(description || res || "Remote call failed");
const [res, description, details] = other;
const error = new Error(description || res || "Remote call failed");
Object.assign(error, details || {});

@@ -394,112 +312,54 @@ if (res != null)

this.flushPendingCalls();
};
RpcSession.prototype.invokeLocal = function (id, name, localMethod, localMethodObject, params) {
return __awaiter(this, void 0, void 0, function () {
var callContext_1, invokeLocalMethod, r, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
callContext_1 = this.createContext(id, name, localMethod);
invokeLocalMethod = function (p) {
if (p === void 0) { p = params; }
return localMethod.call(localMethodObject, p, callContext_1);
};
return [4 /*yield*/, this.localMiddleware(callContext_1, invokeLocalMethod, params, rpc_1.MessageType.Call)];
case 1:
r = _a.sent();
this.send(rpc_1.MessageType.Result, id, r);
return [3 /*break*/, 3];
case 2:
e_2 = _a.sent();
logger_1.log.error("Unable to call method " + name + " with params " + jsonCircularStringify(params) + ". ", e_2);
this.sendError(id, e_2);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
};
RpcSession.prototype.get = function (id, name, topic, params) {
return __awaiter(this, void 0, void 0, function () {
var callContext_2, getFromTopic, r, e_3;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
callContext_2 = this.createContext(id, topic.getTopicName());
getFromTopic = function (p) {
if (p === void 0) { p = params; }
return topic.getData(p, callContext_2, _this.getConnectionContext());
};
return [4 /*yield*/, this.localMiddleware(callContext_2, getFromTopic, params, rpc_1.MessageType.Get)];
case 1:
r = _a.sent();
this.send(rpc_1.MessageType.Result, id, r);
return [3 /*break*/, 3];
case 2:
e_3 = _a.sent();
logger_1.log.error("Unable to get data from topic " + name, e_3);
this.sendError(id, e_3);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
};
RpcSession.prototype.subscribe = function (topic, params, messageId) {
return __awaiter(this, void 0, void 0, function () {
var ctx_1, subscribeTopic, r, e_4;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
ctx_1 = this.createContext(messageId, topic.getTopicName());
subscribeTopic = function (p) {
if (p === void 0) { p = params; }
return topic.subscribeSession(_this, p, messageId, ctx_1);
};
return [4 /*yield*/, this.localMiddleware(ctx_1, subscribeTopic, params, rpc_1.MessageType.Subscribe)];
case 1:
r = _a.sent();
this.send(rpc_1.MessageType.Data, messageId, topic.getTopicName(), cloneParams(params), r);
this.subscriptions.push({ topic: topic, params: params });
this.listeners.subscribed(this.subscriptions.length);
return [3 /*break*/, 3];
case 2:
e_4 = _a.sent();
logger_1.log.error("Unable to subscribe to topic " + topic.getTopicName(), e_4);
this.sendError(messageId, e_4);
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
});
};
RpcSession.prototype.unsubscribe = function (topic, params) {
return __awaiter(this, void 0, void 0, function () {
var paramsKey, idx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, topic.unsubscribeSession(this, params)];
case 1:
_a.sent();
paramsKey = JSON.stringify(params);
idx = this.subscriptions.findIndex(function (s) { return s.topic == topic || JSON.stringify(s.params) == paramsKey; });
if (idx >= 0) {
this.subscriptions.splice(idx, 1);
}
this.listeners.unsubscribed(this.subscriptions.length);
return [2 /*return*/];
}
});
});
};
return RpcSession;
}());
}
async invokeLocal(id, name, localMethod, localMethodObject, params) {
try {
const callContext = this.createContext(id, name, localMethod);
const invokeLocalMethod = (p = params) => localMethod.call(localMethodObject, p, callContext);
const r = await this.localMiddleware(callContext, invokeLocalMethod, params, rpc_1.MessageType.Call);
this.send(rpc_1.MessageType.Result, id, r);
}
catch (e) {
logger_1.log.error(`Unable to call method ${name} with params ${(0, json_stringify_safe_1.default)(params)}. `, e);
this.sendError(id, e);
}
}
async get(id, name, topic, params) {
try {
const callContext = this.createContext(id, topic.getTopicName());
const getFromTopic = (p = params) => topic.getData(p, callContext, this.getConnectionContext());
const r = await this.localMiddleware(callContext, getFromTopic, params, rpc_1.MessageType.Get);
this.send(rpc_1.MessageType.Result, id, r);
}
catch (e) {
logger_1.log.error(`Unable to get data from topic ${name}`, e);
this.sendError(id, e);
}
}
async subscribe(topic, params, messageId) {
try {
const ctx = this.createContext(messageId, topic.getTopicName());
const subscribeTopic = (p = params) => topic.subscribeSession(this, p, messageId, ctx);
const r = await this.localMiddleware(ctx, subscribeTopic, params, rpc_1.MessageType.Subscribe);
this.send(rpc_1.MessageType.Data, messageId, topic.getTopicName(), cloneParams(params), r);
this.subscriptions.push({ topic, params });
this.listeners.subscribed(this.subscriptions.length);
}
catch (e) {
logger_1.log.error(`Unable to subscribe to topic ${topic.getTopicName()}`, e);
this.sendError(messageId, e);
}
}
async unsubscribe(topic, params) {
await topic.unsubscribeSession(this, params);
const paramsKey = JSON.stringify(params);
const idx = this.subscriptions.findIndex(s => s.topic == topic || JSON.stringify(s.params) == paramsKey);
if (idx >= 0) {
this.subscriptions.splice(idx, 1);
}
this.listeners.unsubscribed(this.subscriptions.length);
}
}
exports.RpcSession = RpcSession;
function resubscribeTopics(remote) {
Object.getOwnPropertyNames(remote).forEach(function (key) {
Object.getOwnPropertyNames(remote).forEach(key => {
if (exports.skippedRemoteProps.includes(key))

@@ -512,3 +372,3 @@ return;

}
var PING_MESSAGE_ID = "–ws-ping";
const PING_MESSAGE_ID = "–ws-ping";
exports.PING_MESSAGE = "PING";

@@ -522,3 +382,3 @@ exports.PONG_MESSAGE = "PONG";

return p;
return JSON.parse(jsonCircularStringify(p));
return JSON.parse((0, json_stringify_safe_1.default)(p));
}

@@ -525,0 +385,0 @@ return p;

"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
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;
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRpcServer = void 0;
var UUID = require("uuid-js");
var logger_1 = require("./logger");
var RpcSession_1 = require("./RpcSession");
var remote_1 = require("./remote");
var local_1 = require("./local");
var utils_1 = require("./utils");
var defaultOptions = {
createConnectionContext: function (socket) {
var transportDetails = [];
for (var _i = 1; _i < arguments.length; _i++) {
transportDetails[_i - 1] = arguments[_i];
}
return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, ({
remoteId: UUID.create().toString(),
})];
});
});
},
localMiddleware: function (ctx, next, params, messageType) { return next(params); },
remoteMiddleware: function (ctx, next, params, messageType) { return next(params); },
const UUID = __importStar(require("uuid-js"));
const logger_1 = require("./logger");
const RpcSession_1 = require("./RpcSession");
const remote_1 = require("./remote");
const local_1 = require("./local");
const utils_1 = require("./utils");
const defaultOptions = {
createConnectionContext: async (socket, ...transportDetails) => ({
remoteId: UUID.create().toString(),
}),
localMiddleware: (ctx, next, params, messageType) => next(params),
remoteMiddleware: (ctx, next, params, messageType) => next(params),
pingSendTimeout: 40 * 1000,

@@ -85,19 +44,20 @@ keepAliveTimeout: 120 * 1000,

delayCalls: 0,
messageParser: function (data) { return JSON.parse(data, utils_1.dateReviver); },
messageParser: data => JSON.parse(data, utils_1.dateReviver),
listeners: {
connected: function () { },
disconnected: function () { },
subscribed: function () { },
unsubscribed: function () { },
messageIn: function () { },
messageOut: function () { },
connected: () => { },
disconnected: () => { },
subscribed: () => { },
unsubscribed: () => { },
messageIn: () => { },
messageOut: () => { },
},
};
function createRpcServer(local, socketServer, opts) {
var _this = this;
if (opts === void 0) { opts = {}; }
opts = __assign(__assign({}, defaultOptions), opts);
var sessions = {};
local_1.prepareLocal(local);
socketServer.onError(function (e) {
function createRpcServer(local, socketServer, opts = {}) {
opts = {
...defaultOptions,
...opts,
};
const sessions = {};
(0, local_1.prepareLocal)(local);
socketServer.onError(e => {
logger_1.log.error("RPC WS server error", e);

@@ -107,4 +67,4 @@ });

return Object.values(sessions)
.map(function (s) { return s.subscriptions.length; })
.reduce(function (p, c) { return p + c; }, 0);
.map(s => s.subscriptions.length)
.reduce((p, c) => p + c, 0);
}

@@ -114,105 +74,56 @@ function isConnected(remoteId) {

}
socketServer.onConnection(function (socket) {
var transportDetails = [];
for (var _i = 1; _i < arguments.length; _i++) {
transportDetails[_i - 1] = arguments[_i];
socketServer.onConnection(async (socket, ...transportDetails) => {
let connectionContext;
try {
connectionContext = await opts.createConnectionContext(socket, ...transportDetails);
}
return __awaiter(_this, void 0, void 0, function () {
var connectionContext, e_1, remoteId, session;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, opts.createConnectionContext.apply(opts, __spreadArrays([socket], transportDetails))];
case 1:
connectionContext = _a.sent();
return [3 /*break*/, 3];
case 2:
e_1 = _a.sent();
logger_1.log.warn("Failed to create connection context", e_1);
socket.disconnect();
return [2 /*return*/];
case 3:
remoteId = connectionContext.remoteId;
if (!sessions[remoteId]) return [3 /*break*/, 5];
logger_1.log.warn("Prev session active, disconnecting", remoteId);
return [4 /*yield*/, sessions[remoteId].disconnect()];
case 4:
_a.sent();
_a.label = 5;
case 5:
session = new RpcSession_1.RpcSession(local, {
messageIn: function (data) {
return utils_1.safeListener(function () { return opts.listeners.messageIn(remoteId, data, connectionContext); });
},
messageOut: function (data) {
return utils_1.safeListener(function () { return opts.listeners.messageOut(remoteId, data, connectionContext); });
},
subscribed: function () {
return utils_1.safeListener(function () { return opts.listeners.subscribed(getTotalSubscriptions(), connectionContext); });
},
unsubscribed: function () {
return utils_1.safeListener(function () {
return opts.listeners.unsubscribed(getTotalSubscriptions(), connectionContext);
});
},
}, connectionContext, opts.localMiddleware, opts.remoteMiddleware, opts.messageParser, opts.pingSendTimeout, opts.keepAliveTimeout, opts.callTimeout, opts.syncRemoteCalls, opts.delayCalls);
sessions[remoteId] = session;
session.open(socket);
utils_1.safeListener(function () {
return opts.listeners.connected(remoteId, Object.keys(sessions).length, connectionContext);
});
socket.onDisconnected(function (code, reason) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (sessions[remoteId] == session) {
delete sessions[remoteId];
logger_1.log.debug("Client disconnected, " + remoteId, { code: code, reason: reason });
}
else {
logger_1.log.debug("Disconnected prev session, " + remoteId, { code: code, reason: reason });
}
utils_1.safeListener(function () {
return opts.listeners.disconnected(remoteId, Object.keys(sessions).length, connectionContext);
});
return [4 /*yield*/, session.handleDisconnected()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
socket.onError(function (e) {
logger_1.log.warn("Communication error, client " + remoteId, e);
});
return [2 /*return*/];
}
});
catch (e) {
logger_1.log.warn("Failed to create connection context", e);
socket.disconnect();
return;
}
const { remoteId } = connectionContext;
if (sessions[remoteId]) {
logger_1.log.warn("Prev session active, disconnecting", remoteId);
await sessions[remoteId].disconnect();
}
const session = new RpcSession_1.RpcSession(local, {
messageIn: data => (0, utils_1.safeListener)(() => opts.listeners.messageIn(remoteId, data, connectionContext)),
messageOut: data => (0, utils_1.safeListener)(() => opts.listeners.messageOut(remoteId, data, connectionContext)),
subscribed: () => (0, utils_1.safeListener)(() => opts.listeners.subscribed(getTotalSubscriptions(), connectionContext)),
unsubscribed: () => (0, utils_1.safeListener)(() => opts.listeners.unsubscribed(getTotalSubscriptions(), connectionContext)),
}, connectionContext, opts.localMiddleware, opts.remoteMiddleware, opts.messageParser, opts.pingSendTimeout, opts.keepAliveTimeout, opts.callTimeout, opts.syncRemoteCalls, opts.delayCalls);
sessions[remoteId] = session;
session.open(socket);
(0, utils_1.safeListener)(() => opts.listeners.connected(remoteId, Object.keys(sessions).length, connectionContext));
socket.onDisconnected(async (code, reason) => {
if (sessions[remoteId] == session) {
delete sessions[remoteId];
logger_1.log.debug(`Client disconnected, ${remoteId}`, { code, reason });
}
else {
logger_1.log.debug(`Disconnected prev session, ${remoteId}`, { code, reason });
}
(0, utils_1.safeListener)(() => opts.listeners.disconnected(remoteId, Object.keys(sessions).length, connectionContext));
await session.handleDisconnected();
});
socket.onError(e => {
logger_1.log.warn(`Communication error, client ${remoteId}`, e);
});
}, isConnected);
return {
close: function (cb) { return socketServer.close(cb); },
close: cb => socketServer.close(cb),
/** These remote are not reconnecting - they should not be saved */
getRemote: function (clientId) {
getRemote: clientId => {
if (!sessions[clientId])
throw new Error("Client " + clientId + " is not connected");
return remote_1.createRemote(sessions[clientId]);
throw new Error(`Client ${clientId} is not connected`);
return (0, remote_1.createRemote)(sessions[clientId]);
},
isConnected: isConnected,
getConnectedIds: function () { return Object.keys(sessions); },
disconnectClient: function (clientId) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!sessions[clientId])
throw new Error("Client " + clientId + " is not connected");
return [4 /*yield*/, sessions[clientId].disconnect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); },
isConnected,
getConnectedIds: () => Object.keys(sessions),
disconnectClient: async (clientId) => {
if (!sessions[clientId])
throw new Error(`Client ${clientId} is not connected`);
await sessions[clientId].disconnect();
},
// for debug only

@@ -219,0 +130,0 @@ __sessions: sessions,

@@ -1,3 +0,3 @@

export declare type ThrottleArgsReducer<D> = (prevValue: D, newValue: D) => D;
export type ThrottleArgsReducer<D> = (prevValue: D, newValue: D) => D;
export declare function lastValueReducer<D>(prevValue: D, newValue: D): D;
export declare function throttle<D>(callback: (d: D) => void, delay: number, reducer: ThrottleArgsReducer<D>): (D: any) => void;

@@ -9,8 +9,8 @@ "use strict";

function throttle(callback, delay, reducer) {
var timer;
var lastExec = 0;
var reducedArg;
let timer;
let lastExec = 0;
let reducedArg;
function wrapper(d) {
var self = this;
var elapsed = Date.now() - lastExec;
let self = this;
let elapsed = Date.now() - lastExec;
function exec() {

@@ -17,0 +17,0 @@ lastExec = Date.now();

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
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;
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.safeListener = exports.PromiseCache = exports.createDomWebsocket = exports.mapTopic = exports.composeMiddleware = exports.getClassMethodNames = exports.message = exports.setCreateMessageId = exports.createMessageId = exports.ISO8601_date = exports.ISO8601_secs = exports.ISO8601 = exports.dateReviver = void 0;
var UUID = require("uuid-js");
var jsonCircularStringify = require("json-stringify-safe");
var RpcSession_1 = require("./RpcSession");
var logger_1 = require("./logger");
const UUID = __importStar(require("uuid-js"));
const json_stringify_safe_1 = __importDefault(require("json-stringify-safe"));
const RpcSession_1 = require("./RpcSession");
const logger_1 = require("./logger");
function dateReviver(key, val) {

@@ -67,9 +50,8 @@ if (typeof val == "string") {

function websocketDateToString(message) {
return convertDateToString(message, function (d) {
var s = d.toISOString();
return convertDateToString(message, d => {
const s = d.toISOString();
return s.substring(0, s.lastIndexOf(".")) + "Z";
});
}
function convertDateToString(message, format, cache) {
if (cache === void 0) { cache = []; }
function convertDateToString(message, format, cache = []) {
if (!message)

@@ -80,4 +62,4 @@ return message;

cache.push(message);
Object.keys(message).forEach(function (key) {
var prop = message[key];
Object.keys(message).forEach(key => {
const prop = message[key];
if (typeof prop != "object")

@@ -92,3 +74,3 @@ return;

return convertDateToString(prop, format, cache);
for (var i = 0; i < prop.length; i++) {
for (let i = 0; i < prop.length; i++) {
convertDateToString(prop[i], format, cache);

@@ -102,3 +84,4 @@ }

exports.ISO8601_date = /^\d\d\d\d-\d\d-\d\d$/;
exports.createMessageId = function () { return UUID.create().toString(); };
let createMessageId = () => UUID.create().toString();
exports.createMessageId = createMessageId;
function setCreateMessageId(f) {

@@ -108,9 +91,5 @@ exports.createMessageId = f;

exports.setCreateMessageId = setCreateMessageId;
function message(type, id) {
var params = [];
for (var _i = 2; _i < arguments.length; _i++) {
params[_i - 2] = arguments[_i];
}
function message(type, id, ...params) {
websocketDateToString(params);
return jsonCircularStringify(__spreadArrays([type, id], params));
return (0, json_stringify_safe_1.default)([type, id, ...params]);
}

@@ -120,13 +99,9 @@ exports.message = message;

return Object.getOwnPropertyNames(Object.getPrototypeOf(obj))
.filter(function (m) { return obj[m] instanceof Function; })
.filter(function (m) { return obj[m].name != "constructor"; });
.filter(m => obj[m] instanceof Function)
.filter(m => obj[m].name != "constructor");
}
exports.getClassMethodNames = getClassMethodNames;
function composeMiddleware() {
var middleware = [];
for (var _i = 0; _i < arguments.length; _i++) {
middleware[_i] = arguments[_i];
}
function composeMiddleware(...middleware) {
return function (ctx, next, params, messageType) {
var index = -1;
let index = -1;
return dispatch(0, params);

@@ -154,22 +129,13 @@ function dispatch(i, p) {

return {
subscribe: function (consumer, params, subscriptionKey) {
return t.subscribe(function (d) {
subscribe(consumer, params, subscriptionKey) {
return t.subscribe((d) => {
return consumer(map(d));
}, params, subscriptionKey);
},
unsubscribe: function (params, subscriptionKey) {
unsubscribe(params, subscriptionKey) {
return t.unsubscribe(params, subscriptionKey);
},
get: function (params) {
return __awaiter(this, void 0, void 0, function () {
var d;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, t.get(params)];
case 1:
d = _a.sent();
return [2 /*return*/, map(d)];
}
});
});
async get(params) {
const d = await t.get(params);
return map(d);
},

@@ -180,15 +146,14 @@ };

// TODO better name would be createDomSocket
function createDomWebsocket(url, protocols) {
if (protocols === void 0) { protocols = undefined; }
var ws = new WebSocket(url, protocols);
var onPong = function () { };
var onDisconnected = function (code, reason) { };
function createDomWebsocket(url, protocols = undefined) {
const ws = new WebSocket(url, protocols);
let onPong = () => { };
let onDisconnected = (code, reason) => { };
function singleCallDisconnected(code, reason) {
onDisconnected(code, reason);
onDisconnected = function () { };
onDisconnected = () => { };
}
return {
onMessage: function (h) {
ws.onmessage = function (e) {
var message = e.data.toString();
onMessage: h => {
ws.onmessage = e => {
const message = e.data.toString();
if (message == RpcSession_1.PONG_MESSAGE)

@@ -200,18 +165,15 @@ onPong();

},
onOpen: function (h) { return (ws.onopen = h); },
onDisconnected: function (h) {
onOpen: h => (ws.onopen = h),
onDisconnected: h => {
onDisconnected = h;
ws.onclose = function (_a) {
var code = _a.code, reason = _a.reason;
return void singleCallDisconnected(code, reason);
};
ws.onclose = ({ code, reason }) => void singleCallDisconnected(code, reason);
},
onError: function (h) { return (ws.onerror = h); },
onPong: function (h) {
onError: h => (ws.onerror = h),
onPong: h => {
onPong = h;
},
onPing: function (h) {
onPing: h => {
// not implemented
},
disconnect: function () {
disconnect: () => {
try {

@@ -226,4 +188,4 @@ ws.close(3000, "forced");

},
send: function (data) { return ws.send(data); },
ping: function () {
send: data => ws.send(data),
ping: () => {
ws.send(RpcSession_1.PING_MESSAGE);

@@ -234,17 +196,16 @@ },

exports.createDomWebsocket = createDomWebsocket;
var PromiseCache = /** @class */ (function () {
function PromiseCache() {
class PromiseCache {
constructor() {
this.cache = {};
}
PromiseCache.prototype.invoke = function (cacheKey, supplier) {
var _this = this;
var key = JSON.stringify(cacheKey);
invoke(cacheKey, supplier) {
const key = JSON.stringify(cacheKey);
if (!this.cache[key]) {
this.cache[key] = supplier()
.then(function (r) {
delete _this.cache[key];
.then(r => {
delete this.cache[key];
return r;
})
.catch(function (e) {
delete _this.cache[key];
.catch(e => {
delete this.cache[key];
throw e;

@@ -254,5 +215,4 @@ });

return this.cache[key];
};
return PromiseCache;
}());
}
}
exports.PromiseCache = PromiseCache;

@@ -259,0 +219,0 @@ function safeListener(f) {

{
"name": "@push-rpc/core",
"version": "1.7.1",
"version": "1.8.0",
"main": "dist/index.js",

@@ -21,3 +21,3 @@ "types": "dist/index.d.ts",

},
"gitHead": "a5bdea5151a3b21cc20762664290359caf6cb59f"
"gitHead": "8a5ba0d8a336a598746903ab25c1601e5033a765"
}

@@ -145,3 +145,3 @@ import {RpcSession} from "./RpcSession"

connectionLoop() {
return new Promise(async resolve => {
return new Promise<void>(async resolve => {
let onFirstConnection = resolve

@@ -152,3 +152,3 @@ let errorDelay = 0

// connect, and wait for ...
await new Promise(resolve => {
await new Promise<void>(resolve => {
// 1. ...disconnected

@@ -155,0 +155,0 @@ const connectionPromise = this.connect(resolve)

@@ -15,3 +15,3 @@ import {LocalTopicImpl} from "./local"

import {createMessageId, message} from "./utils"
import * as jsonCircularStringify from "json-stringify-safe"
import jsonCircularStringify from "json-stringify-safe"

@@ -103,3 +103,3 @@ export interface RpcSessionListeners {

disconnect() {
return new Promise(resolve => {
return new Promise<void>(resolve => {
if (!this.socket) {

@@ -106,0 +106,0 @@ resolve()

import * as UUID from "uuid-js"
import * as jsonCircularStringify from "json-stringify-safe"
import jsonCircularStringify from "json-stringify-safe"
import {DataConsumer, MessageType, Middleware, RemoteTopic} from "./rpc"

@@ -4,0 +4,0 @@ import {PING_MESSAGE, PONG_MESSAGE} from "./RpcSession"

@@ -146,3 +146,3 @@ import {assert} from "chai"

abstract async method()
abstract method()
}

@@ -36,5 +36,5 @@ import {createRpcClient, createRpcServer, RpcClientOptions, RpcServer} from "../src"

() =>
new Promise(resolve => {
new Promise<void>(resolve => {
if (wss) {
wss.close(resolve)
wss.close(() => resolve())
} else {

@@ -41,0 +41,0 @@ resolve()

{
"extends": "../../tsconfig.json",
"include": ["src/**/*.ts"],
"compilerOptions": {
"target": "es5",
"outDir": "dist",
"lib": [
"es6"
],
"declaration": true
},
"include": ["src/**/*.ts"]
"outDir": "dist"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc