diff --git a/types/sc-broker/sc-broker-tests.ts b/types/sc-broker/sc-broker-tests.ts index ee87fbc59d..0640230eae 100644 --- a/types/sc-broker/sc-broker-tests.ts +++ b/types/sc-broker/sc-broker-tests.ts @@ -1,6 +1,5 @@ import scBroker = require('sc-broker'); import SCBroker = require('sc-broker/scbroker'); -import * as scClusterBrokerClient from 'scc-broker-client'; // From the README @@ -108,24 +107,4 @@ class MyBroker extends SCBroker { } } -// From the socketcluster sample -class Broker extends SCBroker { - run() { - console.log(' >> Broker PID:', process.pid); - - if (this.options.clusterStateServerHost) { - scClusterBrokerClient.attach(this, { - stateServerHost: this.options.clusterStateServerHost, - stateServerPort: this.options.clusterStateServerPort, - mappingEngine: this.options.clusterMappingEngine, - clientPoolSize: this.options.clusterClientPoolSize, - authKey: this.options.clusterAuthKey, - stateServerConnectTimeout: this.options.clusterStateServerConnectTimeout, - stateServerAckTimeout: this.options.clusterStateServerAckTimeout, - stateServerReconnectRandomness: this.options.clusterStateServerReconnectRandomness, - }); - } - } -} - -new Broker(); +new MyBroker(); diff --git a/types/sc-broker/tsconfig.json b/types/sc-broker/tsconfig.json index bdee2f1aee..ac4f807897 100644 --- a/types/sc-broker/tsconfig.json +++ b/types/sc-broker/tsconfig.json @@ -2,8 +2,7 @@ "compilerOptions": { "module": "commonjs", "lib": [ - "es6", - "esnext.asynciterable" + "es6" ], "noImplicitAny": true, "noImplicitThis": true, @@ -14,11 +13,6 @@ "../" ], "types": [], - "paths": { - "sc-channel": [ - "sc-channel/v1" - ] - }, "noEmit": true, "forceConsistentCasingInFileNames": true }, diff --git a/types/scc-broker-client/cluster-broker-client.d.ts b/types/scc-broker-client/cluster-broker-client.d.ts index 08d08930da..13da5c6358 100644 --- a/types/scc-broker-client/cluster-broker-client.d.ts +++ b/types/scc-broker-client/cluster-broker-client.d.ts @@ -3,11 +3,11 @@ import SCBroker = require('sc-broker/scbroker'); import { Secret } from 'jsonwebtoken'; import ConsumableStream = require('consumable-stream'); -import { MappingEngine, SCCBrokerClientOptions } from '.'; +import { MappingEngine, SCCBrokerClientOptions, Broker } from '.'; import ClientPool = require('./client-pool'); declare class ClusterBrokerClient extends AsyncStreamEmitter { - broker: SCBroker; + broker: Broker; sccBrokerClientPools: ClientPool[]; sccBrokerURIList: string[]; authKey?: Secret; diff --git a/types/scc-broker-client/index.d.ts b/types/scc-broker-client/index.d.ts index 3640fda8fe..26c3bdbbb9 100644 --- a/types/scc-broker-client/index.d.ts +++ b/types/scc-broker-client/index.d.ts @@ -3,10 +3,21 @@ // Definitions by: Daniel Rose // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -import SCBroker = require("sc-broker/scbroker"); -import { Secret } from "jsonwebtoken"; +import AGSimpleBroker = require('ag-simple-broker'); +import ConsumableStream = require('consumable-stream'); +import { Secret } from 'jsonwebtoken'; -import ClusterBrokerClient = require("./cluster-broker-client"); +import ClusterBrokerClient = require('./cluster-broker-client'); + +export interface Broker { + listener(eventName: 'subscribe'): ConsumableStream; + listener(eventName: 'unsubscribe'): ConsumableStream; + listener(eventName: 'publish'): ConsumableStream; + + invokePublish(channelName: string, data: any, suppressEvent: boolean): Promise; + + subscriptions(): string[]; +} export interface MappingEngine { setSites(sites: string[]): void; @@ -17,7 +28,7 @@ export interface MappingEngine { export interface SCCBrokerClientOptions { stateServerReconnectRandomness?: number; authKey?: Secret; - mappingEngine?: "skeletonRendezvous" | "simple" | MappingEngine; + mappingEngine?: 'skeletonRendezvous' | 'simple' | MappingEngine; clientPoolSize?: number; @@ -37,4 +48,4 @@ export interface SCCBrokerClientOptions { pubSubBatchDuration?: number; } -export function attach(broker: SCBroker, options: SCCBrokerClientOptions): ClusterBrokerClient; +export function attach(broker: Broker, options: SCCBrokerClientOptions): ClusterBrokerClient; diff --git a/types/scc-broker-client/scc-broker-client-tests.ts b/types/scc-broker-client/scc-broker-client-tests.ts index 11af713d42..6066b4bfee 100644 --- a/types/scc-broker-client/scc-broker-client-tests.ts +++ b/types/scc-broker-client/scc-broker-client-tests.ts @@ -1,9 +1,9 @@ import { attach } from 'scc-broker-client'; -import SCBroker = require('sc-broker/scbroker'); +import AGSimpleBroker = require('ag-simple-broker'); -const scBroker = new SCBroker(); +const agBroker = new AGSimpleBroker(); -const clusterBrokerClient = attach(scBroker, { +const clusterBrokerClient = attach(agBroker, { stateServerHost: 'localhost', stateServerPort: 8000, mappingEngine: 'simple', diff --git a/types/scc-broker-client/v6/client-pool.d.ts b/types/scc-broker-client/v6/client-pool.d.ts new file mode 100644 index 0000000000..07bab1553b --- /dev/null +++ b/types/scc-broker-client/v6/client-pool.d.ts @@ -0,0 +1,68 @@ +import { EventEmitter } from 'events'; +import { SCClientSocket } from 'socketcluster-client'; +import Hasher = require('./hasher'); +import { Secret } from 'jsonwebtoken'; + +interface ClientPoolOptions { + clientCount?: number; + targetURI: string; + authKey?: Secret; +} + +interface BrokenDownURI { + hostname: string; + port?: string; + secure?: true; +} + +declare class ClientPool extends EventEmitter { + hasher: Hasher; + clientCount: number; + targetURI: string; + authKey?: Secret; + areClientListenersBound: boolean; + clients: SCClientSocket[]; + + constructor(options?: ClientPoolOptions); + + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'subscribe', listener: (data: ClientPool.SubscribeData) => void): this; + on(event: 'subscribeFail', listener: (data: ClientPool.SubscribeFailData) => void): this; + on(event: 'publish' | 'publishFail', listener: (data: ClientPool.PublishData) => void): this; + + bindClientListeners(): void; + unbindClientListeners(): void; + + breakDownURI(uri: string): BrokenDownURI; + + selectClient(key: string): SCClientSocket; + + publish(channelName: string, data: any): void; + + subscriptions(includePending?: boolean): string[]; + subscribeAndWatch(channelName: string, handler: (data: any) => void): void; + + destroyChannel(channelName: string): void; + destroy(): void; +} + +export = ClientPool; + +declare namespace ClientPool { + interface SubscribeData { + targetURI: string; + poolIndex: number; + channel: string; + } + + interface SubscribeFailData extends SubscribeData { + error: Error; + } + + interface PublishData { + targetURI: string; + poolIndex: number; + channel: string; + data: any; + } +} diff --git a/types/scc-broker-client/v6/cluster-broker-client.d.ts b/types/scc-broker-client/v6/cluster-broker-client.d.ts new file mode 100644 index 0000000000..c98351a731 --- /dev/null +++ b/types/scc-broker-client/v6/cluster-broker-client.d.ts @@ -0,0 +1,34 @@ +import { EventEmitter } from 'events'; +import SCBroker = require('sc-broker/scbroker'); +import { Secret } from 'jsonwebtoken'; +import { MappingEngine, SCCBrokerClientOptions } from '.'; +import ClientPool = require('./client-pool'); + +declare class ClusterBrokerClient extends EventEmitter { + broker: SCBroker; + sccBrokerClientPools: ClientPool[]; + sccBrokerURIList: string[]; + authKey?: Secret; + mappingEngine: 'skeletonRendezvous' | 'simple' | MappingEngine; + clientPoolSize: number; + mapper: MappingEngine; + + constructor(broker: SCBroker, options?: SCCBrokerClientOptions); + + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'subscribe', listener: (data: ClientPool.SubscribeData) => void): this; + on(event: 'subscribeFail', listener: (data: ClientPool.SubscribeFailData) => void): this; + on(event: 'publish' | 'publishFail', listener: (data: ClientPool.PublishData) => void): this; + on(event: 'message', listener: (channelName: string, packet: any) => void): this; + + mapChannelNameToBrokerURI(channelName: string): string; + setBrokers(sccBrokerURIList: string[]): void; + getAllSubscriptions(): string[]; + + subscribe(channelName: string): void; + unsubscribe(channelName: string): void; + + publish(channelName: string, data: any): void; +} + +export = ClusterBrokerClient; diff --git a/types/scc-broker-client/v6/hasher.d.ts b/types/scc-broker-client/v6/hasher.d.ts new file mode 100644 index 0000000000..5afb8ecfe5 --- /dev/null +++ b/types/scc-broker-client/v6/hasher.d.ts @@ -0,0 +1,6 @@ +declare class Hasher { + hashToIndex(key: string, modulo: number): number; + hashToHex(key: string, algorithm?: string): string; +} + +export = Hasher; diff --git a/types/scc-broker-client/v6/index.d.ts b/types/scc-broker-client/v6/index.d.ts new file mode 100644 index 0000000000..ac73af936e --- /dev/null +++ b/types/scc-broker-client/v6/index.d.ts @@ -0,0 +1,32 @@ +// Type definitions for scc-broker-client 6.1 +// Project: https://github.com/SocketCluster/scc-broker-client +// Definitions by: Daniel Rose +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import SCBroker = require('sc-broker/scbroker'); +import ClusterBrokerClient = require('./cluster-broker-client'); +import { Secret } from 'jsonwebtoken'; + +export interface MappingEngine { + setSites(sites: string[]): void; + getSites(): string[]; + findSite(key: string): string; +} + +export interface SCCBrokerClientOptions { + stateServerReconnectRandomness?: number; + authKey?: Secret; + mappingEngine?: 'skeletonRendezvous' | 'simple' | MappingEngine; + + clientPoolSize?: number; + + stateServerHost: string; + stateServerPort?: number; + stateServerConnectTimeout?: number; + stateServerAckTimeout?: number; + + noErrorLogging?: boolean; + brokerRetryDelay?: number; +} + +export function attach(broker: SCBroker, options: SCCBrokerClientOptions): ClusterBrokerClient; diff --git a/types/scc-broker-client/v6/scc-broker-client-tests.ts b/types/scc-broker-client/v6/scc-broker-client-tests.ts new file mode 100644 index 0000000000..dcb7f0e7ba --- /dev/null +++ b/types/scc-broker-client/v6/scc-broker-client-tests.ts @@ -0,0 +1,42 @@ +import * as scClusterBrokerClient from 'scc-broker-client'; +import SCBroker = require('sc-broker/scbroker'); + +const scBroker = new SCBroker(); + +const clusterBrokerClient = scClusterBrokerClient + .attach(scBroker, { + stateServerHost: 'localhost', + stateServerPort: 8000, + mappingEngine: 'simple', + clientPoolSize: 100, + authKey: 'secret-key', + stateServerConnectTimeout: 10000, + stateServerAckTimeout: 1000, + stateServerReconnectRandomness: 100, + }) + .on('error', err => { + console.log(`Received ${err}`); + }) + .on('subscribe', data => { + console.log(`Subscribed to ${data.channel}, ${data.poolIndex}, ${data.targetURI}`); + }) + .on('subscribeFail', data => { + console.log(`Error ${data.error} while subscribing to ${data.channel}, ${data.poolIndex}, ${data.targetURI}`); + }) + .on('publish', data => { + console.log(`Published ${data.data} to ${data.channel}, ${data.poolIndex}, ${data.targetURI}`); + }) + .on('publishFail', data => { + console.log(`Error while publishing ${data.data} to ${data.channel}, ${data.poolIndex}, ${data.targetURI}`); + }) + .on('message', (channelName, packet) => { + console.log(`Received ${packet} on channel ${channelName}`); + }); + +clusterBrokerClient.subscribe('test-channel'); +clusterBrokerClient.publish('test-channel', 'lalala'); + +// $ExpectType string[] +clusterBrokerClient.getAllSubscriptions(); + +clusterBrokerClient.unsubscribe('test-channel'); diff --git a/types/scc-broker-client/v6/tsconfig.json b/types/scc-broker-client/v6/tsconfig.json new file mode 100644 index 0000000000..c9bce66ce0 --- /dev/null +++ b/types/scc-broker-client/v6/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../../", + "typeRoots": [ + "../../" + ], + "types": [], + "paths": { + "scc-broker-client": [ + "scc-broker-client/v6" + ], + "scc-broker-client/*": [ + "scc-broker-client/v6/*" + ], + "sc-broker-cluster": [ + "sc-broker-cluster/v6" + ], + "socketcluster-client": [ + "socketcluster-client/v13" + ], + "socketcluster-server": [ + "socketcluster-server/v14" + ], + "sc-channel": [ + "sc-channel/v1" + ] + }, + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "scc-broker-client-tests.ts" + ] +} diff --git a/types/scc-broker-client/v6/tslint.json b/types/scc-broker-client/v6/tslint.json new file mode 100644 index 0000000000..f93cf8562a --- /dev/null +++ b/types/scc-broker-client/v6/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +} diff --git a/types/socketcluster-client/v13/index.d.ts b/types/socketcluster-client/v13/index.d.ts new file mode 100644 index 0000000000..168e6be2bb --- /dev/null +++ b/types/socketcluster-client/v13/index.d.ts @@ -0,0 +1,19 @@ +// Type definitions for socketcluster-client 13.0 +// Project: https://github.com/SocketCluster/socketcluster-client, http://socketcluster.io +// Definitions by: Daniel Rose +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +export import SCClientSocket = require('./lib/scclientsocket'); + +export function create(options?: SCClientSocket.ClientOptions): SCClientSocket; + +/** @deprecated */ +export function connect(options?: SCClientSocket.ClientOptions): SCClientSocket; + +export function destroy(socket: SCClientSocket): void; + +export const clients: { + [id: string]: SCClientSocket; +}; + +export const version: string; diff --git a/types/socketcluster-client/v13/lib/scclientsocket.d.ts b/types/socketcluster-client/v13/lib/scclientsocket.d.ts new file mode 100644 index 0000000000..e715e6be3f --- /dev/null +++ b/types/socketcluster-client/v13/lib/scclientsocket.d.ts @@ -0,0 +1,330 @@ +import Emitter = require('component-emitter'); +import { SCServer } from 'socketcluster-server'; +import { SCAuthEngine } from 'sc-auth'; +import { SocketProtocolIgnoreStatuses, SocketProtocolErrorStatuses } from 'sc-errors'; +import { SCChannel } from 'sc-channel'; +import WebSocket = require('ws'); + +declare class SCClientSocket extends Emitter { + constructor(opts: SCClientSocket.ClientOptions); + + id: string; + clientId: string; + + channels: { + [channelName: string]: SCChannel; + }; + + readonly CONNECTING: 'connecting'; + readonly OPEN: 'open'; + readonly CLOSED: 'closed'; + + state: SCClientSocket.States; + getState(): SCClientSocket.States; + + readonly AUTHENTICATED: 'authenticated'; + readonly UNAUTHENTICATED: 'unauthenticated'; + + authState: SCClientSocket.AuthStates; + + readonly PENDING: 'pending'; + + pendingReconnect: boolean; + pendingReconnectTimeout: number; + + ackTimeout: number; + connectTimeout: number; + + pingTimeout: number; + pingTimeoutDisabled: boolean; + + channelPrefix: string | null; + disconnectOnUnload: boolean; + + authTokenName: string; + + connectAttempts: number; + + options: SCClientSocket.ClientOptions; + + authEngine: SCAuthEngine; + codecEngine: SCServer.SCCodecEngine; + + readonly ignoreStatuses: SocketProtocolIgnoreStatuses; + readonly errorStatuses: SocketProtocolErrorStatuses; + + getBytesReceived(): number; + + deauthenticate(callback?: (err: Error) => void): void; + + connect(): void; + open(): void; + disconnect(code?: number, data?: string | object): void; + reconnect(code?: number, data?: string | object): void; + destroy(code?: number, data?: string | object): void; + + decodeBase64(encodedString: string): string; + encodeBase64(decodedString: string): string; + + getAuthToken(): object | null; + authToken: object | null; + + getSignedAuthToken(): string | null; + signedAuthToken: string | null; + + // Perform client-initiated authentication by providing an encrypted token string. + authenticate(signedAuthToken: string, callback?: (err: Error, authStatus: SCClientSocket.AuthStatus) => void): void; + + decode(message: any): any; + encode(object: any): any; + + send(data: any): void; + + emit(event: string, ...args: any[]): this; + emit(event: string, data: any, callback?: (err: Error, responseData: any) => void): void; + + publish(channelName: string, data: any, callback?: (err: Error, ackData: any) => void): void; + + subscribe(channelName: string, options?: SCChannel.SCChannelOptions): SCChannel; + unsubscribe(channelName: string): void; + + channel(channelName: string, options?: SCChannel.SCChannelOptions): SCChannel; + + destroyChannel(channelName: string): void; + + subscriptions(includePending?: boolean): string[]; + isSubscribed(channelName: string, includePending?: boolean): boolean; + + processPendingSubscriptions(): void; + + watch(channelName: string, handler: SCClientSocket.WatcherFunction): void; + unwatch(channelName: string, handler?: SCClientSocket.WatcherFunction): void; + watchers(channelName: string): SCClientSocket.WatcherFunction[]; + + on(event: string, listener: SCClientSocket.AnyFunction): this; + on(event: 'connecting', listener: () => void): this; + on( + event: 'connect', + listener: (status: SCClientSocket.ConnectStatus, processSubscriptions: () => void) => void, + ): this; + on(event: 'connectAbort' | 'disconnect' | 'close', listener: (code: number, data: string | object) => void): this; + on(event: 'kickOut', listener: (message: string, channelName: string) => void): this; + on(event: 'authenticate', listener: (signedAuthToken: string | null) => void): this; + on(event: 'deauthenticate', listener: (oldSignedToken: string | null) => void): this; + on(event: 'authStateChange', listener: (stateChangeData: SCClientSocket.AuthStateChangeData) => void): this; + on(event: 'removeAuthToken', listener: (oldToken: object | null) => void): this; + on( + event: 'subscribe' | 'subscribeRequest', + listener: (channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + on( + event: 'subscribeStateChange', + listener: (stateChangeData: SCClientSocket.SubscribeStateChangeData) => void, + ): this; + on( + event: 'subscribeFail', + listener: (err: Error, channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + on(event: 'unsubscribe', listener: (channelName: string) => void): this; + on(event: 'error', listener: (err: Error) => void): this; + on(event: 'raw', listener: (data: any) => void): this; + on(event: 'message', listener: (message: WebSocket.Data) => void): this; + + once(event: string, listener: SCClientSocket.AnyFunction): this; + once(event: 'connecting', listener: () => void): this; + once( + event: 'connect', + listener: (status: SCClientSocket.ConnectStatus, processSubscriptions: () => void) => void, + ): this; + once(event: 'connectAbort' | 'disconnect' | 'close', listener: (code: number, data: string | object) => void): this; + once(event: 'kickOut', listener: (message: string, channelName: string) => void): this; + once(event: 'authenticate', listener: (signedAuthToken: string | null) => void): this; + once(event: 'deauthenticate', listener: (oldSignedToken: string | null) => void): this; + once(event: 'authStateChange', listener: (stateChangeData: SCClientSocket.AuthStateChangeData) => void): this; + once(event: 'removeAuthToken', listener: (oldToken: object | null) => void): this; + once( + event: 'subscribe' | 'subscribeRequest', + listener: (channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + once( + event: 'subscribeStateChange', + listener: (stateChangeData: SCClientSocket.SubscribeStateChangeData) => void, + ): this; + once( + event: 'subscribeFail', + listener: (err: Error, channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + once(event: 'unsubscribe', listener: (channelName: string) => void): this; + once(event: 'error', listener: (err: Error) => void): this; + once(event: 'raw', listener: (data: any) => void): this; + once(event: 'message', listener: (message: WebSocket.Data) => void): this; + + off(event?: string, listener?: SCClientSocket.AnyFunction): this; + off(event: 'connecting', listener?: () => void): this; + off( + event: 'connect', + listener?: (status: SCClientSocket.ConnectStatus, processSubscriptions: () => void) => void, + ): this; + off(event: 'connectAbort' | 'disconnect' | 'close', listener?: (code: number, data: string | object) => void): this; + off(event: 'kickOut', listener?: (message: string, channelName: string) => void): this; + off(event: 'authenticate', listener?: (signedAuthToken: string | null) => void): this; + off(event: 'deauthenticate', listener?: (oldSignedToken: string | null) => void): this; + off(event: 'authStateChange', listener?: (stateChangeData: SCClientSocket.AuthStateChangeData) => void): this; + off(event: 'removeAuthToken', listener?: (oldToken: object | null) => void): this; + off( + event: 'subscribe' | 'subscribeRequest', + listener?: (channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + off( + event: 'subscribeStateChange', + listener?: (stateChangeData: SCClientSocket.SubscribeStateChangeData) => void, + ): this; + off( + event: 'subscribeFail', + listener?: (err: Error, channelName: string, subscriptionOptions: SCChannel.SCChannelOptions) => void, + ): this; + off(event: 'unsubscribe', listener?: (channelName: string) => void): this; + off(event: 'error', listener?: (err: Error) => void): this; + off(event: 'raw', listener?: (data: any) => void): this; + off(event: 'message', listener?: (message: WebSocket.Data) => void): this; +} + +export = SCClientSocket; + +declare namespace SCClientSocket { + type AnyFunction = (...args: any[]) => any; + + interface ClientOptions { + host?: string; + + // Defaults to the current host (read from the URL). + hostname?: string; + + // Defaults to false. + secure?: boolean; + + // Defaults to 80 if !secure otherwise defaults to 443. + port?: number; + + // The URL which SC uses to make the initial handshake for the WebSocket. Defaults to '/socketcluster/'. + path?: string; + + // A map of key-value pairs which will be used as query parameters for the initial HTTP handshake which will initiate the WebSocket connection. + query?: string | { [key: string]: string }; + + // (milliseconds) - This is the timeout for getting a response to a SCSocket emit event (when a callback is provided). + ackTimeout?: number; + + // (milliseconds) + connectTimeout?: number; + + // Whether or not to automatically connect the socket as soon as it is created. Default is true. + autoConnect?: boolean; + + // Whether or not to automatically reconnect the socket when it loses the connection. + autoReconnect?: boolean; + + // Valid properties are: initialDelay (milliseconds), randomness (milliseconds), multiplier (decimal; default is 1.5) and maxDelay (milliseconds). + autoReconnectOptions?: AutoReconnectOptions; + + // Whether or not a client automatically disconnects on page unload. If enabled, the client will disconnect when a user navigates away from the page. + // This can happen when a user closes the tab/window, clicks a link to leave the page, or types a new URL into the address bar. Defaults to true. + disconnectOnUnload?: boolean; + + // Turn on/off per-message deflate compression. If this is true, you need to make sure that this property is also set to true on the server-side. + // Note that this option is only relevant when running the client from Node.js. Most modern browsers will automatically use perMessageDeflate so + // you only need to turn it on from the server-side. + perMessageDeflate?: boolean; + + // Defaults to true; multiplexing allows you to reuse a socket instead of creating a second socket to the same address. + multiplex?: boolean; + + // Defaults to null (0 milliseconds); this property affects channel subscription batching; it determines the period in milliseconds for batching + // multiple subscription requests together. It only affects channels that have the batch option set to true. A value of null or 0 means that all + // subscribe or unsubscribe requests which were made within the same call stack will be batched together. This property was introduced on the + // client-side in SC version 8 (both the client and server versions need to be >= 8.0.0). Note that there is also a separate property with the + // same name which can be configured on the server. + pubSubBatchDuration?: number; + + // Whether or not to add a timestamp to the WebSocket handshake request. + timestampRequests?: boolean; + + // The query parameter name to use to hold the timestamp. + timestampParam?: string; + + // A custom engine to use for storing and loading JWT auth tokens on the client side. + authEngine?: SCAuthEngine | null; + + // The name of the JWT auth token (provided to the authEngine - By default this is the localStorage variable name); defaults to 'socketCluster.authToken'. + authTokenName?: string; + + // The type to use to represent binary on the client. Defaults to 'arraybuffer'. + binaryType?: string; + + // Set this to false during debugging - Otherwise client connection will fail when using self-signed certificates. + rejectUnauthorized?: boolean; + + // If you set this to true, any data/objects/arrays that you pass to the client socket will be cloned before being sent/queued up. If the socket + // is disconnected and you emit an event, it will be added to a queue which will be processed upon reconnection. The cloneData option is false + // by default; this means that if you emit/publish an object and that object changes somewhere else in your code before the queue is processed, + // then the changed version of that object will be sent out to the server. + cloneData?: boolean; + + // This is true by default. If you set this to false, then the socket will not automatically try to subscribe to pending subscriptions on + // connect - Instead, you will have to manually invoke the processSubscriptions callback from inside the 'connect' event handler on the client side. + // See SCSocket Client API. This gives you more fine-grained control with regards to when pending subscriptions are processed after the socket + // connection is established (or re-established). + autoSubscribeOnConnect?: boolean; + + // Lets you set a custom codec engine. This allows you to specify how data gets encoded before being sent over the wire and how it gets decoded + // once it reaches the other side. The codecEngine must be an object which exposes an encode(object) and a decode(encodedData) function. + // The encode function can return any data type - Commonly a string or a Buffer/ArrayBuffer. The decode function needs to return a JavaScript + // object which adheres to the SC protocol. The idea of using a custom codec is that it allows you to compress SC packets in any format you like + // (optimized for any use case) - By decoding these packets back into their original protocol form, SC will be able process them appropriately. + // Note that if you provide a codecEngine when creating a client socket see 'codecEngine', you will need to make sure that the server uses the + // same codec by passing the same engine to `worker.scServer.setCodecEngine(codecEngine)` when your SC worker initializes on the server side + // (see 'setCodecEngine' method here). The default codec engine used by SC is here. + codecEngine?: SCServer.SCCodecEngine | null; + + // A prefix to add to the channel names. + channelPrefix?: string | null; + + subscriptionRetryOptions?: object | null; + } + + interface AutoReconnectOptions { + initialDelay?: number; + randomness?: number; + multiplier?: number; + maxDelay?: number; + } + + interface AuthStatus { + isAuthenticated: AuthStates; + authError: Error; + } + + interface AuthStateChangeData { + oldState: AuthStates; + newState: AuthStates; + } + + interface ConnectStatus { + id: string; + pingTimeout: number; + isAuthenticated: boolean; + authToken?: object; + authError?: Error; + } + + interface SubscribeStateChangeData { + channel: string; + oldState: SCChannel.ChannelState; + newState: SCChannel.ChannelState; + subscriptionOptions: SCChannel.SCChannelOptions; + } + + type WatcherFunction = (data: any) => void; + type AuthStates = 'authenticated' | 'unauthenticated'; + type States = 'connecting' | 'open' | 'closed'; +} diff --git a/types/socketcluster-client/v13/socketcluster-client-tests.ts b/types/socketcluster-client/v13/socketcluster-client-tests.ts new file mode 100644 index 0000000000..ce42ba6a7e --- /dev/null +++ b/types/socketcluster-client/v13/socketcluster-client-tests.ts @@ -0,0 +1,108 @@ +// Adapted from README + +import { create, destroy } from 'socketcluster-client'; +import { ClientOptions, SubscribeStateChangeData } from 'socketcluster-client/lib/scclientsocket'; +import { SCChannel } from 'sc-channel'; +import WebSocket = require('ws'); + +const secureClientOptions: ClientOptions = { + hostname: 'securedomain.com', + secure: true, + port: 443, + rejectUnauthorized: false, +}; + +let socket = create(secureClientOptions); + +socket.on('connect', () => { + console.log('CONNECTED'); +}); + +// Listen to an event called 'rand' from the server +socket.on('rand', (num: any) => { + console.log('RANDOM: ' + num); +}); + +const options: ClientOptions = { + path: '/socketcluster/', + port: 8000, + hostname: '127.0.0.1', + autoConnect: true, + secure: false, + rejectUnauthorized: false, + connectTimeout: 10000, // milliseconds + ackTimeout: 10000, // milliseconds + channelPrefix: null, + disconnectOnUnload: true, + multiplex: true, + autoReconnectOptions: { + initialDelay: 10000, // milliseconds + randomness: 10000, // milliseconds + multiplier: 1.5, // decimal + maxDelay: 60000, // milliseconds + }, + authEngine: null, + codecEngine: null, + subscriptionRetryOptions: {}, + query: { + yourparam: 'hello', + }, +}; +socket = create(options); + +// Check some of the standard events, with normal subscription, +// one-time subscription and unsubscription. +const subscribeListener: ( + channelName: string, + subscriptionOptions: SCChannel.SCChannelOptions, +) => void = channelname => { + console.log('subscribe:' + channelname); +}; +socket.on('subscribe', subscribeListener); +socket.once('subscribe', subscribeListener); +socket.off('subscribe', subscribeListener); +socket.off('subscribe'); + +const subscribeFailListener: ( + err: Error, + channelName: string, + subscriptionOptions: SCChannel.SCChannelOptions, +) => void = channelname => { + console.log('subscribeFail:' + channelname); +}; +socket.on('subscribeFail', subscribeFailListener); +socket.once('subscribeFail', subscribeFailListener); +socket.off('subscribeFail', subscribeFailListener); +socket.off('subscribeFail'); + +const unsubscribeListener: (channelName: string) => void = channelname => { + console.log('unsubscribe:' + channelname); +}; +socket.on('unsubscribe', unsubscribeListener); +socket.once('unsubscribe', unsubscribeListener); +socket.off('unsubscribe', unsubscribeListener); +socket.off('unsubscribe'); + +const subscribeStateChangeListener: (stateChangeData: SubscribeStateChangeData) => void = data => { + console.log('subscribeStateChange:' + JSON.stringify(data)); +}; +socket.on('subscribeStateChange', subscribeStateChangeListener); +socket.once('subscribeStateChange', subscribeStateChangeListener); +socket.off('subscribeStateChange', subscribeStateChangeListener); +socket.off('subscribeStateChange'); + +const messageListener: (message: WebSocket.Data) => void = data => { + console.log('message:' + data); +}; +socket.on('message', messageListener); +socket.once('message', messageListener); +socket.off('message', messageListener); +socket.off('message'); + +const channels = socket.channels; +const testChannel = channels['test']; + +// $ExpectType ChannelState +testChannel.getState(); + +destroy(socket); diff --git a/types/socketcluster-client/v13/tsconfig.json b/types/socketcluster-client/v13/tsconfig.json new file mode 100644 index 0000000000..2f681123d2 --- /dev/null +++ b/types/socketcluster-client/v13/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../../", + "typeRoots": [ + "../../" + ], + "types": [], + "paths": { + "socketcluster-client": [ + "socketcluster-client/v13" + ], + "socketcluster-client/*": [ + "socketcluster-client/v13/*" + ], + "socketcluster-server": [ + "socketcluster-server/v14" + ], + "sc-broker-cluster": [ + "sc-broker-cluster/v6" + ], + "sc-channel": [ + "sc-channel/v1" + ] + }, + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "socketcluster-client-tests.ts" + ] +} diff --git a/types/socketcluster-client/v13/tslint.json b/types/socketcluster-client/v13/tslint.json new file mode 100644 index 0000000000..f93cf8562a --- /dev/null +++ b/types/socketcluster-client/v13/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +}