diff --git a/angular-signalr-hub/angular-signalr-hub-tests.ts b/angular-signalr-hub/angular-signalr-hub-tests.ts index b46ff63ac..fc08ac7d9 100644 --- a/angular-signalr-hub/angular-signalr-hub-tests.ts +++ b/angular-signalr-hub/angular-signalr-hub-tests.ts @@ -41,7 +41,7 @@ module ngSignalrTest { console.error(message); }, - stateChanged: (state: SignalRStateChange) => { + stateChanged: (state: SignalR.StateChanged) => { // your code here } }); @@ -74,4 +74,4 @@ module ngSignalrTest { Edit: boolean; Locked: boolean; } -} \ No newline at end of file +} diff --git a/angular-signalr-hub/angular-signalr-hub.d.ts b/angular-signalr-hub/angular-signalr-hub.d.ts index 302794106..d08e6356b 100644 --- a/angular-signalr-hub/angular-signalr-hub.d.ts +++ b/angular-signalr-hub/angular-signalr-hub.d.ts @@ -10,64 +10,64 @@ declare module ngSignalr { /** * Creates a new Hub connection */ - new(hubName: string, options: HubOptions) : Hub + new (hubName: string, options: HubOptions): Hub } - + class Hub { hubName: string; - connection: SignalR; - proxy: HubProxy; - + connection: SignalR.Connection; + proxy: SignalR.Hub.Proxy; + on(event: string, fn: (...args: any[]) => void): void; invoke(method: string, ...args: any[]): JQueryDeferred; disconnect(): void; connect(): JQueryPromise; } - + interface HubOptions { /** * Collection of client side callbacks */ - listeners?: { [index: string] : (...args: any[]) => void }; - + listeners?: { [index: string]: (...args: any[]) => void }; + /** * String array of server side methods which the client can call */ methods?: Array; - + /** * Sets the root path for the SignalR web service */ rootPath?: string; - + /** * Object representing additional query params to be sent on connection */ - queryParams?: { [index: string] : string }; - + queryParams?: { [index: string]: string }; + /** * Function to handle hub connection errors */ errorHandler?: (error: string) => void; - + /** * Enable/disable logging */ logging?: boolean; - + /** * Use a shared global connection or create a new one just for this hub, defaults to true */ useSharedConnection?: boolean; - + /** * Sets transport method (e.g 'longPolling' or ['webSockets', 'longPolling'] ) */ transport?: any; - + /** * Function to handle hub connection state changed event */ - stateChanged?: (state: SignalRStateChange) => void; + stateChanged?: (state: SignalR.StateChanged) => void; } } diff --git a/signalr/signalr-1.0-tests.ts b/signalr/signalr-1.0-tests.ts new file mode 100644 index 000000000..725c65c6b --- /dev/null +++ b/signalr/signalr-1.0-tests.ts @@ -0,0 +1,148 @@ +/// + +function test_client() { + var connection = $.connection('/echo'); + connection.received(function (data) { + console.log(data); + }); + connection.error(function (error) { + console.warn(error); + }); + connection.stateChanged(function (change) { + if (change.newState === $.signalR.connectionState.reconnecting) { + console.log('Re-connecting'); + } + else if (change.newState === $.signalR.connectionState.connected) { + console.log('The server is online'); + } + }); + connection.reconnected(function () { + console.log('Reconnected'); + }); + connection.start(); + connection.start(function () { + console.log("connection started!"); + }); + connection.stop(); + connection.start().done(function () { + console.log("connection started!"); + }); + connection.start({ transport: 'longPolling' }); + connection.start({ transport: $.signalR.transports.webSockets }); + connection.start({ transport: ['longPolling', 'webSockets'] }); + connection.start({ waitForPageLoad: false }); + connection.start({ transport: 'longPolling' }, function () { + console.log('connection started!'); + }); + connection.send("Hello World"); + var connection = $.connection('http://localhost:8081/echo'); + connection.start({ jsonp: true }); +} + +function test_connection() { + var connection = $.connection('/echo'); + connection.received(function (data) { + $('#messages').append('
  • ' + data + '
  • '); + }); + connection.start(); + $("#broadcast").click(function () { + connection.send($('#msg').val()); + }); +} + +interface MyHubConnection extends HubConnection { + someState: string; + SomeFunction: Function; + + // My Hubs Client functions: + client: { + addMessage: (message: string) => void; + }; + // My Hubs Server function: + server: { + send(message: string): any; + }; +} + +interface SignalR { + chat: MyHubConnection; + myHub: MyHubConnection; +} + +function test_hubs() { + var chat = $.connection.chat; + $.connection.hub.start() + .done(function () { alert("Now connected!"); }) + .fail(function () { alert("Could not Connect!"); }); + + $.connection.hub.logging = true; + var myHub = $.connection.myHub; + myHub.someState = "SomeValue"; + function connectionReady() { + alert("Done calling first hub serverside-function"); + }; + myHub.SomeFunction = function () { + alert("serverside called 'Clients.SomeClientFunction()'"); + }; + $.connection.hub.error(function () { + alert("An error occured"); + }); + $.connection.hub.start() + .done(function () { + myHub.SomeFunction("whatever") + .done(connectionReady); + }) + .fail(function () { + alert("Could not Connect!"); + }); + + $.connection.hub.url = 'http://localhost:8081/signalr' + $.connection.hub.start(); + + var connection = $.hubConnection(); + var proxy = connection.createHubProxy('chat'); + var proxy = connection.createHubProxy('chat'), + msg = 'hello', + room = 'main'; + proxy.invoke('send', msg); + proxy.invoke('send', msg, room); + proxy.invoke('add', 1, 2) + .done(function (result: any) { + console.log('The result is ' + result); + }); + proxy.on('addMessage', function (msg?) { + console.log(msg); + }); + + //a listener may have more than 1 parameter, and you should be able to subscribe and unsubscribe + function listenerWithMoreParams(id: number, anything: string){ + console.log('listenerWithMoreParams -> ', arguments); + }; + //subscribe + proxy.on('listenerWithMoreParams', listenerWithMoreParams); + + var connection = $.hubConnection('http://localhost:8081/'); + connection.start({ jsonp: true }); + + //unsubscribe + proxy.off('listenerWithMoreParams', listenerWithMoreParams); +} + +// Sample from : https://github.com/SignalR/SignalR/wiki/QuickStart-Hubs#javascript--html +$(function () { + // Proxy created on the fly + var chat = $.connection.chat; + + // Declare a function on the chat hub so the server can invoke it + chat.client.addMessage = function (message) { + $('#messages').append('
  • ' + message + '
  • '); + }; + + // Start the connection + $.connection.hub.start().done(function () { + $("#broadcast").click(function () { + // Call the chat method on the server + chat.server.send($('#msg').val()); + }); + }); +}); diff --git a/signalr/signalr-1.0.d.ts b/signalr/signalr-1.0.d.ts new file mode 100644 index 000000000..749277a40 --- /dev/null +++ b/signalr/signalr-1.0.d.ts @@ -0,0 +1,113 @@ +// Type definitions for SignalR 1.0 +// Project: http://www.asp.net/signalr +// Definitions by: Boris Yankov , T. Michael Keesey +// Definitions: https://github.com/borisyankov/DefinitelyTyped + + +/// + +interface HubMethod { + (callback: (data: string) => void ): any; +} + +interface SignalREvents { + onStart: string; + onStarting: string; + onReceived: string; + onError: string; + onConnectionSlow: string; + onReconnect: string; + onStateChanged: string; + onDisconnect: string; +} + +interface SignalRStateChange { + oldState: number; + newState: number; +} + +interface SignalR { + events: SignalREvents; + connectionState: any; + transports: any; + + hub: HubConnection; + id: string; + logging: boolean; + messageId: string; + url: string; + qs: any; + state: number; + + (url: string, queryString?: any, logging?: boolean): SignalR; + hubConnection(url?: string): SignalR; + + log(msg: string, logging: boolean): void; + isCrossDomain(url: string): boolean; + changeState(connection: SignalR, expectedState: number, newState: number): boolean; + isDisconnecting(connection: SignalR): boolean; + + // createHubProxy(hubName: string): SignalR; + + start(): JQueryPromise; + start(callback: () => void ): JQueryPromise; + start(settings: ConnectionSettings): JQueryPromise; + start(settings: ConnectionSettings, callback: () => void ): JQueryPromise; + + + send(data: string): void; + stop(async?: boolean, notifyServer?: boolean): void; + + starting(handler: () => void ): SignalR; + received(handler: (data: any) => void ): SignalR; + error(handler: (error: Error) => void ): SignalR; + stateChanged(handler: (change: SignalRStateChange) => void ): SignalR; + disconnected(handler: () => void ): SignalR; + connectionSlow(handler: () => void ): SignalR; + sending(handler: () => void ): SignalR; + reconnecting(handler: () => void): SignalR; + reconnected(handler: () => void): SignalR; +} + +interface HubProxy { + (connection: HubConnection, hubName: string): HubProxy; + state: any; + connection: HubConnection; + hubName: string; + init(connection: HubConnection, hubName: string): void; + hasSubscriptions(): boolean; + on(eventName: string, callback: (...msg: any[]) => void ): HubProxy; + off(eventName: string, callback: (...msg: any[]) => void ): HubProxy; + invoke(methodName: string, ...args: any[]): JQueryDeferred; +} + +interface HubConnectionSettings { + queryString?: string; + logging?: boolean; + useDefaultPath?: boolean; +} + +interface HubConnection extends SignalR { + //(url?: string, queryString?: any, logging?: boolean): HubConnection; + proxies: any; + transport: { name: string, supportsKeepAlive: () => boolean }; + received(callback: (data: { Id: any; Method: any; Hub: any; State: any; Args: any; }) => void ): HubConnection; + createHubProxy(hubName: string): HubProxy; +} + +interface SignalRfn { + init(url: any, qs: any, logging: any): any; +} + +interface ConnectionSettings { + transport?: any; + callback?: any; + waitForPageLoad?: boolean; + jsonp?: boolean; +} + +interface JQueryStatic { + signalR: SignalR; + connection: SignalR; + hubConnection(url?: string, options?: HubConnectionSettings): HubConnection; +} diff --git a/signalr/signalr-tests.ts b/signalr/signalr-tests.ts index 5f2136780..f18eecd98 100644 --- a/signalr/signalr-tests.ts +++ b/signalr/signalr-tests.ts @@ -1,5 +1,54 @@ /// +var connection = $.hubConnection(); +var contosoChatHubProxy = connection.createHubProxy('contosoChatHub'); +contosoChatHubProxy.on('addContosoChatMessageToPage', function (name, message) { + console.log(name + ' ' + message); +}); +connection.start().done(function () { + // Wire up Send button to call NewContosoChatMessage on the server. + $('#newContosoChatMessage').click(function () { + contosoChatHubProxy.invoke('newContosoChatMessage', $('#displayname').val(), $('#message').val()); + $('#message').val('').focus(); + }); +}).fail(function () { + console.log('Could not connect'); +}); + +connection.qs = { 'version': '1.0' }; + +$.connection.hub.url = ''; +$.connection.hub.qs = { 'version': '1.0' }; +$.connection.hub.start({ transport: 'longPolling' }); +$.connection.hub.start({ transport: ['webSockets', 'longPolling'] }); +connection.start({ transport: 'longPolling' }); +connection.start({ transport: ['webSockets', 'longPolling'] }); + +$.connection.hub.start().done(function () { + console.log("Connected, transport = " + $.connection.hub.transport.name); +}); + +connection.hub.start().done(function () { + console.log("Connected, transport = " + connection.transport.name); +}); + +$.connection.hub.connectionSlow(function () { + console.log('We are currently experiencing difficulties with the connection.') +}); +connection.connectionSlow(function () { + console.log('We are currently experiencing difficulties with the connection.') +}); + +$.connection.hub.error(function (error) { + console.log('SignalR error: ' + error) +}); +connection.error(function (error) { + console.log('SignalR error: ' + error) +}); + +connection.logging = true; +$.connection.hub.logging = true; + function test_client() { var connection = $.connection('/echo'); connection.received(function (data) { @@ -50,18 +99,18 @@ function test_connection() { }); } -interface MyHubConnection extends HubConnection { - someState: string; - SomeFunction: Function; +interface MyHubConnection extends SignalR.Hub.Connection { + someState: string; + SomeFunction: Function; - // My Hubs Client functions: - client: { - addMessage: (message: string) => void; - }; - // My Hubs Server function: - server: { - send(message: string): any; - }; + // My Hubs Client functions: + client: { + addMessage: (message: string) => void; + }; + // My Hubs Server function: + server: { + send(message: string): any; + }; } interface SignalR { @@ -90,7 +139,7 @@ function test_hubs() { $.connection.hub.start() .done(function () { myHub.SomeFunction("whatever") - .done(connectionReady); + .done(connectionReady); }) .fail(function () { alert("Could not Connect!"); @@ -113,14 +162,14 @@ function test_hubs() { proxy.on('addMessage', function (msg?) { console.log(msg); }); - + //a listener may have more than 1 parameter, and you should be able to subscribe and unsubscribe - function listenerWithMoreParams(id: number, anything: string){ - console.log('listenerWithMoreParams -> ', arguments); + function listenerWithMoreParams(id: number, anything: string) { + console.log('listenerWithMoreParams -> ', arguments); }; //subscribe proxy.on('listenerWithMoreParams', listenerWithMoreParams); - + var connection = $.hubConnection('http://localhost:8081/'); connection.start({ jsonp: true }); diff --git a/signalr/signalr.d.ts b/signalr/signalr.d.ts index 749277a40..5f605eb5e 100644 --- a/signalr/signalr.d.ts +++ b/signalr/signalr.d.ts @@ -1,113 +1,344 @@ -// Type definitions for SignalR 1.0 +// Type definitions for SignalR 2.2.0 // Project: http://www.asp.net/signalr -// Definitions by: Boris Yankov , T. Michael Keesey +// Definitions by: Boris Yankov , T. Michael Keesey , Giedrius Grabauskas // Definitions: https://github.com/borisyankov/DefinitelyTyped /// -interface HubMethod { - (callback: (data: string) => void ): any; -} -interface SignalREvents { - onStart: string; - onStarting: string; - onReceived: string; - onError: string; - onConnectionSlow: string; - onReconnect: string; - onStateChanged: string; - onDisconnect: string; -} +declare namespace SignalR { -interface SignalRStateChange { - oldState: number; - newState: number; + interface AvailableEvents { + onStart: string; + onStarting: string; + onReceived: string; + onError: string; + onConnectionSlow: string; + onReconnect: string; + onStateChanged: string; + onDisconnect: string; + } + + interface Transport { + name: string; + supportsKeepAlive(): boolean; + send(connection: SignalR.Connection, data: any): void; + start(connection: SignalR.Connection, onSuccess: () => void, onFailed: (error?: any) => void): void; + reconnect(connection: SignalR.Connection): void; + lostConnection(connection: SignalR.Connection): void; + stop(connection: SignalR.Connection): void; + abort(connection: SignalR.Connection, async: boolean): void; + } + + interface Transports { + foreverFrame: Transport; + longPolling: Transport; + serverSentEvents: Transport; + webSockets: Transport; + } + + module Hub { + + interface Proxy { + state: any; + connection: Connection; + hubName: string; + init(connection: Connection, hubName: string): void; + hasSubscriptions(): boolean; + /** + * Wires up a callback to be invoked when a invocation request is received from the server hub. + * + * @param eventName The name of the hub event to register the callback for. + * @param callback The callback to be invoked. + */ + on(eventName: string, callback: (...msg: any[]) => void): Proxy; + /** + * Removes the callback invocation request from the server hub for the given event name. + * + * @param eventName The name of the hub event to unregister the callback for. + * @param callback The callback to be invoked. + */ + off(eventName: string, callback: (...msg: any[]) => void): Proxy; + /** + * Invokes a server hub method with the given arguments. + * + * @param methodName The name of the server hub method. + */ + invoke(methodName: string, ...args: any[]): JQueryPromise; + } + + interface Options { + queryString?: string; + logging?: boolean; + useDefaultPath?: boolean; + } + + interface ClientHubInvocation { + Hub: string; + Method: string; + Args: string; + State: string; + } + + interface Connection extends SignalR.Connection { + proxies: { [hubName: string]: any }; + transport: { name: string, supportsKeepAlive: () => boolean }; + /** + * Creates a new proxy object for the given hub connection that can be used to invoke + * methods on server hubs and handle client method invocation requests from the server. + * + * @param hubName The name of the hub on the server to create the proxy for. + */ + createHubProxy(hubName: string): Proxy; + } + + interface HubCreator { + /** + * Creates a new hub connection. + * + * @param url [Optional] The hub route url, defaults to "/signalr". + * @param options [Optional] Settings to use when creating the hubConnection. + */ + (url?: string, options?: Options): Connection; + } + + interface IHub { + start(): void; + } + + } + + interface StateChanged { + oldState: number; + newState: number; + } + + interface ConnectionStates { + connecting: number; + connected: number; + reconnecting: number; + disconnected: number; + } + + interface Resources { + nojQuery: string; + noTransportOnInit: string; + errorOnNegotiate: string; + stoppedWhileLoading: string; + stoppedWhileNegotiating: string; + errorParsingNegotiateResponse: string; + errorDuringStartRequest: string; + stoppedDuringStartRequest: string; + errorParsingStartResponse: string; + invalidStartResponse: string; + protocolIncompatible: string; + sendFailed: string; + parseFailed: string; + longPollFailed: string; + eventSourceFailedToConnect: string; + eventSourceError: string; + webSocketClosed: string; + pingServerFailedInvalidResponse: string; + pingServerFailed: string; + pingServerFailedStatusCode: string; + pingServerFailedParse: string; + noConnectionTransport: string; + webSocketsInvalidState: string; + reconnectTimeout: string; + reconnectWindowTimeout: string; + } + + interface AjaxDefaults { + processData: boolean; + timeout: number; + async: boolean; + global: boolean; + cache: boolean; + } + + interface ConnectionOptions { + transport?: string | Array | Transport; + callback?: Function; + waitForPageLoad?: boolean; + jsonp?: boolean; + pingInterval?: number; + } + + interface SimplifyLocation { + protocol: string; + host: string; + } + + interface Connection { + clientProtocol: string; + ajaxDataType: string; + contentType: string; + id: string; + logging: boolean; + url: string; + qs: string | Object; + state: number; + reconnectDelay: number; + transportConnectTimeout: number; + /** + * This should be set by the server in response to the negotiate request (30s default) + */ + disconnectTimeout: number; + /** + * This should be set by the server in response to the negotiate request + */ + reconnectWindow: number; + /** + * Warn user of slow connection if we breach the X% mark of the keep alive timeout + */ + keepAliveWarnAt: number; + + /** + * Starts the connection + */ + start(): JQueryPromise; + + /** + * Starts the connection + * + * @param callback A callback function to execute when the connection has started + */ + start(callback: () => void): JQueryPromise; + + /** + * Starts the connection + * + * @param options Options map + */ + start(options: ConnectionOptions): JQueryPromise; + + /** + * Starts the connection + * + * @param options Options map + * @param calback A callback function to execute when the connection has started + */ + start(options: ConnectionOptions, callback: () => void): JQueryPromise; + + /** + * Adds a callback that will be invoked before anything is sent over the connection + * + * @param calback A callback function to execute before the connection is fully instantiated. + */ + starting(callback: () => void): Connection; + + /** + * Sends data over the connection + * + * @param options Options map + * @param calback The data to send over the connection + */ + send(data: string): Connection; + + /** + * Adds a callback that will be invoked after anything is received over the connection + * + * @param calback A callback function to execute when any data is received on the connection + */ + received(callback: (data: any) => void): Connection; + + /** + * Adds a callback that will be invoked when the connection state changes + * + * @param calback A callback function to execute when the connection state changes + */ + stateChanged(callback: (change: StateChanged) => void): Connection; + + /** + * Adds a callback that will be invoked after an error occurs with the connection + * + * @param calback A callback function to execute when an error occurs on the connection + */ + error(callback: (error: Error) => void): Connection; + + /** + * Adds a callback that will be invoked when the client disconnects + * + * @param calback A callback function to execute when the connection is broken + */ + disconnected(callback: () => void): Connection; + + /** + * Adds a callback that will be invoked when the client detects a slow connection + * + * @param calback A callback function to execute when the connection is slow + */ + connectionSlow(callback: () => void): Connection; + + /** + * Adds a callback that will be invoked when the underlying transport begins reconnecting + * + * @param calback A callback function to execute when the connection enters a reconnecting state + */ + reconnecting(callback: () => void): Connection; + + /** + * Adds a callback that will be invoked when the underlying transport reconnects + * + * @param calback A callback function to execute when the connection is restored + */ + reconnected(callback: () => void): Connection; + + /** + * Stops listening + * + * @param async Whether or not to asynchronously abort the connection + * @param notifyServer Whether we want to notify the server that we are aborting the connection + */ + stop(async?: boolean, notifyServer?: boolean): Connection; + + log(msg: string): Connection; + + /** + * Checks if url is cross domain + * + * @param url The base URL + * @param against An optional argument to compare the URL against, if not specified it will be set to window.location. If specified it must contain a protocol and a host property. + */ + isCrossDomain(url: string, against?: Location | SimplifyLocation): boolean; + + hub: Hub.Connection; + + lastError: any; + resources: Resources; + } } interface SignalR { - events: SignalREvents; - connectionState: any; - transports: any; - - hub: HubConnection; - id: string; - logging: boolean; - messageId: string; - url: string; - qs: any; - state: number; - - (url: string, queryString?: any, logging?: boolean): SignalR; - hubConnection(url?: string): SignalR; - - log(msg: string, logging: boolean): void; - isCrossDomain(url: string): boolean; - changeState(connection: SignalR, expectedState: number, newState: number): boolean; - isDisconnecting(connection: SignalR): boolean; - - // createHubProxy(hubName: string): SignalR; - - start(): JQueryPromise; - start(callback: () => void ): JQueryPromise; - start(settings: ConnectionSettings): JQueryPromise; - start(settings: ConnectionSettings, callback: () => void ): JQueryPromise; - - - send(data: string): void; - stop(async?: boolean, notifyServer?: boolean): void; - - starting(handler: () => void ): SignalR; - received(handler: (data: any) => void ): SignalR; - error(handler: (error: Error) => void ): SignalR; - stateChanged(handler: (change: SignalRStateChange) => void ): SignalR; - disconnected(handler: () => void ): SignalR; - connectionSlow(handler: () => void ): SignalR; - sending(handler: () => void ): SignalR; - reconnecting(handler: () => void): SignalR; - reconnected(handler: () => void): SignalR; -} - -interface HubProxy { - (connection: HubConnection, hubName: string): HubProxy; - state: any; - connection: HubConnection; - hubName: string; - init(connection: HubConnection, hubName: string): void; - hasSubscriptions(): boolean; - on(eventName: string, callback: (...msg: any[]) => void ): HubProxy; - off(eventName: string, callback: (...msg: any[]) => void ): HubProxy; - invoke(methodName: string, ...args: any[]): JQueryDeferred; -} - -interface HubConnectionSettings { - queryString?: string; - logging?: boolean; - useDefaultPath?: boolean; -} - -interface HubConnection extends SignalR { - //(url?: string, queryString?: any, logging?: boolean): HubConnection; - proxies: any; - transport: { name: string, supportsKeepAlive: () => boolean }; - received(callback: (data: { Id: any; Method: any; Hub: any; State: any; Args: any; }) => void ): HubConnection; - createHubProxy(hubName: string): HubProxy; -} - -interface SignalRfn { - init(url: any, qs: any, logging: any): any; -} - -interface ConnectionSettings { - transport?: any; - callback?: any; - waitForPageLoad?: boolean; - jsonp?: boolean; + /** + * Creates a new SignalR connection for the given url + * + * @param url The URL of the long polling endpoint + * @param queryString [Optional] Custom querystring parameters to add to the connection URL. If an object, every non-function member will be added to the querystring. If a string, it's added to the QS as specified. + * @param logging [Optional] A flag indicating whether connection logging is enabled to the browser console/log. Defaults to false. + */ + (url: string, queryString?: string | Object, logging?: boolean): SignalR.Connection; + ajaxDefaults: SignalR.AjaxDefaults; + changeState(connection: SignalR.Connection, expectedState: number, newState: number): void; + connectionState: SignalR.ConnectionStates; + events: SignalR.AvailableEvents; + transports: SignalR.Transports; + hub: SignalR.Hub.Connection; + hubConnection: SignalR.Hub.HubCreator; + isDisconnecting(connection: SignalR.Connection): boolean; + /** + * Reinstates the original value of $.connection and returns the signalR object for manual assignment. + */ + noConflict(): SignalR.Connection; + /** + * Current SignalR version. + */ + version: string; } interface JQueryStatic { signalR: SignalR; connection: SignalR; - hubConnection(url?: string, options?: HubConnectionSettings): HubConnection; + hubConnection: SignalR.Hub.HubCreator; }