@socket-mesh/client 17.1.4 → 18.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/auth.js +28 -45
- package/auth.js.map +1 -1
- package/client-options.d.ts +2 -2
- package/clientsocket.d.ts +9 -10
- package/clientsocket.js +118 -137
- package/clientsocket.js.map +1 -1
- package/events.d.ts +1 -1
- package/factory.d.ts +2 -2
- package/factory.js +7 -7
- package/factory.js.map +1 -1
- package/index.d.ts +6 -6
- package/index.js +5 -6
- package/index.js.map +1 -1
- package/package.json +18 -34
- package/transport.d.ts +5 -4
- package/transport.js +79 -97
- package/transport.js.map +1 -1
package/README.md
CHANGED
|
@@ -135,7 +135,7 @@ let options = {
|
|
|
135
135
|
hostname: 'securedomain.com',
|
|
136
136
|
secure: true,
|
|
137
137
|
port: 443,
|
|
138
|
-
rejectUnauthorized: false // Only necessary during debug if using a self-signed certificate
|
|
138
|
+
wsOptions: { rejectUnauthorized: false } // Only necessary during debug if using a self-signed certificate
|
|
139
139
|
};
|
|
140
140
|
// Initiate the connection to the server
|
|
141
141
|
let socket = socketClusterClient.create(options);
|
|
@@ -155,11 +155,9 @@ let options = {
|
|
|
155
155
|
hostname: '127.0.0.1',
|
|
156
156
|
autoConnect: true,
|
|
157
157
|
secure: false,
|
|
158
|
-
rejectUnauthorized: false,
|
|
159
158
|
connectTimeout: 10000, //milliseconds
|
|
160
159
|
ackTimeout: 10000, //milliseconds
|
|
161
160
|
channelPrefix: null,
|
|
162
|
-
disconnectOnUnload: true,
|
|
163
161
|
autoReconnectOptions: {
|
|
164
162
|
initialDelay: 10000, //milliseconds
|
|
165
163
|
randomness: 10000, //milliseconds
|
|
@@ -169,6 +167,7 @@ let options = {
|
|
|
169
167
|
authEngine: null,
|
|
170
168
|
codecEngine: null,
|
|
171
169
|
subscriptionRetryOptions: {},
|
|
170
|
+
wsOptions: { rejectUnauthorized: false },
|
|
172
171
|
query: {
|
|
173
172
|
yourparam: 'hello'
|
|
174
173
|
}
|
package/auth.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
export class LocalStorageAuthEngine {
|
|
11
2
|
constructor() {
|
|
12
3
|
this._internalStorage = {};
|
|
@@ -15,52 +6,44 @@ export class LocalStorageAuthEngine {
|
|
|
15
6
|
_checkLocalStorageEnabled() {
|
|
16
7
|
let err;
|
|
17
8
|
try {
|
|
18
|
-
// Some browsers will throw an error here if localStorage is disabled.
|
|
19
|
-
global.localStorage;
|
|
20
9
|
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
|
|
21
10
|
// throw QuotaExceededError. We're going to detect this and avoid hard to debug edge cases.
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
localStorage.setItem('__scLocalStorageTest', "1");
|
|
12
|
+
localStorage.removeItem('__scLocalStorageTest');
|
|
24
13
|
}
|
|
25
14
|
catch (e) {
|
|
26
15
|
err = e;
|
|
27
16
|
}
|
|
28
17
|
return !err;
|
|
29
18
|
}
|
|
30
|
-
saveToken(name, token) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return token;
|
|
39
|
-
});
|
|
19
|
+
async saveToken(name, token) {
|
|
20
|
+
if (this.isLocalStorageEnabled) {
|
|
21
|
+
localStorage.setItem(name, token);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this._internalStorage[name] = token;
|
|
25
|
+
}
|
|
26
|
+
return token;
|
|
40
27
|
}
|
|
41
|
-
removeToken(name) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return loadPromise;
|
|
51
|
-
});
|
|
28
|
+
async removeToken(name) {
|
|
29
|
+
let loadPromise = this.loadToken(name);
|
|
30
|
+
if (this.isLocalStorageEnabled) {
|
|
31
|
+
localStorage.removeItem(name);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
delete this._internalStorage[name];
|
|
35
|
+
}
|
|
36
|
+
return loadPromise;
|
|
52
37
|
}
|
|
53
|
-
loadToken(name) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return token;
|
|
63
|
-
});
|
|
38
|
+
async loadToken(name) {
|
|
39
|
+
let token;
|
|
40
|
+
if (this.isLocalStorageEnabled) {
|
|
41
|
+
token = localStorage.getItem(name);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
token = this._internalStorage[name] || null;
|
|
45
|
+
}
|
|
46
|
+
return token;
|
|
64
47
|
}
|
|
65
48
|
}
|
|
66
49
|
//# sourceMappingURL=auth.js.map
|
package/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAO,sBAAsB;IAIlC;QACC,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC3B,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,yBAAyB,EAAE,CAAC;IAC/D,CAAC;IAEO,yBAAyB;QAChC,IAAI,GAAG,CAAC;QAER,IAAI;YACH,iGAAiG;YACjG,2FAA2F;YAC3F,YAAY,CAAC,OAAO,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;YAClD,YAAY,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;SAChD;QAAC,OAAO,CAAC,EAAE;YACX,GAAG,GAAG,CAAC,CAAC;SACR;QAED,OAAO,CAAC,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,KAAa;QAC1C,IAAI,IAAI,CAAC,qBAAqB,EAAE;YAC/B,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;SAClC;aAAM;YACN,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;SACpC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAY;QAC7B,IAAI,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEvC,IAAI,IAAI,CAAC,qBAAqB,EAAE;YAC/B,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;SAC9B;aAAM;YACN,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;SACnC;QAED,OAAO,WAAW,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY;QAC3B,IAAI,KAAK,CAAC;QAEV,IAAI,IAAI,CAAC,qBAAqB,EAAE;YAC/B,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SACnC;aAAM;YACN,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;SAC5C;QAED,OAAO,KAAK,CAAC;IACd,CAAC;CACD"}
|
package/client-options.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthEngine } from "./auth";
|
|
1
|
+
import { AuthEngine } from "./auth.js";
|
|
2
2
|
import { CodecEngine } from "@socket-mesh/formatter";
|
|
3
3
|
import * as ws from "ws";
|
|
4
4
|
export type ProtocolVersions = 1 | 2;
|
|
@@ -14,6 +14,7 @@ export interface ClientOptions {
|
|
|
14
14
|
host?: string;
|
|
15
15
|
hostname?: string;
|
|
16
16
|
secure?: boolean;
|
|
17
|
+
usabilityMode?: boolean;
|
|
17
18
|
port?: number;
|
|
18
19
|
path?: string;
|
|
19
20
|
protocolScheme?: string;
|
|
@@ -25,7 +26,6 @@ export interface ClientOptions {
|
|
|
25
26
|
autoConnect?: boolean;
|
|
26
27
|
autoReconnect?: boolean;
|
|
27
28
|
autoReconnectOptions?: AutoReconnectOptions;
|
|
28
|
-
disconnectOnUnload?: boolean;
|
|
29
29
|
timestampRequests?: boolean;
|
|
30
30
|
timestampParam?: string;
|
|
31
31
|
authEngine?: AuthEngine | null;
|
package/clientsocket.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ClientOptions, ProtocolVersions } from "./client-options";
|
|
1
|
+
import { ClientOptions, ProtocolVersions } from "./client-options.js";
|
|
2
2
|
import { DemuxedConsumableStream, StreamDemuxWrapper } from "@socket-mesh/stream-demux";
|
|
3
|
-
import { AuthEngine, AuthStatus } from "./auth";
|
|
3
|
+
import { AuthEngine, AuthStatus } from "./auth.js";
|
|
4
4
|
import { AuthState, AuthToken, SignedAuthToken } from "@socket-mesh/auth";
|
|
5
5
|
import { CodecEngine } from "@socket-mesh/formatter";
|
|
6
|
-
import { Transport } from "./transport";
|
|
6
|
+
import { Transport } from "./transport.js";
|
|
7
7
|
import * as ws from "ws";
|
|
8
8
|
import { Client, ChannelDetails } from "@socket-mesh/channel";
|
|
9
|
-
import { SocketState } from "./socket-state";
|
|
10
|
-
import { AuthStateChanged, AuthTokenRemoved, Authenticated, Closed, Connected, Connecting, Deauthenticated, ErrorOccured, KickedOut, MessageReceived, SubscribeFailed, SubscribeStateChanged, Subscribed, Unsubscribed } from "./events";
|
|
9
|
+
import { SocketState } from "./socket-state.js";
|
|
10
|
+
import { AuthStateChanged, AuthTokenRemoved, Authenticated, Closed, Connected, Connecting, Deauthenticated, ErrorOccured, KickedOut, MessageReceived, SubscribeFailed, SubscribeStateChanged, Subscribed, Unsubscribed } from "./events.js";
|
|
11
11
|
export declare class ClientSocket extends Client<any> {
|
|
12
12
|
auth: AuthEngine;
|
|
13
13
|
authTokenName?: string;
|
|
@@ -20,7 +20,6 @@ export declare class ClientSocket extends Client<any> {
|
|
|
20
20
|
batchOnHandshakeDuration: number;
|
|
21
21
|
clientId?: string;
|
|
22
22
|
id: string | null;
|
|
23
|
-
disconnectOnUnload: boolean;
|
|
24
23
|
pendingReconnect: boolean;
|
|
25
24
|
pendingReconnectTimeout: number;
|
|
26
25
|
preparingPendingSubscriptions: boolean;
|
|
@@ -44,15 +43,15 @@ export declare class ClientSocket extends Client<any> {
|
|
|
44
43
|
private _procedureDemux;
|
|
45
44
|
private _reconnectTimeoutRef?;
|
|
46
45
|
private readonly _outboundBuffer;
|
|
47
|
-
constructor(socketOptions
|
|
46
|
+
constructor(socketOptions?: ClientOptions);
|
|
47
|
+
uri(): string;
|
|
48
48
|
getBackpressure(): number;
|
|
49
|
-
private _handleBrowserUnload;
|
|
50
49
|
private _setAuthToken;
|
|
51
50
|
private _removeAuthToken;
|
|
52
51
|
getState(): SocketState;
|
|
53
52
|
getBytesReceived(): unknown;
|
|
54
53
|
deauthenticate(): Promise<void>;
|
|
55
|
-
connect(): void;
|
|
54
|
+
connect(socketOptions?: ClientOptions): void;
|
|
56
55
|
reconnect(code?: number, reason?: string): void;
|
|
57
56
|
disconnect(code?: number, reason?: string): void;
|
|
58
57
|
private _changeToUnauthenticatedStateAndClearTokens;
|
|
@@ -80,7 +79,7 @@ export declare class ClientSocket extends Client<any> {
|
|
|
80
79
|
transmit(event: string, data?: any, options?: {
|
|
81
80
|
ackTimeout?: number;
|
|
82
81
|
}): Promise<void>;
|
|
83
|
-
invoke<T>(event: string, data
|
|
82
|
+
invoke<T>(event: string, data?: any, options?: {
|
|
84
83
|
ackTimeout?: number;
|
|
85
84
|
}): Promise<T>;
|
|
86
85
|
transmitPublish(channelName: string, data: any): Promise<void>;
|
package/clientsocket.js
CHANGED
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { StreamDemux, StreamDemuxWrapper } from "@socket-mesh/stream-demux";
|
|
11
|
-
import { LocalStorageAuthEngine } from "./auth";
|
|
2
|
+
import { LocalStorageAuthEngine } from "./auth.js";
|
|
12
3
|
import { AuthState } from "@socket-mesh/auth";
|
|
13
4
|
import formatter from "@socket-mesh/formatter";
|
|
14
|
-
import { Transport } from "./transport";
|
|
5
|
+
import { Transport } from "./transport.js";
|
|
15
6
|
import { List, Item } from "linked-list";
|
|
16
7
|
import cloneDeep from "clone-deep";
|
|
17
8
|
import { Buffer } from "buffer";
|
|
18
|
-
import { wait } from "./wait";
|
|
9
|
+
import { wait } from "./wait.js";
|
|
19
10
|
import { ChannelState, Client } from "@socket-mesh/channel";
|
|
20
|
-
import { SocketState } from "./socket-state";
|
|
11
|
+
import { SocketState } from "./socket-state.js";
|
|
21
12
|
import { hydrateError, InvalidArgumentsError, InvalidMessageError, SocketProtocolError, TimeoutError, BadConnectionError, socketProtocolIgnoreStatuses, socketProtocolErrorStatuses } from "@socket-mesh/errors";
|
|
22
|
-
const isBrowser = typeof window !== 'undefined';
|
|
23
13
|
class EventNode extends Item {
|
|
24
14
|
constructor() {
|
|
25
15
|
super();
|
|
@@ -43,7 +33,6 @@ export class ClientSocket extends Client {
|
|
|
43
33
|
ackTimeout: 10000,
|
|
44
34
|
timestampRequests: false,
|
|
45
35
|
timestampParam: 't',
|
|
46
|
-
authTokenName: 'socketcluster.authToken',
|
|
47
36
|
binaryType: 'arraybuffer',
|
|
48
37
|
batchOnHandshake: false,
|
|
49
38
|
batchOnHandshakeDuration: 100,
|
|
@@ -52,6 +41,10 @@ export class ClientSocket extends Client {
|
|
|
52
41
|
wsOptions: {},
|
|
53
42
|
cloneData: false
|
|
54
43
|
}, socketOptions);
|
|
44
|
+
if (opts.authTokenName == null) {
|
|
45
|
+
const authHostString = opts.host ? `.${opts.host}` : `.${opts.hostname || 'localhost'}${opts.port ? `:${opts.port}` : ''}`;
|
|
46
|
+
opts.authTokenName = `socketcluster.authToken${authHostString}`;
|
|
47
|
+
}
|
|
55
48
|
this.version = opts.version || null;
|
|
56
49
|
this.protocolVersion = opts.protocolVersion;
|
|
57
50
|
this.signedAuthToken = null;
|
|
@@ -64,7 +57,6 @@ export class ClientSocket extends Client {
|
|
|
64
57
|
this.connectTimeout = opts.connectTimeout;
|
|
65
58
|
this.ackTimeout = opts.ackTimeout;
|
|
66
59
|
this.channelPrefix = opts.channelPrefix || null;
|
|
67
|
-
this.disconnectOnUnload = opts.disconnectOnUnload == null ? true : opts.disconnectOnUnload;
|
|
68
60
|
this.authTokenName = opts.authTokenName;
|
|
69
61
|
// pingTimeout will be connectTimeout at the start, but it will
|
|
70
62
|
// be updated with values provided by the 'connect' event
|
|
@@ -133,75 +125,38 @@ export class ClientSocket extends Client {
|
|
|
133
125
|
this.codec = formatter;
|
|
134
126
|
}
|
|
135
127
|
if (this.options.protocol) {
|
|
136
|
-
let protocolOptionError = new InvalidArgumentsError('The
|
|
137
|
-
'If you want to utilize SSL/TLS, use
|
|
128
|
+
let protocolOptionError = new InvalidArgumentsError('The protocol option does not affect socketcluster-client - ' +
|
|
129
|
+
'If you want to utilize SSL/TLS, use the secure option instead');
|
|
138
130
|
this._onError(protocolOptionError);
|
|
139
131
|
}
|
|
140
132
|
this.options.query = opts.query || {};
|
|
141
|
-
if (isBrowser && this.disconnectOnUnload && global.addEventListener && global.removeEventListener) {
|
|
142
|
-
this._handleBrowserUnload();
|
|
143
|
-
}
|
|
144
133
|
if (this.options.autoConnect) {
|
|
145
134
|
this.connect();
|
|
146
135
|
}
|
|
147
136
|
}
|
|
137
|
+
uri() {
|
|
138
|
+
return Transport.computeUri(this.options);
|
|
139
|
+
}
|
|
140
|
+
;
|
|
148
141
|
getBackpressure() {
|
|
149
142
|
return Math.max(this.getListenerBackpressure(), this.receiver.getBackpressure(), this.procedure.getBackpressure(), this.getChannelBackpressure());
|
|
150
143
|
}
|
|
151
|
-
_handleBrowserUnload() {
|
|
152
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
-
let unloadHandler = () => {
|
|
154
|
-
this.disconnect();
|
|
155
|
-
};
|
|
156
|
-
let isUnloadHandlerAttached = false;
|
|
157
|
-
let attachUnloadHandler = () => {
|
|
158
|
-
if (!isUnloadHandlerAttached) {
|
|
159
|
-
isUnloadHandlerAttached = true;
|
|
160
|
-
global.addEventListener('beforeunload', unloadHandler, false);
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
let detachUnloadHandler = () => {
|
|
164
|
-
if (isUnloadHandlerAttached) {
|
|
165
|
-
isUnloadHandlerAttached = false;
|
|
166
|
-
global.removeEventListener('beforeunload', unloadHandler, false);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
(() => __awaiter(this, void 0, void 0, function* () {
|
|
170
|
-
let consumer = this.listen('connecting').createConsumer();
|
|
171
|
-
while (true) {
|
|
172
|
-
let packet = yield consumer.next();
|
|
173
|
-
if (packet.done)
|
|
174
|
-
break;
|
|
175
|
-
attachUnloadHandler();
|
|
176
|
-
}
|
|
177
|
-
}))();
|
|
178
|
-
(() => __awaiter(this, void 0, void 0, function* () {
|
|
179
|
-
let consumer = this.listen('close').createConsumer();
|
|
180
|
-
while (true) {
|
|
181
|
-
let packet = yield consumer.next();
|
|
182
|
-
if (packet.done)
|
|
183
|
-
break;
|
|
184
|
-
detachUnloadHandler();
|
|
185
|
-
}
|
|
186
|
-
}))();
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
144
|
_setAuthToken(data) {
|
|
190
145
|
this._changeToAuthenticatedState(data.token);
|
|
191
|
-
(() =>
|
|
146
|
+
(async () => {
|
|
192
147
|
try {
|
|
193
|
-
|
|
148
|
+
await this.auth.saveToken(this.authTokenName, data.token, {});
|
|
194
149
|
}
|
|
195
150
|
catch (err) {
|
|
196
151
|
this._onError(err);
|
|
197
152
|
}
|
|
198
|
-
})
|
|
153
|
+
})();
|
|
199
154
|
}
|
|
200
155
|
_removeAuthToken() {
|
|
201
|
-
(() =>
|
|
156
|
+
(async () => {
|
|
202
157
|
let oldAuthToken;
|
|
203
158
|
try {
|
|
204
|
-
oldAuthToken =
|
|
159
|
+
oldAuthToken = await this.auth.removeToken(this.authTokenName);
|
|
205
160
|
}
|
|
206
161
|
catch (err) {
|
|
207
162
|
// Non-fatal error - Do not close the connection
|
|
@@ -209,7 +164,7 @@ export class ClientSocket extends Client {
|
|
|
209
164
|
return;
|
|
210
165
|
}
|
|
211
166
|
this.emit('removeAuthToken', { oldAuthToken });
|
|
212
|
-
})
|
|
167
|
+
})();
|
|
213
168
|
this._changeToUnauthenticatedStateAndClearTokens();
|
|
214
169
|
}
|
|
215
170
|
getState() {
|
|
@@ -218,27 +173,34 @@ export class ClientSocket extends Client {
|
|
|
218
173
|
getBytesReceived() {
|
|
219
174
|
return this.transport.getBytesReceived();
|
|
220
175
|
}
|
|
221
|
-
deauthenticate() {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
oldAuthToken = yield this.auth.removeToken(this.authTokenName);
|
|
227
|
-
}
|
|
228
|
-
catch (err) {
|
|
229
|
-
this._onError(err);
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
this.emit('removeAuthToken', { oldAuthToken });
|
|
233
|
-
}))();
|
|
234
|
-
if (this.state !== SocketState.CLOSED) {
|
|
235
|
-
this.transmit('#removeAuthToken');
|
|
176
|
+
async deauthenticate() {
|
|
177
|
+
(async () => {
|
|
178
|
+
let oldAuthToken;
|
|
179
|
+
try {
|
|
180
|
+
oldAuthToken = await this.auth.removeToken(this.authTokenName);
|
|
236
181
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
182
|
+
catch (err) {
|
|
183
|
+
this._onError(err);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
this.emit('removeAuthToken', { oldAuthToken });
|
|
187
|
+
})();
|
|
188
|
+
if (this.state !== SocketState.CLOSED) {
|
|
189
|
+
this.transmit('#removeAuthToken');
|
|
190
|
+
}
|
|
191
|
+
this._changeToUnauthenticatedStateAndClearTokens();
|
|
192
|
+
await wait(0);
|
|
240
193
|
}
|
|
241
|
-
connect() {
|
|
194
|
+
connect(socketOptions) {
|
|
195
|
+
if (socketOptions) {
|
|
196
|
+
if (this.state !== SocketState.CLOSED) {
|
|
197
|
+
this.disconnect(1000, 'Socket was disconnected by the client to initiate a new connection');
|
|
198
|
+
}
|
|
199
|
+
this.options = {
|
|
200
|
+
...this.options,
|
|
201
|
+
...socketOptions
|
|
202
|
+
};
|
|
203
|
+
}
|
|
242
204
|
if (this.state === SocketState.CLOSED) {
|
|
243
205
|
this.pendingReconnect = false;
|
|
244
206
|
this.pendingReconnectTimeout = null;
|
|
@@ -343,7 +305,9 @@ export class ClientSocket extends Client {
|
|
|
343
305
|
return Buffer.from(decodedString, 'utf8').toString('base64');
|
|
344
306
|
}
|
|
345
307
|
_extractAuthTokenData(signedAuthToken) {
|
|
346
|
-
|
|
308
|
+
if (typeof signedAuthToken !== 'string')
|
|
309
|
+
return null;
|
|
310
|
+
let tokenParts = signedAuthToken.split('.');
|
|
347
311
|
let encodedTokenData = tokenParts[1];
|
|
348
312
|
if (encodedTokenData != null) {
|
|
349
313
|
let tokenData = encodedTokenData;
|
|
@@ -364,53 +328,51 @@ export class ClientSocket extends Client {
|
|
|
364
328
|
return this.signedAuthToken;
|
|
365
329
|
}
|
|
366
330
|
// Perform client-initiated authentication by providing an encrypted token string.
|
|
367
|
-
authenticate(signedAuthToken) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
this._changeToUnauthenticatedStateAndClearTokens();
|
|
378
|
-
}
|
|
379
|
-
yield wait(0);
|
|
380
|
-
throw err;
|
|
381
|
-
}
|
|
382
|
-
if ((authStatus === null || authStatus === void 0 ? void 0 : authStatus.isAuthenticated) != null) {
|
|
383
|
-
// If authStatus is correctly formatted (has an isAuthenticated property),
|
|
384
|
-
// then we will rehydrate the authError.
|
|
385
|
-
if (authStatus.authError) {
|
|
386
|
-
authStatus.authError = hydrateError(authStatus.authError);
|
|
387
|
-
}
|
|
331
|
+
async authenticate(signedAuthToken) {
|
|
332
|
+
let authStatus;
|
|
333
|
+
try {
|
|
334
|
+
authStatus = await this.invoke('#authenticate', signedAuthToken);
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
if (err.name !== 'BadConnectionError' && err.name !== 'TimeoutError') {
|
|
338
|
+
// In case of a bad/closed connection or a timeout, we maintain the last
|
|
339
|
+
// known auth state since those errors don't mean that the token is invalid.
|
|
340
|
+
this._changeToUnauthenticatedStateAndClearTokens();
|
|
388
341
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
342
|
+
await wait(0);
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
345
|
+
if (authStatus?.isAuthenticated != null) {
|
|
346
|
+
// If authStatus is correctly formatted (has an isAuthenticated property),
|
|
347
|
+
// then we will rehydrate the authError.
|
|
348
|
+
if (authStatus.authError) {
|
|
349
|
+
authStatus.authError = hydrateError(authStatus.authError);
|
|
396
350
|
}
|
|
397
|
-
|
|
398
|
-
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
// Some errors like BadConnectionError and TimeoutError will not pass a valid
|
|
354
|
+
// authStatus object to the current function, so we need to create it ourselves.
|
|
355
|
+
authStatus = {
|
|
356
|
+
isAuthenticated: this.authState,
|
|
357
|
+
authError: null
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
if (authStatus.isAuthenticated) {
|
|
361
|
+
this._changeToAuthenticatedState(signedAuthToken);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
this._changeToUnauthenticatedStateAndClearTokens();
|
|
365
|
+
}
|
|
366
|
+
(async () => {
|
|
367
|
+
try {
|
|
368
|
+
await this.auth.saveToken(this.authTokenName, signedAuthToken, {});
|
|
399
369
|
}
|
|
400
|
-
|
|
401
|
-
this.
|
|
370
|
+
catch (err) {
|
|
371
|
+
this._onError(err);
|
|
402
372
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
catch (err) {
|
|
408
|
-
this._onError(err);
|
|
409
|
-
}
|
|
410
|
-
}))();
|
|
411
|
-
yield wait(0);
|
|
412
|
-
return authStatus;
|
|
413
|
-
});
|
|
373
|
+
})();
|
|
374
|
+
await wait(0);
|
|
375
|
+
return authStatus;
|
|
414
376
|
}
|
|
415
377
|
_tryReconnect(initialDelay) {
|
|
416
378
|
let exponent = this.connectAttempts++;
|
|
@@ -468,9 +430,12 @@ export class ClientSocket extends Client {
|
|
|
468
430
|
}
|
|
469
431
|
// If the user invokes the callback while in autoSubscribeOnConnect mode, it
|
|
470
432
|
// won't break anything.
|
|
471
|
-
this.emit('connect',
|
|
433
|
+
this.emit('connect', {
|
|
434
|
+
...status,
|
|
435
|
+
processPendingSubscriptions: () => {
|
|
472
436
|
this.processPendingSubscriptions();
|
|
473
|
-
}
|
|
437
|
+
}
|
|
438
|
+
});
|
|
474
439
|
if (this.state === SocketState.OPEN) {
|
|
475
440
|
this._flushOutboundBuffer();
|
|
476
441
|
}
|
|
@@ -497,7 +462,7 @@ export class ClientSocket extends Client {
|
|
|
497
462
|
let callback = eventObject.callback;
|
|
498
463
|
if (callback) {
|
|
499
464
|
delete eventObject.callback;
|
|
500
|
-
let errorMessage = `Event
|
|
465
|
+
let errorMessage = `Event ${eventObject.event} was aborted due to a bad connection`;
|
|
501
466
|
let error = new BadConnectionError(errorMessage, failureType);
|
|
502
467
|
callback.call(eventObject, error, eventObject);
|
|
503
468
|
}
|
|
@@ -526,7 +491,7 @@ export class ClientSocket extends Client {
|
|
|
526
491
|
this.emit('close', { code, reason });
|
|
527
492
|
if (!socketProtocolIgnoreStatuses[code]) {
|
|
528
493
|
let closeMessage;
|
|
529
|
-
if (reason) {
|
|
494
|
+
if (typeof reason === 'string') {
|
|
530
495
|
closeMessage = 'Socket connection closed with status code ' + code + ' and reason: ' + reason;
|
|
531
496
|
}
|
|
532
497
|
else {
|
|
@@ -559,7 +524,10 @@ export class ClientSocket extends Client {
|
|
|
559
524
|
}
|
|
560
525
|
}
|
|
561
526
|
_onInboundTransmit(event, data) {
|
|
527
|
+
data = data || {};
|
|
562
528
|
if (event === '#publish') {
|
|
529
|
+
if (typeof data.channel !== 'string')
|
|
530
|
+
return;
|
|
563
531
|
let undecoratedChannelName = this._undecorateChannelName(data.channel);
|
|
564
532
|
let isSubscribed = this.isSubscribed(undecoratedChannelName, true);
|
|
565
533
|
if (isSubscribed) {
|
|
@@ -567,6 +535,8 @@ export class ClientSocket extends Client {
|
|
|
567
535
|
}
|
|
568
536
|
}
|
|
569
537
|
else if (event === '#kickOut') {
|
|
538
|
+
if (typeof data.channel !== 'string')
|
|
539
|
+
return;
|
|
570
540
|
let undecoratedChannelName = this._undecorateChannelName(data.channel);
|
|
571
541
|
let channel = this._channelMap[undecoratedChannelName];
|
|
572
542
|
if (channel) {
|
|
@@ -598,7 +568,9 @@ export class ClientSocket extends Client {
|
|
|
598
568
|
request.end();
|
|
599
569
|
}
|
|
600
570
|
else {
|
|
601
|
-
|
|
571
|
+
let error = new InvalidMessageError('No token data provided by #setAuthToken event');
|
|
572
|
+
delete error.stack;
|
|
573
|
+
request.error(error);
|
|
602
574
|
}
|
|
603
575
|
}
|
|
604
576
|
else if (procedure === '#removeAuthToken') {
|
|
@@ -634,7 +606,7 @@ export class ClientSocket extends Client {
|
|
|
634
606
|
let callback = eventObject.callback;
|
|
635
607
|
if (callback) {
|
|
636
608
|
delete eventObject.callback;
|
|
637
|
-
let error = new TimeoutError(`Event response for
|
|
609
|
+
let error = new TimeoutError(`Event response for ${eventObject.event} event timed out`);
|
|
638
610
|
callback.call(eventObject, error, eventObject);
|
|
639
611
|
}
|
|
640
612
|
// Cleanup any pending response callback in the transport layer too.
|
|
@@ -716,7 +688,10 @@ export class ClientSocket extends Client {
|
|
|
716
688
|
this._channelEventDemux.write(`${channelName}/subscribe`, {
|
|
717
689
|
subscriptionOptions
|
|
718
690
|
});
|
|
719
|
-
this.emit('subscribeStateChange',
|
|
691
|
+
this.emit('subscribeStateChange', {
|
|
692
|
+
channel: channelName,
|
|
693
|
+
...stateChangeData
|
|
694
|
+
});
|
|
720
695
|
this.emit('subscribe', {
|
|
721
696
|
channel: channelName,
|
|
722
697
|
subscriptionOptions
|
|
@@ -821,7 +796,10 @@ export class ClientSocket extends Client {
|
|
|
821
796
|
if (channel.options.data) {
|
|
822
797
|
subscriptionOptions.data = channel.options.data;
|
|
823
798
|
}
|
|
824
|
-
channel._pendingSubscriptionCid = this.transport.invokeRaw('#subscribe',
|
|
799
|
+
channel._pendingSubscriptionCid = this.transport.invokeRaw('#subscribe', {
|
|
800
|
+
channel: this._decorateChannelName(channel.name),
|
|
801
|
+
...subscriptionOptions
|
|
802
|
+
}, options, (err) => {
|
|
825
803
|
if (err) {
|
|
826
804
|
if (err.name === 'BadConnectionError') {
|
|
827
805
|
// In case of a failed connection, keep the subscription
|
|
@@ -858,7 +836,10 @@ export class ClientSocket extends Client {
|
|
|
858
836
|
};
|
|
859
837
|
this._channelEventDemux.write(`${channelName}/subscribeStateChange`, stateChangeData);
|
|
860
838
|
this._channelEventDemux.write(`${channelName}/unsubscribe`, {});
|
|
861
|
-
this.emit('subscribeStateChange',
|
|
839
|
+
this.emit('subscribeStateChange', {
|
|
840
|
+
channel: channelName,
|
|
841
|
+
...stateChangeData
|
|
842
|
+
});
|
|
862
843
|
this.emit('unsubscribe', { channel: channelName });
|
|
863
844
|
}
|
|
864
845
|
if (setAsPending) {
|