UNPKG

ng4-signalr

Version:
400 lines (385 loc) 14.9 kB
import { Subject } from 'rxjs'; import * as i0 from '@angular/core'; import { InjectionToken, Injectable, Inject, NgZone, NgModule } from '@angular/core'; class ConnectionStatus { constructor(value) { if (value == null || value < 0) { throw new Error("Failed to create ConnectionStatus. Argument 'name' can not be null or empty."); } this._value = value; } get value() { return this._value; } get name() { return ConnectionStatus.names[Number.parseInt(this._value.toString(), 10)]; } toString() { return this.name; } equals(other) { if (other == null) { return false; } return this._value === other.value; } } ConnectionStatus.names = ['connecting', 'connected', 'reconnecting', '', 'disconnected']; // @dynamic class ConnectionStatuses { static get connecting() { return ConnectionStatuses.statuses[0]; } static get connected() { return ConnectionStatuses.statuses[1]; } static get reconnecting() { return ConnectionStatuses.statuses[2]; } static get disconnected() { return ConnectionStatuses.statuses[3]; } } ConnectionStatuses.statuses = [ new ConnectionStatus(0), new ConnectionStatus(1), new ConnectionStatus(2), new ConnectionStatus(4) ]; class BroadcastEventListener extends Subject { constructor(event) { super(); this.event = event; if (event == null || event === '') { throw new Error('Failed to create BroadcastEventListener. Argument \'event\' can not be empty'); } } } class SignalRConnection { constructor(jConnection, jProxies, zone, configuration) { this._jProxies = jProxies; this._defaultProxy = jProxies.values().next().value; this._jConnection = jConnection; this._zone = zone; this._errors = this.wireUpErrorsAsObservable(); this._status = this.wireUpStatusEventsAsObservable(); this._configuration = configuration; } get errors() { return this._errors; } get status() { return this._status; } setQs(qs) { this._jConnection.qs = qs; } getQs() { return this._jConnection.qs; } start() { console.log('Starting connection', this._jConnection); const jTransports = this.convertTransports(this._configuration.transport); const $promise = new Promise((resolve, reject) => { this._jConnection .start({ jsonp: this._configuration.jsonp, transport: jTransports, withCredentials: this._configuration.withCredentials, }) .done(() => { console.log('Connection established, ID: ' + this._jConnection.id); console.log('Connection established, Transport: ' + this._jConnection.transport.name); resolve(this); }) .fail((error) => { console.log('Could not connect'); reject('Failed to connect. Error: ' + error.message); // ex: Error during negotiation request. }); }); return $promise; } stop() { console.log('Stopping connection', this._jConnection); this._jConnection.stop(); } get id() { return this._jConnection.id; } invoke(method, sproxy, ...parameters) { if (method == null) { throw new Error('SignalRConnection: Failed to invoke. Argument \'method\' can not be null'); } this.log(`SignalRConnection. Start invoking \'${method}\'...`); const $promise = new Promise((resolve, reject) => { this.getCurrentProxy(sproxy).invoke(method, ...parameters) .done((result) => { this.log(`\'${method}\' invoked succesfully. Resolving promise...`); resolve(result); this.log(`Promise resolved.`); }) .fail((err) => { console.log(`Invoking \'${method}\' failed. Rejecting promise...`); reject(err); console.log(`Promise rejected.`); }); }); return $promise; } listen(listener, sproxy) { if (listener == null) { throw new Error('Failed to listen. Argument \'listener\' can not be null'); } this.log(`SignalRConnection: Starting to listen to server event with name ${listener.event}`); this.getCurrentProxy(sproxy).on(listener.event, (...args) => { this._zone.run(() => { let casted = null; if (args.length > 0) { casted = args[0]; this.log('SignalRConnection.proxy.on invoked. Calling listener next() ...'); listener.next(casted); this.log('listener next() called.'); } }); }); } listenFor(event, sproxy) { if (event == null || event === '') { throw new Error('Failed to listen. Argument \'event\' can not be empty'); } const listener = new BroadcastEventListener(event); this.listen(listener, sproxy); return listener; } getCurrentProxy(sproxy) { if (!sproxy) { return this._defaultProxy; } else { return this._jProxies.get(sproxy); } } convertTransports(transports) { if (transports instanceof Array) { return transports.map((t) => t.name); } return transports.name; } wireUpErrorsAsObservable() { const sError = new Subject(); this._jConnection.error((error) => { // this._zone.run(() => { /*errors don't need to run in a zone*/ sError.next(error); // }); }); return sError; } wireUpStatusEventsAsObservable() { const sStatus = new Subject(); // aggregate all signalr connection status handlers into 1 observable. // handler wire up, for signalr connection status callback. this._jConnection.stateChanged((change) => { this._zone.run(() => { sStatus.next(new ConnectionStatus(change.newState)); }); }); return sStatus.asObservable(); } /*private onBroadcastEventReceived<T>(listener: BroadcastEventListener<T>, ...args: any[]) { this.log('SignalRConnection.proxy.on invoked. Calling listener next() ...'); let casted: T = null; if (args.length > 0) { casted = (args[0] as T); } this._zone.run(() => { listener.next(casted); }); this.log('listener next() called.'); }*/ log(...args) { if (this._jConnection.logging === false) { return; } console.log(args.join(', ')); } } class ConnectionTransport { constructor(name) { if (name == null || name === "") { throw new Error("Failed to create ConnectionTransport. Argument 'name' can not be null or empty."); } this._name = name; } get name() { return this._name; } toString() { return this._name; } equals(other) { if (other == null) { return false; } return this._name === other.name; } } // @dynamic class ConnectionTransports { static get foreverFrame() { return ConnectionTransports.transports[0]; } static get longPolling() { return ConnectionTransports.transports[1]; } static get serverSentEvents() { return ConnectionTransports.transports[2]; } static get webSockets() { return ConnectionTransports.transports[3]; } static get auto() { return ConnectionTransports.transports[4]; } } ConnectionTransports.transports = [ new ConnectionTransport("foreverFrame"), new ConnectionTransport("longPolling"), new ConnectionTransport("serverSentEvents"), new ConnectionTransport("webSockets"), new ConnectionTransport("auto"), ]; class SignalRConfiguration { constructor() { this.hubNames = []; this.logging = false; this.qs = null; this.url = null; this.jsonp = false; this.withCredentials = false; this.transport = ConnectionTransports.auto; } } const SIGNALR_JCONNECTION_TOKEN = new InjectionToken('SIGNALR_JCONNECTION_TOKEN'); class SignalR { constructor(configuration, zone, jHubConnectionFn) { this._configuration = configuration; this._zone = zone; this._jHubConnectionFn = jHubConnectionFn; } createConnection(options) { const configuration = this.merge(options ? options : {}); try { const serializedQs = JSON.stringify(configuration.qs); const serializedTransport = JSON.stringify(configuration.transport); if (configuration.logging) { console.log(`Creating connecting with multiple HUBS support!...`); console.log(`configuration:[url: '${configuration.url}'] ...`); configuration.hubNames.forEach((element) => { console.log(`configuration:[hubName: '${element}'] ...`); }); console.log(`configuration:[qs: '${serializedQs}'] ...`); console.log(`configuration:[transport: '${serializedTransport}'] ...`); } } catch (err) { /* empty */ } // create connection object const jConnection = this._jHubConnectionFn(configuration.url); jConnection.logging = configuration.logging; jConnection.qs = configuration.qs; const jProxies = new Map(); configuration.hubNames.forEach((element) => { // create a proxy const jp = jConnection.createHubProxy(element); jp.on('noOp', () => { }); jProxies.set(element, jp); // !!! important. We need to register at least one function otherwise server callbacks will not work. }); const hubConnection = new SignalRConnection(jConnection, jProxies, this._zone, configuration); return hubConnection; } connect(options) { return this.createConnection(options).start(); } merge(overrides) { const merged = new SignalRConfiguration(); merged.hubNames = overrides.hubNames || this._configuration.hubNames; merged.url = overrides.url || this._configuration.url; merged.qs = overrides.qs || this._configuration.qs; merged.logging = this._configuration.logging; merged.jsonp = overrides.jsonp || this._configuration.jsonp; merged.withCredentials = overrides.withCredentials || this._configuration.withCredentials; merged.transport = overrides.transport || this._configuration.transport; return merged; } } SignalR.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalR, deps: [{ token: SignalRConfiguration }, { token: i0.NgZone }, { token: SIGNALR_JCONNECTION_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); SignalR.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalR }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalR, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: SignalRConfiguration }, { type: i0.NgZone }, { type: undefined, decorators: [{ type: Inject, args: [SIGNALR_JCONNECTION_TOKEN] }] }]; } }); const SIGNALR_CONFIGURATION = new InjectionToken('SIGNALR_CONFIGURATION'); function createSignalr(configuration, zone) { const jConnectionFn = getJConnectionFn(); return new SignalR(configuration, zone, jConnectionFn); } function getJConnectionFn() { const jQuery = getJquery(); const hubConnectionFn = jQuery.hubConnection; if (hubConnectionFn == null) { // tslint:disable-next-line:max-line-length throw new Error('Signalr failed to initialize. Script \'jquery.signalR.js\' is missing. Please make sure to include \'jquery.signalR.js\' script.'); } return hubConnectionFn; } function getJquery() { const jQuery = window.jQuery; if (jQuery == null) { // tslint:disable-next-line:max-line-length throw new Error('Signalr failed to initialize. Script \'jquery.js\' is missing. Please make sure to include jquery script.'); } return jQuery; } class SignalRModule { static forRoot(getSignalRConfiguration) { return { ngModule: SignalRModule, providers: [ { provide: SIGNALR_CONFIGURATION, useFactory: getSignalRConfiguration }, { deps: [SIGNALR_CONFIGURATION, NgZone], provide: SignalR, useFactory: (createSignalr) } ], }; } static forChild() { throw new Error("forChild method not implemented"); } } SignalRModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalRModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); SignalRModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: SignalRModule }); SignalRModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalRModule, providers: [{ provide: SignalR, useValue: SignalR }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SignalRModule, decorators: [{ type: NgModule, args: [{ providers: [{ provide: SignalR, useValue: SignalR }] }] }] }); /** * Generated bundle index. Do not edit. */ export { BroadcastEventListener, ConnectionStatus, ConnectionStatuses, ConnectionTransport, ConnectionTransports, SignalR, SignalRConfiguration, SignalRConnection, SignalRModule }; //# sourceMappingURL=ng4-signalr.mjs.map