1 | // Copyright (c) .NET Foundation. All rights reserved.
|
2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
3 |
|
4 | import { DefaultReconnectPolicy } from "./DefaultReconnectPolicy";
|
5 | import { HttpConnection } from "./HttpConnection";
|
6 | import { HubConnection } from "./HubConnection";
|
7 | import { IHttpConnectionOptions } from "./IHttpConnectionOptions";
|
8 | import { IHubProtocol } from "./IHubProtocol";
|
9 | import { ILogger, LogLevel } from "./ILogger";
|
10 | import { IRetryPolicy } from "./IRetryPolicy";
|
11 | import { HttpTransportType } from "./ITransport";
|
12 | import { JsonHubProtocol } from "./JsonHubProtocol";
|
13 | import { NullLogger } from "./Loggers";
|
14 | import { Arg, ConsoleLogger } from "./Utils";
|
15 |
|
16 | // tslint:disable:object-literal-sort-keys
|
17 | const LogLevelNameMapping = {
|
18 | trace: LogLevel.Trace,
|
19 | debug: LogLevel.Debug,
|
20 | info: LogLevel.Information,
|
21 | information: LogLevel.Information,
|
22 | warn: LogLevel.Warning,
|
23 | warning: LogLevel.Warning,
|
24 | error: LogLevel.Error,
|
25 | critical: LogLevel.Critical,
|
26 | none: LogLevel.None,
|
27 | };
|
28 |
|
29 | function parseLogLevel(name: string): LogLevel {
|
30 | // Case-insensitive matching via lower-casing
|
31 | // Yes, I know case-folding is a complicated problem in Unicode, but we only support
|
32 | // the ASCII strings defined in LogLevelNameMapping anyway, so it's fine -anurse.
|
33 | const mapping = LogLevelNameMapping[name.toLowerCase()];
|
34 | if (typeof mapping !== "undefined") {
|
35 | return mapping;
|
36 | } else {
|
37 | throw new Error(`Unknown log level: ${name}`);
|
38 | }
|
39 | }
|
40 |
|
41 | /** A builder for configuring {@link @microsoft/signalr.HubConnection} instances. */
|
42 | export class HubConnectionBuilder {
|
43 | /** @internal */
|
44 | public protocol?: IHubProtocol;
|
45 | /** @internal */
|
46 | public httpConnectionOptions?: IHttpConnectionOptions;
|
47 | /** @internal */
|
48 | public url?: string;
|
49 | /** @internal */
|
50 | public logger?: ILogger;
|
51 |
|
52 | /** If defined, this indicates the client should automatically attempt to reconnect if the connection is lost. */
|
53 | /** @internal */
|
54 | public reconnectPolicy?: IRetryPolicy;
|
55 |
|
56 | /** Configures console logging for the {@link @microsoft/signalr.HubConnection}.
|
57 | *
|
58 | * @param {LogLevel} logLevel The minimum level of messages to log. Anything at this level, or a more severe level, will be logged.
|
59 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
60 | */
|
61 | public configureLogging(logLevel: LogLevel): HubConnectionBuilder;
|
62 |
|
63 | /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.
|
64 | *
|
65 | * @param {ILogger} logger An object implementing the {@link @microsoft/signalr.ILogger} interface, which will be used to write all log messages.
|
66 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
67 | */
|
68 | public configureLogging(logger: ILogger): HubConnectionBuilder;
|
69 |
|
70 | /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.
|
71 | *
|
72 | * @param {string} logLevel A string representing a LogLevel setting a minimum level of messages to log.
|
73 | * See {@link https://docs.microsoft.com/en-us/aspnet/core/signalr/configuration#configure-logging|the documentation for client logging configuration} for more details.
|
74 | */
|
75 | public configureLogging(logLevel: string): HubConnectionBuilder;
|
76 |
|
77 | /** Configures custom logging for the {@link @microsoft/signalr.HubConnection}.
|
78 | *
|
79 | * @param {LogLevel | string | ILogger} logging A {@link @microsoft/signalr.LogLevel}, a string representing a LogLevel, or an object implementing the {@link @microsoft/signalr.ILogger} interface.
|
80 | * See {@link https://docs.microsoft.com/en-us/aspnet/core/signalr/configuration#configure-logging|the documentation for client logging configuration} for more details.
|
81 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
82 | */
|
83 | public configureLogging(logging: LogLevel | string | ILogger): HubConnectionBuilder;
|
84 | public configureLogging(logging: LogLevel | string | ILogger): HubConnectionBuilder {
|
85 | Arg.isRequired(logging, "logging");
|
86 |
|
87 | if (isLogger(logging)) {
|
88 | this.logger = logging;
|
89 | } else if (typeof logging === "string") {
|
90 | const logLevel = parseLogLevel(logging);
|
91 | this.logger = new ConsoleLogger(logLevel);
|
92 | } else {
|
93 | this.logger = new ConsoleLogger(logging);
|
94 | }
|
95 |
|
96 | return this;
|
97 | }
|
98 |
|
99 | /** Configures the {@link @microsoft/signalr.HubConnection} to use HTTP-based transports to connect to the specified URL.
|
100 | *
|
101 | * The transport will be selected automatically based on what the server and client support.
|
102 | *
|
103 | * @param {string} url The URL the connection will use.
|
104 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
105 | */
|
106 | public withUrl(url: string): HubConnectionBuilder;
|
107 |
|
108 | /** Configures the {@link @microsoft/signalr.HubConnection} to use the specified HTTP-based transport to connect to the specified URL.
|
109 | *
|
110 | * @param {string} url The URL the connection will use.
|
111 | * @param {HttpTransportType} transportType The specific transport to use.
|
112 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
113 | */
|
114 | public withUrl(url: string, transportType: HttpTransportType): HubConnectionBuilder;
|
115 |
|
116 | /** Configures the {@link @microsoft/signalr.HubConnection} to use HTTP-based transports to connect to the specified URL.
|
117 | *
|
118 | * @param {string} url The URL the connection will use.
|
119 | * @param {IHttpConnectionOptions} options An options object used to configure the connection.
|
120 | * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
|
121 | */
|
122 | public withUrl(url: string, options: IHttpConnectionOptions): HubConnectionBuilder;
|
123 | public withUrl(url: string, transportTypeOrOptions?: IHttpConnectionOptions | HttpTransportType): HubConnectionBuilder {
|
124 | Arg.isRequired(url, "url");
|
125 |
|
126 | this.url = url;
|
127 |
|
128 | // Flow-typing knows where it's at. Since HttpTransportType is a number and IHttpConnectionOptions is guaranteed
|
129 | // to be an object, we know (as does TypeScript) this comparison is all we need to figure out which overload was called.
|
130 | if (typeof transportTypeOrOptions === "object") {
|
131 | this.httpConnectionOptions = { ...this.httpConnectionOptions, ...transportTypeOrOptions };
|
132 | } else {
|
133 | this.httpConnectionOptions = {
|
134 | ...this.httpConnectionOptions,
|
135 | transport: transportTypeOrOptions,
|
136 | };
|
137 | }
|
138 |
|
139 | return this;
|
140 | }
|
141 |
|
142 | /** Configures the {@link @microsoft/signalr.HubConnection} to use the specified Hub Protocol.
|
143 | *
|
144 | * @param {IHubProtocol} protocol The {@link @microsoft/signalr.IHubProtocol} implementation to use.
|
145 | */
|
146 | public withHubProtocol(protocol: IHubProtocol): HubConnectionBuilder {
|
147 | Arg.isRequired(protocol, "protocol");
|
148 |
|
149 | this.protocol = protocol;
|
150 | return this;
|
151 | }
|
152 |
|
153 | /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.
|
154 | * By default, the client will wait 0, 2, 10 and 30 seconds respectively before trying up to 4 reconnect attempts.
|
155 | */
|
156 | public withAutomaticReconnect(): HubConnectionBuilder;
|
157 |
|
158 | /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.
|
159 | *
|
160 | * @param {number[]} retryDelays An array containing the delays in milliseconds before trying each reconnect attempt.
|
161 | * The length of the array represents how many failed reconnect attempts it takes before the client will stop attempting to reconnect.
|
162 | */
|
163 | public withAutomaticReconnect(retryDelays: number[]): HubConnectionBuilder;
|
164 |
|
165 | /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.
|
166 | *
|
167 | * @param {IRetryPolicy} reconnectPolicy An {@link @microsoft/signalR.IRetryPolicy} that controls the timing and number of reconnect attempts.
|
168 | */
|
169 | public withAutomaticReconnect(reconnectPolicy: IRetryPolicy): HubConnectionBuilder;
|
170 | public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IRetryPolicy): HubConnectionBuilder {
|
171 | if (this.reconnectPolicy) {
|
172 | throw new Error("A reconnectPolicy has already been set.");
|
173 | }
|
174 |
|
175 | if (!retryDelaysOrReconnectPolicy) {
|
176 | this.reconnectPolicy = new DefaultReconnectPolicy();
|
177 | } else if (Array.isArray(retryDelaysOrReconnectPolicy)) {
|
178 | this.reconnectPolicy = new DefaultReconnectPolicy(retryDelaysOrReconnectPolicy);
|
179 | } else {
|
180 | this.reconnectPolicy = retryDelaysOrReconnectPolicy;
|
181 | }
|
182 |
|
183 | return this;
|
184 | }
|
185 |
|
186 | /** Creates a {@link @microsoft/signalr.HubConnection} from the configuration options specified in this builder.
|
187 | *
|
188 | * @returns {HubConnection} The configured {@link @microsoft/signalr.HubConnection}.
|
189 | */
|
190 | public build(): HubConnection {
|
191 | // If httpConnectionOptions has a logger, use it. Otherwise, override it with the one
|
192 | // provided to configureLogger
|
193 | const httpConnectionOptions = this.httpConnectionOptions || {};
|
194 |
|
195 | // If it's 'null', the user **explicitly** asked for null, don't mess with it.
|
196 | if (httpConnectionOptions.logger === undefined) {
|
197 | // If our logger is undefined or null, that's OK, the HttpConnection constructor will handle it.
|
198 | httpConnectionOptions.logger = this.logger;
|
199 | }
|
200 |
|
201 | // Now create the connection
|
202 | if (!this.url) {
|
203 | throw new Error("The 'HubConnectionBuilder.withUrl' method must be called before building the connection.");
|
204 | }
|
205 | const connection = new HttpConnection(this.url, httpConnectionOptions);
|
206 |
|
207 | return HubConnection.create(
|
208 | connection,
|
209 | this.logger || NullLogger.instance,
|
210 | this.protocol || new JsonHubProtocol(),
|
211 | this.reconnectPolicy);
|
212 | }
|
213 | }
|
214 |
|
215 | function isLogger(logger: any): logger is ILogger {
|
216 | return logger.log !== undefined;
|
217 | }
|