Creating Stores and using Observables
Change-Id: I214692e64df065beaddee0e0ec8759de540c269d
diff --git a/package.json b/package.json
index a42a6cc..bd5da85 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,7 @@
"angular-resource": "^1.6.0",
"angular-ui-router": "1.0.0-beta.1",
"lodash": "^4.17.2",
+ "rxjs": "^5.0.1",
"socket.io-client": "^1.7.2"
},
"devDependencies": {
@@ -68,6 +69,7 @@
"build": "gulp",
"start": "gulp serve",
"serve:dist": "gulp serve:dist",
+ "pretest": "npm run lint",
"test": "gulp test",
"test:auto": "gulp test:auto",
"config": "gulp config",
diff --git a/src/app/config/app.config.ts b/src/app/config/app.config.ts
index 2357f77..7b6fa12 100644
--- a/src/app/config/app.config.ts
+++ b/src/app/config/app.config.ts
@@ -6,6 +6,6 @@
}
export const AppConfig: IAppConfig = {
- apiEndpoint: 'http://xos-rest-gw:3000/api',
- websocketClient: 'http://xos-rest-gw:3000'
+ apiEndpoint: 'http://xos.dev:3000/api',
+ websocketClient: 'http://xos.dev:3000'
};
diff --git a/src/app/core/login/login.ts b/src/app/core/login/login.ts
index 51dc7c9..e5881dd 100644
--- a/src/app/core/login/login.ts
+++ b/src/app/core/login/login.ts
@@ -1,4 +1,4 @@
-import {AuthService} from '../../rest/auth.rest';
+import {AuthService} from '../../datasources/rest/auth.rest';
class LoginCtrl {
static $inject = ['AuthService', '$state'];
diff --git a/src/app/core/table/table.scss b/src/app/core/table/table.scss
new file mode 100644
index 0000000..fbf6ee7
--- /dev/null
+++ b/src/app/core/table/table.scss
@@ -0,0 +1,41 @@
+table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 20px;
+ border-collapse: collapse !important;
+ background: darken(grey, 20);
+ border: 1px solid darken(grey, 35);
+
+ td, th {
+ }
+ > tbody > tr > th,
+ > tfoot > tr > th,
+ > thead > tr > td,
+ > tbody > tr > td,
+ > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #ddd;
+ }
+ > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #ddd;
+ text-align: left;
+ padding: 8px;
+ }
+ > caption + thead > tr:first-child > th,
+ > colgroup + thead > tr:first-child > th,
+ > thead:first-child > tr:first-child > th,
+ > caption + thead > tr:first-child > td,
+ > colgroup + thead > tr:first-child > td,
+ > thead:first-child > tr:first-child > td {
+ border-top: 0;
+ }
+ > tbody + tbody {
+ border-top: 2px solid #ddd;
+ }
+ .table .table {
+ background-color: #fff;
+ }
+}
\ No newline at end of file
diff --git a/src/app/core/table/table.ts b/src/app/core/table/table.ts
index 43360c6..a837600 100644
--- a/src/app/core/table/table.ts
+++ b/src/app/core/table/table.ts
@@ -1,6 +1,7 @@
// TODO fininsh to import all methods from https://github.com/opencord/ng-xos-lib/blob/master/src/ui_components/dumbComponents/table/table.component.js
// TODO import tests
+import './table.scss';
import * as _ from 'lodash';
interface IXosTableCgfOrder {
@@ -19,8 +20,6 @@
public columns: any[];
public orderBy: string;
public reverse: boolean;
-
- private data: any[];
private config: IXosTableCfg;
@@ -34,13 +33,13 @@
}
// handle default ordering
- if (this.config.order && angular.isObject(this.config.order)){
+ if (this.config.order && angular.isObject(this.config.order)) {
this.reverse = this.config.order.reverse || false;
this.orderBy = this.config.order.field || 'id';
}
// if columns with type 'custom' are provided
- // check that a custom formatte3 is provided too
+ // check that a custom formatter is provided too
let customCols = _.filter(this.config.columns, {type: 'custom'});
if (angular.isArray(customCols) && customCols.length > 0) {
_.forEach(customCols, (col) => {
@@ -51,7 +50,7 @@
}
// if columns with type 'icon' are provided
- // check that a custom formatte3 is provided too
+ // check that a custom formatter is provided too
let iconCols = _.filter(this.config.columns, {type: 'icon'});
if (angular.isArray(iconCols) && iconCols.length > 0) {
_.forEach(iconCols, (col) => {
diff --git a/src/app/datasources/helpers/store.helpers.ts b/src/app/datasources/helpers/store.helpers.ts
new file mode 100644
index 0000000..dfb1e7a
--- /dev/null
+++ b/src/app/datasources/helpers/store.helpers.ts
@@ -0,0 +1,34 @@
+import {BehaviorSubject} from 'rxjs';
+import * as _ from 'lodash';
+import {IWSEvent} from '../websocket/global';
+
+export interface IStoreHelpersService {
+ updateCollection(event: IWSEvent, subject: BehaviorSubject<any>): BehaviorSubject<any>;
+}
+
+export class StoreHelpers {
+ public updateCollection(event: IWSEvent, subject: BehaviorSubject<any>): BehaviorSubject<any> {
+ const collection: any[] = subject.value;
+ const index: number = _.findIndex(collection, (i) => {
+ return i.id === event.msg.object.id;
+ });
+ const exist: boolean = index > -1;
+ const isDeleted: boolean = _.includes(event.msg.changed_fields, 'deleted');
+ // remove
+ if (exist && isDeleted) {
+ _.remove(collection, {id: event.msg.object.id});
+ }
+ // Replace item at index using native splice
+ else if (exist && !isDeleted) {
+ collection.splice(index, 1, event.msg.object);
+ }
+ // if the element is not deleted add it
+ else if (!exist && !isDeleted) {
+ collection.push(event.msg.object);
+ }
+
+ subject.next(collection);
+
+ return subject;
+ }
+}
diff --git a/src/app/datasources/index.ts b/src/app/datasources/index.ts
new file mode 100644
index 0000000..4473541
--- /dev/null
+++ b/src/app/datasources/index.ts
@@ -0,0 +1,20 @@
+import {CoreRest} from './rest/core.rest';
+import {SlicesRest} from './rest/slices.rest';
+import {AuthService} from './rest/auth.rest';
+import {WebSocketEvent} from './websocket/global';
+import {SliceStore} from './stores/slices.store';
+import {StoreHelpers} from './helpers/store.helpers';
+
+export const xosRest = 'xosDataSources';
+
+angular
+ .module('xosDataSources', ['ngCookies'])
+ .service('CoreRest', CoreRest)
+ .service('SlicesRest', SlicesRest)
+ .service('AuthService', AuthService)
+ .service('WebSocket', WebSocketEvent);
+
+angular
+ .module('xosDataSources')
+ .service('StoreHelpers', StoreHelpers)
+ .service('SlicesStore', SliceStore);
diff --git a/src/app/rest/auth.rest.ts b/src/app/datasources/rest/auth.rest.ts
similarity index 95%
rename from src/app/rest/auth.rest.ts
rename to src/app/datasources/rest/auth.rest.ts
index c72b51e..a94599a 100644
--- a/src/app/rest/auth.rest.ts
+++ b/src/app/datasources/rest/auth.rest.ts
@@ -1,4 +1,4 @@
-import {AppConfig} from '../config/app.config';
+import {AppConfig} from '../../config/app.config';
import IHttpPromiseCallbackArg = angular.IHttpPromiseCallbackArg;
export interface IAuthRequestData {
username: string;
diff --git a/src/app/rest/core.rest.ts b/src/app/datasources/rest/core.rest.ts
similarity index 87%
rename from src/app/rest/core.rest.ts
rename to src/app/datasources/rest/core.rest.ts
index aace3aa..2c10e10 100644
--- a/src/app/rest/core.rest.ts
+++ b/src/app/datasources/rest/core.rest.ts
@@ -1,4 +1,4 @@
-import {AppConfig} from '../config/app.config';
+import {AppConfig} from '../../config/app.config';
export class CoreRest {
/** @ngInject */
diff --git a/src/app/datasources/rest/slices.rest.ts b/src/app/datasources/rest/slices.rest.ts
new file mode 100644
index 0000000..a5b7e5c
--- /dev/null
+++ b/src/app/datasources/rest/slices.rest.ts
@@ -0,0 +1,21 @@
+import {AppConfig} from '../../config/app.config';
+
+export interface IXosResourceService {
+ getResource(): ng.resource.IResourceClass<any>;
+}
+
+export class SlicesRest implements IXosResourceService {
+ static $inject = ['$resource'];
+ private resource: angular.resource.IResourceClass<any>;
+
+ /** @ngInject */
+ constructor(
+ private $resource: ng.resource.IResourceService
+ ) {
+ this.resource = this.$resource(`${AppConfig.apiEndpoint}/core/slices/`);
+ }
+
+ public getResource(): ng.resource.IResourceClass<ng.resource.IResource<any>> {
+ return this.resource;
+ }
+}
diff --git a/src/app/datasources/stores/slices.store.ts b/src/app/datasources/stores/slices.store.ts
new file mode 100644
index 0000000..9c3389f
--- /dev/null
+++ b/src/app/datasources/stores/slices.store.ts
@@ -0,0 +1,43 @@
+/// <reference path="../../../../typings/index.d.ts"/>
+
+import {BehaviorSubject, Observable} from 'rxjs/Rx';
+import {IWSEvent, IWSEventService} from '../websocket/global';
+import {IXosResourceService} from '../rest/slices.rest';
+import {IStoreHelpersService} from '../helpers/store.helpers';
+
+export interface IStoreService {
+ query(): Observable<any>;
+}
+
+export class SliceStore {
+ static $inject = ['WebSocket', 'StoreHelpers', 'SlicesRest'];
+ private _slices: BehaviorSubject<any[]> = new BehaviorSubject([]);
+ constructor(
+ private webSocket: IWSEventService,
+ private storeHelpers: IStoreHelpersService,
+ private sliceService: IXosResourceService
+ ) {
+ this.loadInitialData();
+ this.webSocket.list()
+ .filter((e: IWSEvent) => e.model === 'Slice')
+ .subscribe(
+ (event: IWSEvent) => {
+ this.storeHelpers.updateCollection(event, this._slices);
+ }
+ );
+ }
+
+ query() {
+ return this._slices.asObservable();
+ }
+
+ private loadInitialData() {
+ this.sliceService.getResource().query().$promise
+ .then(
+ res => {
+ this._slices.next(res);
+ },
+ err => console.log('Error retrieving Slices', err)
+ );
+ }
+}
diff --git a/src/app/datasources/websocket/global.ts b/src/app/datasources/websocket/global.ts
new file mode 100644
index 0000000..aaf142a
--- /dev/null
+++ b/src/app/datasources/websocket/global.ts
@@ -0,0 +1,31 @@
+import * as io from 'socket.io-client';
+import {Subject, Observable} from 'rxjs/Rx';
+import {AppConfig} from '../../config/app.config';
+
+export interface IWSEvent {
+ model: string;
+ msg: {
+ changed_fields: string[],
+ object?: any,
+ pk?: number
+ };
+}
+
+export interface IWSEventService {
+ list(): Observable<IWSEvent>;
+}
+
+export class WebSocketEvent {
+ private _events: Subject<IWSEvent> = new Subject<IWSEvent>();
+ private socket;
+ constructor() {
+ console.log('socket.io');
+ this.socket = io(AppConfig.websocketClient);
+ this.socket.on('event', (data: IWSEvent): void => {
+ this._events.next(data);
+ });
+ }
+ list() {
+ return this._events.asObservable();
+ }
+}
diff --git a/src/app/rest/index.ts b/src/app/rest/index.ts
deleted file mode 100644
index d28084b..0000000
--- a/src/app/rest/index.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import {CoreRest} from './core.rest';
-import {SlicesRest} from './slices.rest';
-import {AuthService} from './auth.rest';
-
-export const xosRest = 'xosRest';
-
-angular
- .module('xosRest', ['ngCookies'])
- .service('CoreRest', CoreRest)
- .service('SlicesRest', SlicesRest)
- .service('AuthService', AuthService);
diff --git a/src/app/rest/slices.rest.ts b/src/app/rest/slices.rest.ts
deleted file mode 100644
index 0d1d8a1..0000000
--- a/src/app/rest/slices.rest.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import {AppConfig} from '../config/app.config';
-
-export interface IXosResourceService {
- getResource(): ng.resource.IResourceClass<any>;
-}
-
-export class SlicesRest implements IXosResourceService{
- static $inject = ['$resource'];
-
- /** @ngInject */
- constructor(
- private $resource: ng.resource.IResourceService
- ) {
-
- }
-
- public getResource(): ng.resource.IResourceClass<ng.resource.IResource<any>> {
- return this.$resource(`${AppConfig.apiEndpoint}/core/slices/`);
- }
-}
diff --git a/src/app/views/crud/crud.ts b/src/app/views/crud/crud.ts
index b35c104..853669c 100644
--- a/src/app/views/crud/crud.ts
+++ b/src/app/views/crud/crud.ts
@@ -1,37 +1,42 @@
-import {IXosResourceService} from '../../rest/slices.rest';
import {IXosTableCfg} from '../../core/table/table';
+import {IStoreService} from '../../datasources/stores/slices.store';
export interface IXosCrudData {
title: string;
- resource: string;
+ store: string;
xosTableCfg: IXosTableCfg;
}
class CrudController {
- static $inject = ['$state', '$injector'];
+ // TODO dynamically inject store
+ static $inject = ['$state', '$injector', '$scope'];
public data: IXosCrudData;
public tableCfg: IXosTableCfg;
public title: string;
- public resourceName: string;
- public resource: ng.resource.IResourceClass<ng.resource.IResource<any>>;
+ public storeName: string;
+ public store: IStoreService;
public tableData: any[];
constructor(
private $state: angular.ui.IStateService,
- private $injector: angular.Injectable<any>
+ private $injector: angular.Injectable<any>,
+ private $scope: angular.IScope
) {
this.data = this.$state.current.data;
- console.log('xosCrud', this.data);
this.tableCfg = this.data.xosTableCfg;
this.title = this.data.title;
- this.resourceName = this.data.resource;
- this.resource = this.$injector.get(this.resourceName).getResource();
+ this.storeName = this.data.store;
+ this.store = this.$injector.get(this.storeName);
- this.resource
- .query().$promise
- .then(res => {
- this.tableData = res;
- });
+ this.store.query()
+ .subscribe(
+ (event) => {
+ // NOTE Observable mess with $digest cycles, we need to schedule the expression later
+ $scope.$evalAsync(() => {
+ this.tableData = event;
+ });
+ }
+ );
}
}
diff --git a/src/index.scss b/src/index.scss
index 2cbe173..3d155ca 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -36,6 +36,7 @@
flex-basis: 90%;
background: darken(grey, 25);
padding: 20px;
+ color: #eee;
}
}
@@ -49,12 +50,6 @@
font-size: 1.5rem;
margin: 1rem;
}
-.header-date {
- flex: 1;
- text-align: right;
- margin: 1rem;
- white: white;
-}
.footer {
padding: 0.5rem;
@@ -63,3 +58,7 @@
text-align: center;
color: white;
}
+
+h1 {
+ color: #fff;
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 66a32f1..c654e52 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -11,7 +11,7 @@
import './index.scss';
import {xosCore} from './app/core/index';
-import {xosRest} from './app/rest/index';
+import {xosRest} from './app/datasources/index';
import {xosViews} from './app/views/index';
import {interceptorConfig, userStatusInterceptor, CredentialsInterceptor} from './interceptors';
diff --git a/src/routes.ts b/src/routes.ts
index 8290e9a..d5a0800 100644
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -29,7 +29,7 @@
component: `xosCrud`,
data: {
title: 'Slices',
- resource: 'SlicesRest',
+ store: 'SlicesStore',
xosTableCfg: {
columns: [
{
diff --git a/typings.json b/typings.json
index 700269c..ac768af 100644
--- a/typings.json
+++ b/typings.json
@@ -8,6 +8,7 @@
"es6-shim": "registry:dt/es6-shim#0.31.2+20160602141504",
"jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a",
"jquery": "github:DefinitelyTyped/DefinitelyTyped/jquery/jquery.d.ts#dc9dabe74a5be62613b17a3605309783a12ff28a",
- "require": "registry:dt/require#2.1.20+20160316155526"
+ "require": "registry:dt/require#2.1.20+20160316155526",
+ "socket.io-client": "registry:dt/socket.io-client#1.4.4+20160317120654"
}
}
diff --git a/typings/globals/socket.io-client/index.d.ts b/typings/globals/socket.io-client/index.d.ts
new file mode 100644
index 0000000..db58959
--- /dev/null
+++ b/typings/globals/socket.io-client/index.d.ts
@@ -0,0 +1,663 @@
+// Generated by typings
+// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/socket.io-client/socket.io-client.d.ts
+declare var io: SocketIOClientStatic;
+
+declare module 'socket.io-client' {
+ export = io;
+}
+
+interface SocketIOClientStatic {
+
+ /**
+ * Looks up an existing 'Manager' for multiplexing. If the user summons:
+ * 'io( 'http://localhost/a' );'
+ * 'io( 'http://localhost/b' );'
+ *
+ * We reuse the existing instance based on the same scheme/port/host, and
+ * we initialize sockets for each namespace. If autoConnect isn't set to
+ * false in the options, then we'll automatically connect
+ * @param uri The uri that we'll connect to, including the namespace, where '/' is the default one (e.g. http://localhost:4000/somenamespace)
+ * @opts Any connect options that we want to pass along
+ * @return A Socket object
+ */
+ ( uri: string, opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Socket;
+
+ /**
+ * Auto-connects to the window location and defalt namespace.
+ * E.g. window.protocol + '//' + window.host + ':80/'
+ * @opts Any connect options that we want to pass along
+ * @return A Socket object
+ */
+ ( opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Socket;
+
+ /**
+ * @see the default constructor (io(uri, opts))
+ */
+ connect( uri: string, opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Socket;
+
+ /**
+ * @see the default constructor (io(opts))
+ */
+ connect( opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Socket;
+
+ /**
+ * The socket.io protocol revision number this client works with
+ * @default 4
+ */
+ protocol: number;
+
+ /**
+ * Socket constructor - exposed for the standalone build
+ */
+ Socket: SocketIOClient.Socket;
+
+ /**
+ * Manager constructor - exposed for the standalone build
+ */
+ Manager: SocketIOClient.ManagerStatic;
+}
+
+declare namespace SocketIOClient {
+
+ /**
+ * The base emiter class, used by Socket and Manager
+ */
+ interface Emitter {
+ /**
+ * Adds a listener for a particular event. Calling multiple times will add
+ * multiple listeners
+ * @param event The event that we're listening for
+ * @param fn The function to call when we get the event. Parameters depend on the
+ * event in question
+ * @return This Emitter
+ */
+ on( event: string, fn: Function ):Emitter;
+
+ /**
+ * @see on( event, fn )
+ */
+ addEventListener( event: string, fn: Function ):Emitter;
+
+ /**
+ * Adds a listener for a particular event that will be invoked
+ * a single time before being automatically removed
+ * @param event The event that we're listening for
+ * @param fn The function to call when we get the event. Parameters depend on
+ * the event in question
+ * @return This Emitter
+ */
+ once( event: string, fn: Function ):Emitter;
+
+ /**
+ * Removes a listener for a particular type of event. This will either
+ * remove a specific listener, or all listeners for this type of event
+ * @param event The event that we want to remove the listener of
+ * @param fn The function to remove, or null if we want to remove all functions
+ * @return This Emitter
+ */
+ off( event: string, fn?: Function ):Emitter;
+
+ /**
+ * @see off( event, fn )
+ */
+ removeListener( event: string, fn?: Function ):Emitter;
+
+ /**
+ * @see off( event, fn )
+ */
+ removeEventListener( event: string, fn?: Function ):Emitter;
+
+ /**
+ * Removes all event listeners on this object
+ * @return This Emitter
+ */
+ removeAllListeners():Emitter;
+
+ /**
+ * Emits 'event' with the given args
+ * @param event The event that we want to emit
+ * @param args Optional arguments to emit with the event
+ * @return Emitter
+ */
+ emit( event: string, ...args: any[] ):Emitter;
+
+ /**
+ * Returns all the callbacks for a particular event
+ * @param event The event that we're looking for the callbacks of
+ * @return An array of callback Functions, or an empty array if we don't have any
+ */
+ listeners( event: string ):Function[];
+
+ /**
+ * Returns if we have listeners for a particular event
+ * @param event The event that we want to check if we've listeners for
+ * @return True if we have listeners for this event, false otherwise
+ */
+ hasListeners( event: string ):boolean;
+ }
+
+ /**
+ * The Socket static interface
+ */
+ interface SocketStatic {
+
+ /**
+ * Creates a new Socket, used for communicating with a specific namespace
+ * @param io The Manager that's controlling this socket
+ * @param nsp The namespace that this socket is for (@default '/')
+ * @return A new Socket
+ */
+ ( io: SocketIOClient.Manager, nsp: string ): Socket;
+
+ /**
+ * Creates a new Socket, used for communicating with a specific namespace
+ * @param io The Manager that's controlling this socket
+ * @param nsp The namespace that this socket is for (@default '/')
+ * @return A new Socket
+ */
+ new ( url: string, opts: any ): SocketIOClient.Manager;
+ }
+
+ /**
+ * The Socket that we use to connect to a Namespace on the server
+ */
+ interface Socket extends Emitter {
+
+ /**
+ * The Manager that's controller this socket
+ */
+ io: SocketIOClient.Manager;
+
+ /**
+ * The namespace that this socket is for
+ * @default '/'
+ */
+ nsp: string;
+
+ /**
+ * The ID of the socket; matches the server ID and is set when we're connected, and cleared
+ * when we're disconnected
+ */
+ id: string;
+
+ /**
+ * Are we currently connected?
+ * @default false
+ */
+ connected: boolean;
+
+ /**
+ * Are we currently disconnected?
+ * @default true
+ */
+ disconnected: boolean;
+
+ /**
+ * Opens our socket so that it connects. If the 'autoConnect' option for io is
+ * true (default), then this is called automatically when the Socket is created
+ */
+ open(): Socket;
+
+ /**
+ * @see open();
+ */
+ connect(): Socket;
+
+ /**
+ * Sends a 'message' event
+ * @param args Any optional arguments that we want to send
+ * @see emit
+ * @return This Socket
+ */
+ send( ...args: any[] ):Socket;
+
+ /**
+ * An override of the base emit. If the event is one of:
+ * connect
+ * connect_error
+ * connect_timeout
+ * connecting
+ * disconnect
+ * error
+ * reconnect
+ * reconnect_attempt
+ * reconnect_failed
+ * reconnect_error
+ * reconnecting
+ * ping
+ * pong
+ * then the event is emitted normally. Otherwise, if we're connected, the
+ * event is sent. Otherwise, it's buffered.
+ *
+ * If the last argument is a function, then it will be called
+ * as an 'ack' when the response is received. The parameter(s) of the
+ * ack will be whatever data is returned from the event
+ * @param event The event that we're emitting
+ * @param args Optional arguments to send with the event
+ * @return This Socket
+ */
+ emit( event: string, ...args: any[] ):Socket;
+
+ /**
+ * Disconnects the socket manually
+ * @return This Socket
+ */
+ close():Socket;
+
+ /**
+ * @see close()
+ */
+ disconnect():Socket;
+
+ /**
+ * Sets the compress flag.
+ * @param compress If `true`, compresses the sending data
+ * @return this Socket
+ */
+ compress(compress: boolean):Socket;
+ }
+
+ /**
+ * The Manager static interface
+ */
+ interface ManagerStatic {
+ /**
+ * Creates a new Manager
+ * @param uri The URI that we're connecting to (e.g. http://localhost:4000)
+ * @param opts Any connection options that we want to use (and pass to engine.io)
+ * @return A Manager
+ */
+ ( uri: string, opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Manager;
+
+ /**
+ * Creates a new Manager with the default URI (window host)
+ * @param opts Any connection options that we want to use (and pass to engine.io)
+ */
+ ( opts: SocketIOClient.ConnectOpts ):SocketIOClient.Manager;
+
+ /**
+ * @see default constructor
+ */
+ new ( uri: string, opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Manager;
+
+ /**
+ * @see default constructor
+ */
+ new ( opts: SocketIOClient.ConnectOpts ):SocketIOClient.Manager;
+ }
+
+ /**
+ * The Manager class handles all the Namespaces and Sockets that we're using
+ */
+ interface Manager extends Emitter {
+
+ /**
+ * All the namespaces currently controlled by this Manager, and the Sockets
+ * that we're using to communicate with them
+ */
+ nsps: { [namespace:string]: Socket };
+
+ /**
+ * The connect options that we used when creating this Manager
+ */
+ opts: SocketIOClient.ConnectOpts;
+
+ /**
+ * The state of the Manager. Either 'closed', 'opening', or 'open'
+ */
+ readyState: string;
+
+ /**
+ * The URI that this manager is for (host + port), e.g. 'http://localhost:4000'
+ */
+ uri: string;
+
+ /**
+ * The currently connected sockets
+ */
+ connecting: Socket[];
+
+ /**
+ * If we should auto connect (also used when creating Sockets). Set via the
+ * opts object
+ */
+ autoConnect: boolean;
+
+ /**
+ * Gets if we should reconnect automatically
+ * @default true
+ */
+ reconnection(): boolean;
+
+ /**
+ * Sets if we should reconnect automatically
+ * @param v True if we should reconnect automatically, false otherwise
+ * @default true
+ * @return This Manager
+ */
+ reconnection( v: boolean ): Manager;
+
+ /**
+ * Gets the number of reconnection attempts we should try before giving up
+ * @default Infinity
+ */
+ reconnectionAttempts(): number;
+
+ /**
+ * Sets the number of reconnection attempts we should try before giving up
+ * @param v The number of attempts we should do before giving up
+ * @default Infinity
+ * @return This Manager
+ */
+ reconnectionAttempts( v: number ): Manager;
+
+ /**
+ * Gets the delay in milliseconds between each reconnection attempt
+ * @default 1000
+ */
+ reconnectionDelay(): number;
+
+ /**
+ * Sets the delay in milliseconds between each reconnection attempt
+ * @param v The delay in milliseconds
+ * @default 1000
+ * @return This Manager
+ */
+ reconnectionDelay( v: number ): Manager;
+
+ /**
+ * Gets the max reconnection delay in milliseconds between each reconnection
+ * attempt
+ * @default 5000
+ */
+ reconnectionDelayMax(): number;
+
+ /**
+ * Sets the max reconnection delay in milliseconds between each reconnection
+ * attempt
+ * @param v The max reconnection dleay in milliseconds
+ * @return This Manager
+ */
+ reconnectionDelayMax( v: number ): Manager;
+
+ /**
+ * Gets the randomisation factor used in the exponential backoff jitter
+ * when reconnecting
+ * @default 0.5
+ */
+ randomizationFactor(): number;
+
+ /**
+ * Sets the randomisation factor used in the exponential backoff jitter
+ * when reconnecting
+ * @param The reconnection randomisation factor
+ * @default 0.5
+ * @return This Manager
+ */
+ randomizationFactor( v: number ): Manager;
+
+ /**
+ * Gets the timeout in milliseconds for our connection attempts
+ * @default 20000
+ */
+ timeout(): number;
+
+ /**
+ * Sets the timeout in milliseconds for our connection attempts
+ * @param The connection timeout milliseconds
+ * @return This Manager
+ */
+ timeout(v: boolean): Manager;
+
+ /**
+ * Sets the current transport socket and opens our connection
+ * @param fn An optional callback to call when our socket has either opened, or
+ * failed. It can take one optional parameter of type Error
+ * @return This Manager
+ */
+ open( fn?: (err?: any) => void ): Manager;
+
+ /**
+ * @see open( fn );
+ */
+ connect( fn?: (err?: any) => void ): Manager;
+
+ /**
+ * Creates a new Socket for the given namespace
+ * @param nsp The namespace that this Socket is for
+ * @return A new Socket, or if one has already been created for this namespace,
+ * an existing one
+ */
+ socket( nsp: string ): Socket;
+ }
+
+ /**
+ * Options we can pass to the socket when connecting
+ */
+ interface ConnectOpts {
+
+ /**
+ * Should we force a new Manager for this connection?
+ * @default false
+ */
+ forceNew?: boolean;
+
+ /**
+ * Should we multiplex our connection (reuse existing Manager) ?
+ * @default true
+ */
+ multiplex?: boolean;
+
+ /**
+ * The path to get our client file from, in the case of the server
+ * serving it
+ * @default '/socket.io'
+ */
+ path?: string;
+
+ /**
+ * Should we allow reconnections?
+ * @default true
+ */
+ reconnection?: boolean;
+
+ /**
+ * How many reconnection attempts should we try?
+ * @default Infinity
+ */
+ reconnectionAttempts?: number;
+
+ /**
+ * The time delay in milliseconds between reconnection attempts
+ * @default 1000
+ */
+ reconnectionDelay?: number;
+
+ /**
+ * The max time delay in milliseconds between reconnection attempts
+ * @default 5000
+ */
+ reconnectionDelayMax?: number;
+
+ /**
+ * Used in the exponential backoff jitter when reconnecting
+ * @default 0.5
+ */
+ randomizationFactor?: number;
+
+ /**
+ * The timeout in milliseconds for our connection attempt
+ * @default 20000
+ */
+ timeout?: number;
+
+ /**
+ * Should we automically connect?
+ * @default true
+ */
+ autoConnect?: boolean;
+
+ /**
+ * The host that we're connecting to. Set from the URI passed when connecting
+ */
+ host?: string;
+
+ /**
+ * The hostname for our connection. Set from the URI passed when connecting
+ */
+ hostname?: string;
+
+ /**
+ * If this is a secure connection. Set from the URI passed when connecting
+ */
+ secure?: boolean;
+
+ /**
+ * The port for our connection. Set from the URI passed when connecting
+ */
+ port?: string;
+
+ /**
+ * Any query parameters in our uri. Set from the URI passed when connecting
+ */
+ query?: Object;
+
+ /**
+ * `http.Agent` to use, defaults to `false` (NodeJS only)
+ */
+ agent?: string|boolean;
+
+ /**
+ * Whether the client should try to upgrade the transport from
+ * long-polling to something better.
+ * @default true
+ */
+ upgrade?: boolean;
+
+ /**
+ * Forces JSONP for polling transport.
+ */
+ forceJSONP?: boolean;
+
+ /**
+ * Determines whether to use JSONP when necessary for polling. If
+ * disabled (by settings to false) an error will be emitted (saying
+ * "No transports available") if no other transports are available.
+ * If another transport is available for opening a connection (e.g.
+ * WebSocket) that transport will be used instead.
+ * @default true
+ */
+ jsonp?: boolean;
+
+ /**
+ * Forces base 64 encoding for polling transport even when XHR2
+ * responseType is available and WebSocket even if the used standard
+ * supports binary.
+ */
+ forceBase64?: boolean;
+
+ /**
+ * Enables XDomainRequest for IE8 to avoid loading bar flashing with
+ * click sound. default to `false` because XDomainRequest has a flaw
+ * of not sending cookie.
+ * @default false
+ */
+ enablesXDR?: boolean;
+
+ /**
+ * The param name to use as our timestamp key
+ * @default 't'
+ */
+ timestampParam?: string;
+
+ /**
+ * Whether to add the timestamp with each transport request. Note: this
+ * is ignored if the browser is IE or Android, in which case requests
+ * are always stamped
+ * @default false
+ */
+ timestampRequests?: boolean;
+
+ /**
+ * A list of transports to try (in order). Engine.io always attempts to
+ * connect directly with the first one, provided the feature detection test
+ * for it passes.
+ * @default ['polling','websocket']
+ */
+ transports?: string[];
+
+ /**
+ * The port the policy server listens on
+ * @default 843
+ */
+ policyPost?: number;
+
+ /**
+ * If true and if the previous websocket connection to the server succeeded,
+ * the connection attempt will bypass the normal upgrade process and will
+ * initially try websocket. A connection attempt following a transport error
+ * will use the normal upgrade process. It is recommended you turn this on
+ * only when using SSL/TLS connections, or if you know that your network does
+ * not block websockets.
+ * @default false
+ */
+ rememberUpgrade?: boolean;
+
+ /**
+ * Are we only interested in transports that support binary?
+ */
+ onlyBinaryUpgrades?: boolean;
+
+ /**
+ * (SSL) Certificate, Private key and CA certificates to use for SSL.
+ * Can be used in Node.js client environment to manually specify
+ * certificate information.
+ */
+ pfx?: string;
+
+ /**
+ * (SSL) Private key to use for SSL. Can be used in Node.js client
+ * environment to manually specify certificate information.
+ */
+ key?: string;
+
+ /**
+ * (SSL) A string or passphrase for the private key or pfx. Can be
+ * used in Node.js client environment to manually specify certificate
+ * information.
+ */
+ passphrase?: string
+
+ /**
+ * (SSL) Public x509 certificate to use. Can be used in Node.js client
+ * environment to manually specify certificate information.
+ */
+ cert?: string;
+
+ /**
+ * (SSL) An authority certificate or array of authority certificates to
+ * check the remote host against.. Can be used in Node.js client
+ * environment to manually specify certificate information.
+ */
+ ca?: string|string[];
+
+ /**
+ * (SSL) A string describing the ciphers to use or exclude. Consult the
+ * [cipher format list]
+ * (http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) for
+ * details on the format.. Can be used in Node.js client environment to
+ * manually specify certificate information.
+ */
+ ciphers?: string;
+
+ /**
+ * (SSL) If true, the server certificate is verified against the list of
+ * supplied CAs. An 'error' event is emitted if verification fails.
+ * Verification happens at the connection level, before the HTTP request
+ * is sent. Can be used in Node.js client environment to manually specify
+ * certificate information.
+ */
+ rejectUnauthorized?: boolean;
+
+ }
+}
diff --git a/typings/globals/socket.io-client/typings.json b/typings/globals/socket.io-client/typings.json
new file mode 100644
index 0000000..f29e7a2
--- /dev/null
+++ b/typings/globals/socket.io-client/typings.json
@@ -0,0 +1,8 @@
+{
+ "resolution": "main",
+ "tree": {
+ "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/socket.io-client/socket.io-client.d.ts",
+ "raw": "registry:dt/socket.io-client#1.4.4+20160317120654",
+ "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/socket.io-client/socket.io-client.d.ts"
+ }
+}
diff --git a/typings/index.d.ts b/typings/index.d.ts
index dfa460a..b0a5fb0 100644
--- a/typings/index.d.ts
+++ b/typings/index.d.ts
@@ -7,3 +7,4 @@
/// <reference path="globals/jasmine/index.d.ts" />
/// <reference path="globals/jquery/index.d.ts" />
/// <reference path="globals/require/index.d.ts" />
+/// <reference path="globals/socket.io-client/index.d.ts" />