UNPKG

nxkit

Version:

This is a collection of tools, independent of any other libraries

205 lines (204 loc) 6.94 kB
"use strict"; /* ***** BEGIN LICENSE BLOCK ***** * Distributed under the BSD license: * * Copyright (c) 2015, xuewen.chu * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of xuewen.chu nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL xuewen.chu BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ Object.defineProperty(exports, "__esModule", { value: true }); const path = require("../path"); const event_1 = require("../event"); const cli = require("../ws/cli"); const uuid_1 = require("../hash/uuid"); const errno_1 = require("../errno"); const util_1 = require("../util"); /** * @class WSConv */ class WSConv extends cli.WSConversation { constructor(path, headers) { super(path); this.m_headers = headers || {}; this.autoReconnect = 500; // 500ms auto reconnect } getRequestHeaders() { return this.m_headers; } } function urlHref(url) { var s = url.protocol == 'fmts:' ? 'wss:' : 'ws:'; s += '//' + url.host + url.path; return s; } /** * @class WSClient */ class WSClient extends cli.WSClient { constructor(host, url, headers) { super('_fmt', new WSConv(urlHref(url), headers)); this.m_host = host; this.conv.onOpen.on(e => { console.log('open ok', host.id); if (host.m_subscribe.size) { var events = []; for (var i of host.m_subscribe) events.push(i); this.call('subscribe', { events }).catch(console.error); } }); this.conv.onClose.on(e => { this.trigger('Offline', {}); }); this.addEventListener('Load', e => { this.trigger('Online', {}); }); this.addEventListener('ForceLogout', e => { console.error(`FMTService Force Logout, id=${host.id}, token=${this.conv.token}`); }); } /** * @overwrite */ handleCall(method, data, sender) { return this.m_host.handleCall(method, data, sender); } /** * @func close() close client */ close() { this.conv.close(); } } /** * @class FMTClient */ class FMTClient extends event_1.Notification { constructor(id = uuid_1.default(), url = 'fmt://localhost/', headers) { super(); this.m_subscribe = new Set(); this.onOnline = new event_1.EventNoticer('Online', this); this.onOffline = new event_1.EventNoticer('Offline', this); var u = new path.URL(url); u.setParam('id', id); this.m_id = String(id); this.m_cli = new WSClient(this, u, headers); this.m_cli.addEventForward('Online', this.onOnline); this.m_cli.addEventForward('Offline', this.onOffline); } get id() { return this.m_id; } get conv() { return this.m_cli.conv; } get loaded() { return this.m_cli.loaded; } close() { this.m_cli.close(); } that(id) { util_1.default.assert(id != this.id); return new ThatClientIMPL(this.m_cli, id); } user(id = this.id) { return this.m_cli.call('getUser', [id]); } /** * @func handleCall() */ handleCall(method, data, sender) { if (method in FMTClient.prototype) { throw Error.new(errno_1.default.ERR_FORBIDDEN_ACCESS); } var fn = this[method]; if (typeof fn != 'function') { throw Error.new(String.format('"{0}" no defined function', method)); } return fn.call(this, data, sender); } /** * @func subscribe() */ subscribe(events) { events.forEach(e => this.m_subscribe.add(e)); return this.m_cli.call('subscribe', { events }); } /** * @func unsubscribe() */ unsubscribe(events) { events.forEach(e => this.m_subscribe.delete(e)); return this.m_cli.call('unsubscribe', { events }); } getNoticer(name) { if (!this.hasNoticer(name)) { this.m_cli.addEventForward(name, super.getNoticer(name)); // Forward event } return super.getNoticer(name); } triggerListenerChange(name, count, change) { if (change > 0) { // add if (!this.m_subscribe.has(name)) { this.m_subscribe.add(name); this.m_cli.call('subscribe', { events: [name] }).catch(console.error); // subscribe event } } else if (count === 0) { // del if (this.m_subscribe.has(name)) { this.m_subscribe.delete(name); this.m_cli.call('unsubscribe', { events: [name] }).catch(console.error); // unsubscribe event } } } } exports.FMTClient = FMTClient; class ThatClientIMPL { constructor(cli, id) { this.m_cli = cli; this.m_id = String(id); } get id() { return this.m_id; } hasOnline() { return this.m_cli.call('hasOnline', [this.m_id]); } trigger(event, data) { return this.m_cli.send('triggerTo', [this.m_id, event, data]); } call(method, data, timeout = cli.METHOD_CALL_TIMEOUT) { timeout = Number(timeout) || cli.METHOD_CALL_TIMEOUT; var args = [this.m_id, method, data]; if (timeout != cli.METHOD_CALL_TIMEOUT) args.push(timeout); return this.m_cli.call('callTo', args, timeout); } send(method, data) { return this.m_cli.send('sendTo', [this.m_id, method, data]); } user() { return this.m_cli.call('getUser', [this.m_id]); } }