@push-rpc/core
Advanced tools
Comparing version 1.7.1 to 1.8.0
@@ -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" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
150260
4345