@socket-mesh/client 18.0.8 → 18.1.0
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 -2
- package/dist/client-auth-engine.d.ts +22 -0
- package/dist/client-auth-engine.js +52 -0
- package/dist/client-channels.d.ts +22 -0
- package/dist/client-channels.js +149 -0
- package/dist/client-socket-options.d.ts +24 -0
- package/dist/client-socket-options.js +6 -0
- package/dist/client-socket.d.ts +26 -0
- package/dist/client-socket.js +100 -0
- package/dist/client-transport.d.ts +52 -0
- package/dist/client-transport.js +261 -0
- package/dist/handlers/index.d.ts +4 -0
- package/dist/handlers/index.js +4 -0
- package/dist/handlers/kickout.d.ts +6 -0
- package/dist/handlers/kickout.js +5 -0
- package/dist/handlers/publish.d.ts +7 -0
- package/dist/handlers/publish.js +3 -0
- package/dist/handlers/remove-auth-token.d.ts +2 -0
- package/dist/handlers/remove-auth-token.js +3 -0
- package/dist/handlers/set-auth-token.d.ts +3 -0
- package/dist/handlers/set-auth-token.js +3 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/maps/client-map.d.ts +21 -0
- package/dist/maps/client-map.js +1 -0
- package/dist/maps/index.d.ts +3 -0
- package/dist/maps/index.js +3 -0
- package/dist/maps/server-map.d.ts +27 -0
- package/dist/maps/server-map.js +1 -0
- package/dist/maps/socket-map.d.ts +17 -0
- package/dist/maps/socket-map.js +1 -0
- package/dist/plugins/batching-plugin.d.ts +41 -0
- package/dist/plugins/batching-plugin.js +111 -0
- package/dist/plugins/in-order-plugin.d.ts +10 -0
- package/dist/plugins/in-order-plugin.js +70 -0
- package/dist/plugins/index.d.ts +3 -0
- package/dist/plugins/index.js +3 -0
- package/dist/plugins/offline-plugin.d.ts +13 -0
- package/dist/plugins/offline-plugin.js +47 -0
- package/package.json +54 -58
- package/auth.d.ts +0 -21
- package/auth.js +0 -49
- package/auth.js.map +0 -1
- package/client-options.d.ts +0 -53
- package/client-options.js +0 -2
- package/client-options.js.map +0 -1
- package/clientsocket.d.ts +0 -135
- package/clientsocket.js +0 -898
- package/clientsocket.js.map +0 -1
- package/events.d.ts +0 -54
- package/events.js +0 -2
- package/events.js.map +0 -1
- package/factory.d.ts +0 -3
- package/factory.js +0 -37
- package/factory.js.map +0 -1
- package/index.d.ts +0 -7
- package/index.js +0 -10
- package/index.js.map +0 -1
- package/remote-procedure.d.ts +0 -6
- package/remote-procedure.js +0 -10
- package/remote-procedure.js.map +0 -1
- package/socket-state.d.ts +0 -5
- package/socket-state.js +0 -7
- package/socket-state.js.map +0 -1
- package/transport-handlers.d.ts +0 -37
- package/transport-handlers.js +0 -2
- package/transport-handlers.js.map +0 -1
- package/transport.d.ts +0 -84
- package/transport.js +0 -441
- package/transport.js.map +0 -1
- package/wait.d.ts +0 -1
- package/wait.js +0 -8
- package/wait.js.map +0 -1
- package/ws-browser.d.ts +0 -15
- package/ws-browser.js +0 -40
- package/ws-browser.js.map +0 -1
package/README.md
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SignedAuthToken } from "@socket-mesh/auth";
|
|
2
|
+
export interface ClientAuthEngine {
|
|
3
|
+
saveToken(token: SignedAuthToken, options?: {
|
|
4
|
+
[key: string]: any;
|
|
5
|
+
}): Promise<SignedAuthToken>;
|
|
6
|
+
removeToken(): Promise<SignedAuthToken>;
|
|
7
|
+
loadToken(): Promise<SignedAuthToken | null>;
|
|
8
|
+
}
|
|
9
|
+
export declare function isAuthEngine(auth: ClientAuthEngine | LocalStorageAuthEngineOptions): auth is ClientAuthEngine;
|
|
10
|
+
export interface LocalStorageAuthEngineOptions {
|
|
11
|
+
authTokenName?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class LocalStorageAuthEngine implements ClientAuthEngine {
|
|
14
|
+
private readonly _authTokenName;
|
|
15
|
+
private readonly _internalStorage;
|
|
16
|
+
readonly isLocalStorageEnabled: boolean;
|
|
17
|
+
constructor({ authTokenName }?: LocalStorageAuthEngineOptions);
|
|
18
|
+
private _checkLocalStorageEnabled;
|
|
19
|
+
saveToken(token: string): Promise<SignedAuthToken>;
|
|
20
|
+
removeToken(): Promise<SignedAuthToken>;
|
|
21
|
+
loadToken(): Promise<SignedAuthToken>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function isAuthEngine(auth) {
|
|
2
|
+
return (typeof auth === 'object' && 'saveToken' in auth && 'removeToken' in auth && 'loadToken' in auth);
|
|
3
|
+
}
|
|
4
|
+
export class LocalStorageAuthEngine {
|
|
5
|
+
constructor({ authTokenName } = {}) {
|
|
6
|
+
this._internalStorage = {};
|
|
7
|
+
this.isLocalStorageEnabled = this._checkLocalStorageEnabled();
|
|
8
|
+
this._authTokenName = authTokenName ?? 'socketmesh.authToken';
|
|
9
|
+
}
|
|
10
|
+
_checkLocalStorageEnabled() {
|
|
11
|
+
let err;
|
|
12
|
+
try {
|
|
13
|
+
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
|
|
14
|
+
// throw QuotaExceededError. We're going to detect this and avoid hard to debug edge cases.
|
|
15
|
+
localStorage.setItem('__localStorageTest', "1");
|
|
16
|
+
localStorage.removeItem('__localStorageTest');
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
err = e;
|
|
20
|
+
}
|
|
21
|
+
return !err;
|
|
22
|
+
}
|
|
23
|
+
async saveToken(token) {
|
|
24
|
+
if (this.isLocalStorageEnabled) {
|
|
25
|
+
localStorage.setItem(this._authTokenName, token);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this._internalStorage[this._authTokenName] = token;
|
|
29
|
+
}
|
|
30
|
+
return token;
|
|
31
|
+
}
|
|
32
|
+
async removeToken() {
|
|
33
|
+
let loadPromise = this.loadToken();
|
|
34
|
+
if (this.isLocalStorageEnabled) {
|
|
35
|
+
localStorage.removeItem(this._authTokenName);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
delete this._internalStorage[this._authTokenName];
|
|
39
|
+
}
|
|
40
|
+
return loadPromise;
|
|
41
|
+
}
|
|
42
|
+
async loadToken() {
|
|
43
|
+
let token;
|
|
44
|
+
if (this.isLocalStorageEnabled) {
|
|
45
|
+
token = localStorage.getItem(this._authTokenName);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
token = this._internalStorage[this._authTokenName] || null;
|
|
49
|
+
}
|
|
50
|
+
return token;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ChannelDetails, Channels, ChannelsOptions } from "@socket-mesh/channels";
|
|
2
|
+
import { ClientTransport } from "./client-transport.js";
|
|
3
|
+
import { ClientMap } from "./maps/client-map.js";
|
|
4
|
+
export interface ClientChannelsOptions extends ChannelsOptions {
|
|
5
|
+
autoSubscribeOnConnect?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare class ClientChannels<T extends ClientMap> extends Channels<T['Channel']> {
|
|
8
|
+
autoSubscribeOnConnect: boolean;
|
|
9
|
+
protected readonly _transport: ClientTransport<T>;
|
|
10
|
+
protected _preparingPendingSubscriptions: boolean;
|
|
11
|
+
constructor(transport: ClientTransport<T>, options?: ClientChannelsOptions);
|
|
12
|
+
private suspendSubscriptions;
|
|
13
|
+
protected trySubscribe(channel: ChannelDetails): void;
|
|
14
|
+
private processPendingSubscriptions;
|
|
15
|
+
unsubscribe(channelName: keyof T['Channel'] & string | string): void;
|
|
16
|
+
protected tryUnsubscribe(channel: ChannelDetails): void;
|
|
17
|
+
private triggerChannelSubscribeFail;
|
|
18
|
+
transmitPublish<U extends keyof T['Channel'] & string>(channelName: U, data: T['Channel'][U]): Promise<void>;
|
|
19
|
+
transmitPublish<U>(channelName: string, data: U): Promise<void>;
|
|
20
|
+
invokePublish<U extends keyof T['Channel'] & string>(channelName: keyof T['Channel'] & string, data: T['Channel'][U]): Promise<void>;
|
|
21
|
+
invokePublish<U>(channelName: string, data: U): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Channels } from "@socket-mesh/channels";
|
|
2
|
+
export class ClientChannels extends Channels {
|
|
3
|
+
constructor(transport, options) {
|
|
4
|
+
if (!options) {
|
|
5
|
+
options = {};
|
|
6
|
+
}
|
|
7
|
+
super(options);
|
|
8
|
+
this.autoSubscribeOnConnect = options.autoSubscribeOnConnect ?? true;
|
|
9
|
+
this._transport = transport;
|
|
10
|
+
this._preparingPendingSubscriptions = false;
|
|
11
|
+
this._transport.plugins.push({
|
|
12
|
+
type: 'channels',
|
|
13
|
+
onAuthenticated: () => {
|
|
14
|
+
if (!this._preparingPendingSubscriptions) {
|
|
15
|
+
this.processPendingSubscriptions();
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
onReady: () => {
|
|
19
|
+
if (this.autoSubscribeOnConnect) {
|
|
20
|
+
this.processPendingSubscriptions();
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
onClose: () => {
|
|
24
|
+
this.suspendSubscriptions();
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
suspendSubscriptions() {
|
|
29
|
+
for (const channel in this._channelMap) {
|
|
30
|
+
this.triggerChannelUnsubscribe(this._channelMap[channel], true);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
trySubscribe(channel) {
|
|
34
|
+
const meetsAuthRequirements = !channel.options.waitForAuth || !!this._transport.signedAuthToken;
|
|
35
|
+
// We can only ever have one pending subscribe action at any given time on a channel
|
|
36
|
+
if (this._transport.status === 'ready' &&
|
|
37
|
+
!this._preparingPendingSubscriptions &&
|
|
38
|
+
!channel.subscribePromise &&
|
|
39
|
+
meetsAuthRequirements) {
|
|
40
|
+
const subscriptionOptions = {};
|
|
41
|
+
if (channel.options.waitForAuth) {
|
|
42
|
+
subscriptionOptions.waitForAuth = true;
|
|
43
|
+
}
|
|
44
|
+
if (channel.options.data) {
|
|
45
|
+
subscriptionOptions.data = channel.options.data;
|
|
46
|
+
}
|
|
47
|
+
[channel.subscribePromise, channel.subscribeAbort] = this._transport.invoke({ method: '#subscribe', ackTimeoutMs: false }, {
|
|
48
|
+
channel: this.decorateChannelName(channel.name),
|
|
49
|
+
...subscriptionOptions
|
|
50
|
+
});
|
|
51
|
+
channel.subscribePromise.then(() => {
|
|
52
|
+
delete channel.subscribePromise;
|
|
53
|
+
delete channel.subscribeAbort;
|
|
54
|
+
this.triggerChannelSubscribe(channel, subscriptionOptions);
|
|
55
|
+
}).catch(err => {
|
|
56
|
+
if (err.name === 'BadConnectionError') {
|
|
57
|
+
// In case of a failed connection, keep the subscription
|
|
58
|
+
// as pending; it will try again on reconnect.
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (err.name !== 'AbortError') {
|
|
62
|
+
this.triggerChannelSubscribeFail(err, channel, subscriptionOptions);
|
|
63
|
+
}
|
|
64
|
+
delete channel.subscribePromise;
|
|
65
|
+
delete channel.subscribeAbort;
|
|
66
|
+
});
|
|
67
|
+
this.emit('subscribeRequest', {
|
|
68
|
+
channel: channel.name,
|
|
69
|
+
options: subscriptionOptions
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
processPendingSubscriptions() {
|
|
74
|
+
this._preparingPendingSubscriptions = false;
|
|
75
|
+
const pendingChannels = [];
|
|
76
|
+
Object.keys(this._channelMap).forEach((channelName) => {
|
|
77
|
+
const channel = this._channelMap[channelName];
|
|
78
|
+
if (channel.state === 'pending') {
|
|
79
|
+
pendingChannels.push(channel);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
pendingChannels.sort((a, b) => {
|
|
83
|
+
const ap = a.options.priority || 0;
|
|
84
|
+
const bp = b.options.priority || 0;
|
|
85
|
+
if (ap > bp) {
|
|
86
|
+
return -1;
|
|
87
|
+
}
|
|
88
|
+
if (ap < bp) {
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
return 0;
|
|
92
|
+
});
|
|
93
|
+
pendingChannels.forEach((channel) => {
|
|
94
|
+
this.trySubscribe(channel);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
unsubscribe(channelName) {
|
|
98
|
+
const channel = this._channelMap[channelName];
|
|
99
|
+
if (channel) {
|
|
100
|
+
this.tryUnsubscribe(channel);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
tryUnsubscribe(channel) {
|
|
104
|
+
this.triggerChannelUnsubscribe(channel);
|
|
105
|
+
if (this._transport.status === 'ready') {
|
|
106
|
+
// If there is a pending subscribe action, cancel the callback
|
|
107
|
+
this.cancelPendingSubscribeCallback(channel);
|
|
108
|
+
const decoratedChannelName = this.decorateChannelName(channel.name);
|
|
109
|
+
// This operation cannot fail because the TCP protocol guarantees delivery
|
|
110
|
+
// so long as the connection remains open. If the connection closes,
|
|
111
|
+
// the server will automatically unsubscribe the client and thus complete
|
|
112
|
+
// the operation on the server side.
|
|
113
|
+
this._transport
|
|
114
|
+
.transmit('#unsubscribe', decoratedChannelName)
|
|
115
|
+
.catch(err => { });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
triggerChannelSubscribeFail(err, channel, options) {
|
|
119
|
+
const meetsAuthRequirements = !channel.options.waitForAuth || !!this._transport.signedAuthToken;
|
|
120
|
+
const hasChannel = !!this._channelMap[channel.name];
|
|
121
|
+
if (hasChannel && meetsAuthRequirements) {
|
|
122
|
+
delete this._channelMap[channel.name];
|
|
123
|
+
this._channelEventDemux.write(`${channel.name}/subscribeFail`, {
|
|
124
|
+
channel: channel.name,
|
|
125
|
+
error: err,
|
|
126
|
+
options
|
|
127
|
+
});
|
|
128
|
+
this.emit('subscribeFail', {
|
|
129
|
+
error: err,
|
|
130
|
+
channel: channel.name,
|
|
131
|
+
options
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
transmitPublish(channelName, data) {
|
|
136
|
+
const pubData = {
|
|
137
|
+
channel: this.decorateChannelName(channelName),
|
|
138
|
+
data
|
|
139
|
+
};
|
|
140
|
+
return this._transport.transmit('#publish', pubData);
|
|
141
|
+
}
|
|
142
|
+
invokePublish(channelName, data) {
|
|
143
|
+
const pubData = {
|
|
144
|
+
channel: this.decorateChannelName(channelName),
|
|
145
|
+
data
|
|
146
|
+
};
|
|
147
|
+
return this._transport.invoke('#publish', pubData)[0];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import ws from "isomorphic-ws";
|
|
2
|
+
import { SocketOptions } from "@socket-mesh/core";
|
|
3
|
+
import { ClientAuthEngine, LocalStorageAuthEngineOptions } from "./client-auth-engine.js";
|
|
4
|
+
import { SocketMapFromClient } from "./maps/socket-map.js";
|
|
5
|
+
import { ClientMap } from "./maps/client-map.js";
|
|
6
|
+
export interface AutoReconnectOptions {
|
|
7
|
+
initialDelay: number;
|
|
8
|
+
randomness: number;
|
|
9
|
+
multiplier: number;
|
|
10
|
+
maxDelayMs: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ConnectOptions {
|
|
13
|
+
address?: string | URL;
|
|
14
|
+
connectTimeoutMs?: number;
|
|
15
|
+
wsOptions?: ws.ClientOptions;
|
|
16
|
+
}
|
|
17
|
+
export interface ClientSocketOptions<T extends ClientMap> extends SocketOptions<SocketMapFromClient<T>>, ConnectOptions {
|
|
18
|
+
autoConnect?: boolean;
|
|
19
|
+
authEngine?: ClientAuthEngine | LocalStorageAuthEngineOptions | null;
|
|
20
|
+
autoReconnect?: Partial<AutoReconnectOptions> | boolean;
|
|
21
|
+
autoSubscribeOnConnect?: boolean;
|
|
22
|
+
channelPrefix?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function parseClientOptions<T extends ClientMap>(options: ClientSocketOptions<T> | string | URL): ClientSocketOptions<T>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AutoReconnectOptions, ClientSocketOptions, ConnectOptions } from "./client-socket-options.js";
|
|
2
|
+
import { SignedAuthToken } from "@socket-mesh/auth";
|
|
3
|
+
import { Socket } from "@socket-mesh/core";
|
|
4
|
+
import { ClientChannels } from "./client-channels.js";
|
|
5
|
+
import { SocketMapFromClient } from "./maps/socket-map.js";
|
|
6
|
+
import { ClientMap } from "./maps/client-map.js";
|
|
7
|
+
export declare class ClientSocket<T extends ClientMap> extends Socket<SocketMapFromClient<T>> {
|
|
8
|
+
private readonly _clientTransport;
|
|
9
|
+
readonly channels: ClientChannels<T>;
|
|
10
|
+
constructor(address: string | URL);
|
|
11
|
+
constructor(options: ClientSocketOptions<T>);
|
|
12
|
+
authenticate(signedAuthToken: SignedAuthToken): Promise<void>;
|
|
13
|
+
get autoReconnect(): AutoReconnectOptions | false;
|
|
14
|
+
set autoReconnect(value: Partial<AutoReconnectOptions> | boolean);
|
|
15
|
+
connect(options?: ConnectOptions): void;
|
|
16
|
+
get connectTimeoutMs(): number;
|
|
17
|
+
set connectTimeoutMs(timeoutMs: number);
|
|
18
|
+
deauthenticate(): Promise<boolean>;
|
|
19
|
+
get isPingTimeoutDisabled(): boolean;
|
|
20
|
+
set isPingTimeoutDisabled(isDisabled: boolean);
|
|
21
|
+
get pingTimeoutMs(): number;
|
|
22
|
+
set pingTimeoutMs(timeoutMs: number);
|
|
23
|
+
reconnect(code?: number, reason?: string): void;
|
|
24
|
+
get type(): 'client';
|
|
25
|
+
get uri(): URL;
|
|
26
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ClientTransport } from "./client-transport.js";
|
|
2
|
+
import { parseClientOptions } from "./client-socket-options.js";
|
|
3
|
+
import { setAuthTokenHandler } from "./handlers/set-auth-token.js";
|
|
4
|
+
import { removeAuthTokenHandler } from "./handlers/remove-auth-token.js";
|
|
5
|
+
import { hydrateError } from "@socket-mesh/errors";
|
|
6
|
+
import { Socket, wait } from "@socket-mesh/core";
|
|
7
|
+
import { ClientChannels } from "./client-channels.js";
|
|
8
|
+
import { publishHandler } from "./handlers/publish.js";
|
|
9
|
+
import { kickOutHandler } from "./handlers/kickout.js";
|
|
10
|
+
export class ClientSocket extends Socket {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
options = parseClientOptions(options);
|
|
13
|
+
options.handlers =
|
|
14
|
+
Object.assign({
|
|
15
|
+
"#kickOut": kickOutHandler,
|
|
16
|
+
"#publish": publishHandler,
|
|
17
|
+
"#setAuthToken": setAuthTokenHandler,
|
|
18
|
+
"#removeAuthToken": removeAuthTokenHandler
|
|
19
|
+
}, options.handlers);
|
|
20
|
+
const clientTransport = new ClientTransport(options);
|
|
21
|
+
super(clientTransport, options);
|
|
22
|
+
this._clientTransport = clientTransport;
|
|
23
|
+
this.channels = new ClientChannels(this._clientTransport, options);
|
|
24
|
+
if (options.autoConnect !== false) {
|
|
25
|
+
this.connect(options);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async authenticate(signedAuthToken) {
|
|
29
|
+
try {
|
|
30
|
+
await this._clientTransport.invoke('#authenticate', signedAuthToken)[0];
|
|
31
|
+
this._clientTransport.setAuthorization(signedAuthToken);
|
|
32
|
+
// In order for the events to trigger we need to wait for the next tick.
|
|
33
|
+
await wait(0);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (err.name !== 'BadConnectionError' && err.name !== 'TimeoutError') {
|
|
37
|
+
// In case of a bad/closed connection or a timeout, we maintain the last
|
|
38
|
+
// known auth state since those errors don't mean that the token is invalid.
|
|
39
|
+
await this._clientTransport.changeToUnauthenticatedState();
|
|
40
|
+
// In order for the events to trigger we need to wait for the next tick.
|
|
41
|
+
await wait(0);
|
|
42
|
+
}
|
|
43
|
+
throw hydrateError(err);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
get autoReconnect() {
|
|
47
|
+
return this._clientTransport.autoReconnect;
|
|
48
|
+
}
|
|
49
|
+
set autoReconnect(value) {
|
|
50
|
+
this._clientTransport.autoReconnect = value;
|
|
51
|
+
}
|
|
52
|
+
connect(options) {
|
|
53
|
+
this._clientTransport.connect(options);
|
|
54
|
+
}
|
|
55
|
+
get connectTimeoutMs() {
|
|
56
|
+
return this._clientTransport.connectTimeoutMs;
|
|
57
|
+
}
|
|
58
|
+
set connectTimeoutMs(timeoutMs) {
|
|
59
|
+
this._clientTransport.connectTimeoutMs = timeoutMs;
|
|
60
|
+
}
|
|
61
|
+
async deauthenticate() {
|
|
62
|
+
(async () => {
|
|
63
|
+
let oldAuthToken;
|
|
64
|
+
try {
|
|
65
|
+
oldAuthToken = await this._clientTransport.authEngine.removeToken();
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
this._clientTransport.onError(err);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.emit('removeAuthToken', { oldAuthToken });
|
|
72
|
+
})();
|
|
73
|
+
if (this.status !== 'closed') {
|
|
74
|
+
await this._clientTransport.transmit('#removeAuthToken');
|
|
75
|
+
}
|
|
76
|
+
return await super.deauthenticate();
|
|
77
|
+
}
|
|
78
|
+
get isPingTimeoutDisabled() {
|
|
79
|
+
return this._clientTransport.isPingTimeoutDisabled;
|
|
80
|
+
}
|
|
81
|
+
set isPingTimeoutDisabled(isDisabled) {
|
|
82
|
+
this._clientTransport.isPingTimeoutDisabled = isDisabled;
|
|
83
|
+
}
|
|
84
|
+
get pingTimeoutMs() {
|
|
85
|
+
return this._clientTransport.pingTimeoutMs;
|
|
86
|
+
}
|
|
87
|
+
set pingTimeoutMs(timeoutMs) {
|
|
88
|
+
this._clientTransport.pingTimeoutMs = timeoutMs;
|
|
89
|
+
}
|
|
90
|
+
reconnect(code, reason) {
|
|
91
|
+
this.disconnect(code, reason);
|
|
92
|
+
this.connect();
|
|
93
|
+
}
|
|
94
|
+
get type() {
|
|
95
|
+
return this._clientTransport.type;
|
|
96
|
+
}
|
|
97
|
+
get uri() {
|
|
98
|
+
return this._clientTransport.uri;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { AnyPacket, AnyResponse, FunctionReturnType, InvokeMethodOptions, InvokeServiceOptions, SocketTransport, SocketStatus } from "@socket-mesh/core";
|
|
2
|
+
import ws from "isomorphic-ws";
|
|
3
|
+
import { ClientAuthEngine } from "./client-auth-engine.js";
|
|
4
|
+
import { ServerPrivateMap } from "./maps/server-map.js";
|
|
5
|
+
import { AutoReconnectOptions, ClientSocketOptions, ConnectOptions } from "./client-socket-options.js";
|
|
6
|
+
import { AuthToken } from "@socket-mesh/auth";
|
|
7
|
+
import { SocketMapFromClient } from "./maps/socket-map.js";
|
|
8
|
+
import { ClientMap } from "./maps/client-map.js";
|
|
9
|
+
export declare class ClientTransport<T extends ClientMap> extends SocketTransport<SocketMapFromClient<T>> {
|
|
10
|
+
readonly authEngine: ClientAuthEngine;
|
|
11
|
+
private _uri;
|
|
12
|
+
private _wsOptions;
|
|
13
|
+
connectTimeoutMs: number;
|
|
14
|
+
private _connectTimeoutRef;
|
|
15
|
+
private _autoReconnect;
|
|
16
|
+
private _connectAttempts;
|
|
17
|
+
private _pendingReconnectTimeout;
|
|
18
|
+
private _pingTimeoutMs;
|
|
19
|
+
isPingTimeoutDisabled: boolean;
|
|
20
|
+
constructor(options: ClientSocketOptions<T>);
|
|
21
|
+
get autoReconnect(): AutoReconnectOptions | false;
|
|
22
|
+
set autoReconnect(value: Partial<AutoReconnectOptions> | boolean);
|
|
23
|
+
connect(options?: ConnectOptions): void;
|
|
24
|
+
get connectAttempts(): number;
|
|
25
|
+
protected decode(data: string | ws.RawData): AnyPacket<SocketMapFromClient<T>> | AnyPacket<SocketMapFromClient<T>>[] | AnyResponse<SocketMapFromClient<T>> | AnyResponse<SocketMapFromClient<T>>[];
|
|
26
|
+
disconnect(code?: number, reason?: string): void;
|
|
27
|
+
private handshake;
|
|
28
|
+
protected onOpen(): void;
|
|
29
|
+
protected onPing(data: Buffer): void;
|
|
30
|
+
protected onClose(code: number, reason?: Buffer): void;
|
|
31
|
+
get pendingReconnect(): boolean;
|
|
32
|
+
get pingTimeoutMs(): number;
|
|
33
|
+
set pingTimeoutMs(value: number);
|
|
34
|
+
private resetReconnect;
|
|
35
|
+
setAuthorization(authToken: AuthToken): Promise<boolean>;
|
|
36
|
+
setAuthorization(signedAuthToken: string, authToken?: AuthToken): Promise<boolean>;
|
|
37
|
+
get status(): SocketStatus;
|
|
38
|
+
private tryReconnect;
|
|
39
|
+
type: 'client';
|
|
40
|
+
get uri(): URL;
|
|
41
|
+
protected get webSocket(): ws.WebSocket | null;
|
|
42
|
+
protected set webSocket(value: ws.WebSocket | null);
|
|
43
|
+
transmit<TMethod extends keyof SocketMapFromClient<T>['Outgoing']>(method: TMethod, arg?: Parameters<SocketMapFromClient<T>['Outgoing'][TMethod]>[0]): Promise<void>;
|
|
44
|
+
transmit<TService extends keyof SocketMapFromClient<T>['Service'], TMethod extends keyof SocketMapFromClient<T>['Service'][TService]>(options: [TService, TMethod], arg?: Parameters<SocketMapFromClient<T>['Service'][TService][TMethod]>[0]): Promise<void>;
|
|
45
|
+
transmit<TMethod extends keyof (SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)>(method: TMethod, arg?: Parameters<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)[TMethod]>[0]): Promise<void>;
|
|
46
|
+
invoke<TMethod extends keyof SocketMapFromClient<T>['Outgoing']>(method: TMethod, arg?: Parameters<SocketMapFromClient<T>['Outgoing'][TMethod]>[0]): [Promise<FunctionReturnType<SocketMapFromClient<T>['Outgoing'][TMethod]>>, () => void];
|
|
47
|
+
invoke<TService extends keyof SocketMapFromClient<T>['Service'], TMethod extends keyof SocketMapFromClient<T>['Service'][TService]>(options: [TService, TMethod, (number | false)?], arg?: Parameters<SocketMapFromClient<T>['Service'][TService][TMethod]>[0]): [Promise<FunctionReturnType<SocketMapFromClient<T>['Service'][TService][TMethod]>>, () => void];
|
|
48
|
+
invoke<TService extends keyof SocketMapFromClient<T>['Service'], TMethod extends keyof SocketMapFromClient<T>['Service'][TService]>(options: InvokeServiceOptions<SocketMapFromClient<T>['Service'], TService, TMethod>, arg?: Parameters<SocketMapFromClient<T>['Service'][TService][TMethod]>[0]): [Promise<FunctionReturnType<SocketMapFromClient<T>['Service'][TService][TMethod]>>, () => void];
|
|
49
|
+
invoke<TMethod extends keyof SocketMapFromClient<T>['Outgoing']>(options: InvokeMethodOptions<SocketMapFromClient<T>['Outgoing'], TMethod>, arg?: Parameters<SocketMapFromClient<T>['Outgoing'][TMethod]>[0]): [Promise<FunctionReturnType<SocketMapFromClient<T>['Outgoing'][TMethod]>>, () => void];
|
|
50
|
+
invoke<TMethod extends keyof (SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)>(method: TMethod, arg: Parameters<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)[TMethod]>[0]): [Promise<FunctionReturnType<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)[TMethod]>>, () => void];
|
|
51
|
+
invoke<TMethod extends keyof (SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)>(options: InvokeMethodOptions<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap), TMethod>, arg?: Parameters<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)[TMethod]>[0]): [Promise<FunctionReturnType<(SocketMapFromClient<T>['PrivateOutgoing'] & ServerPrivateMap)[TMethod]>>, () => void];
|
|
52
|
+
}
|