@socket-mesh/client 18.1.5 → 19.0.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.
@@ -1,22 +1,22 @@
1
- import { SignedAuthToken } from "@socket-mesh/auth";
1
+ import { SignedAuthToken } from '@socket-mesh/auth';
2
2
  export interface ClientAuthEngine {
3
+ loadToken(): Promise<null | SignedAuthToken>;
4
+ removeToken(): Promise<null | SignedAuthToken>;
3
5
  saveToken(token: SignedAuthToken, options?: {
4
6
  [key: string]: any;
5
7
  }): Promise<SignedAuthToken>;
6
- removeToken(): Promise<SignedAuthToken>;
7
- loadToken(): Promise<SignedAuthToken | null>;
8
8
  }
9
- export declare function isAuthEngine(auth: ClientAuthEngine | LocalStorageAuthEngineOptions): auth is ClientAuthEngine;
10
9
  export interface LocalStorageAuthEngineOptions {
11
10
  authTokenName?: string;
12
11
  }
12
+ export declare function isAuthEngine(auth?: ClientAuthEngine | LocalStorageAuthEngineOptions | null): auth is ClientAuthEngine;
13
13
  export declare class LocalStorageAuthEngine implements ClientAuthEngine {
14
14
  private readonly _authTokenName;
15
15
  private readonly _internalStorage;
16
16
  readonly isLocalStorageEnabled: boolean;
17
17
  constructor({ authTokenName }?: LocalStorageAuthEngineOptions);
18
- private _checkLocalStorageEnabled;
18
+ private checkLocalStorageEnabled;
19
+ loadToken(): Promise<null | SignedAuthToken>;
20
+ removeToken(): Promise<null | SignedAuthToken>;
19
21
  saveToken(token: string): Promise<SignedAuthToken>;
20
- removeToken(): Promise<SignedAuthToken>;
21
- loadToken(): Promise<SignedAuthToken>;
22
22
  }
@@ -1,18 +1,21 @@
1
1
  export function isAuthEngine(auth) {
2
- return (typeof auth === 'object' && 'saveToken' in auth && 'removeToken' in auth && 'loadToken' in auth);
2
+ return (!!auth && typeof auth === 'object' && 'saveToken' in auth && 'removeToken' in auth && 'loadToken' in auth);
3
3
  }
4
4
  export class LocalStorageAuthEngine {
5
+ _authTokenName;
6
+ _internalStorage;
7
+ isLocalStorageEnabled;
5
8
  constructor({ authTokenName } = {}) {
6
9
  this._internalStorage = {};
7
- this.isLocalStorageEnabled = this._checkLocalStorageEnabled();
10
+ this.isLocalStorageEnabled = this.checkLocalStorageEnabled();
8
11
  this._authTokenName = authTokenName ?? 'socketmesh.authToken';
9
12
  }
10
- _checkLocalStorageEnabled() {
13
+ checkLocalStorageEnabled() {
11
14
  let err;
12
15
  try {
13
16
  // Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
14
17
  // throw QuotaExceededError. We're going to detect this and avoid hard to debug edge cases.
15
- localStorage.setItem('__localStorageTest', "1");
18
+ localStorage.setItem('__localStorageTest', '1');
16
19
  localStorage.removeItem('__localStorageTest');
17
20
  }
18
21
  catch (e) {
@@ -20,17 +23,18 @@ export class LocalStorageAuthEngine {
20
23
  }
21
24
  return !err;
22
25
  }
23
- async saveToken(token) {
26
+ async loadToken() {
27
+ let token;
24
28
  if (this.isLocalStorageEnabled) {
25
- localStorage.setItem(this._authTokenName, token);
29
+ token = localStorage.getItem(this._authTokenName);
26
30
  }
27
31
  else {
28
- this._internalStorage[this._authTokenName] = token;
32
+ token = this._internalStorage[this._authTokenName] || null;
29
33
  }
30
34
  return token;
31
35
  }
32
36
  async removeToken() {
33
- let loadPromise = this.loadToken();
37
+ const loadPromise = this.loadToken();
34
38
  if (this.isLocalStorageEnabled) {
35
39
  localStorage.removeItem(this._authTokenName);
36
40
  }
@@ -39,13 +43,12 @@ export class LocalStorageAuthEngine {
39
43
  }
40
44
  return loadPromise;
41
45
  }
42
- async loadToken() {
43
- let token;
46
+ async saveToken(token) {
44
47
  if (this.isLocalStorageEnabled) {
45
- token = localStorage.getItem(this._authTokenName);
48
+ localStorage.setItem(this._authTokenName, token);
46
49
  }
47
50
  else {
48
- token = this._internalStorage[this._authTokenName] || null;
51
+ this._internalStorage[this._authTokenName] = token;
49
52
  }
50
53
  return token;
51
54
  }
@@ -1,20 +1,21 @@
1
- import { ChannelDetails, ChannelMap, Channels, ChannelsOptions } from "@socket-mesh/channels";
2
- import { ClientTransport } from "./client-transport.js";
3
- import { MethodMap, PrivateMethodMap, PublicMethodMap, ServiceMap } from "@socket-mesh/core";
1
+ import { ChannelDetails, ChannelMap, Channels, ChannelsOptions } from '@socket-mesh/channels';
2
+ import { SocketTransport } from '@socket-mesh/core';
3
+ import { ClientTransport } from './client-transport.js';
4
+ import { ServerPrivateMap } from './maps/server-map.js';
4
5
  export interface ClientChannelsOptions extends ChannelsOptions {
5
6
  autoSubscribeOnConnect?: boolean;
6
7
  }
7
- export declare class ClientChannels<TChannel extends ChannelMap, TIncoming extends MethodMap, TService extends ServiceMap, TOutgoing extends PublicMethodMap, TPrivateOutgoing extends PrivateMethodMap, TState extends object> extends Channels<TChannel> {
8
- autoSubscribeOnConnect: boolean;
9
- protected readonly _transport: ClientTransport<TIncoming, TService, TOutgoing, TPrivateOutgoing, TState>;
8
+ export declare class ClientChannels<TChannel extends ChannelMap, TState extends object = {}> extends Channels<TChannel> {
10
9
  protected _preparingPendingSubscriptions: boolean;
11
- constructor(transport: ClientTransport<TIncoming, TService, TOutgoing, TPrivateOutgoing, TState>, options?: ClientChannelsOptions);
10
+ protected readonly _transport: SocketTransport<{}, {}, TState, {}, {}, ServerPrivateMap>;
11
+ autoSubscribeOnConnect: boolean;
12
+ constructor(transport: ClientTransport<TState>, options?: ClientChannelsOptions);
13
+ invokePublish<U extends keyof TChannel & string>(channelName: keyof TChannel & string, data: TChannel[U]): Promise<void>;
14
+ private processPendingSubscriptions;
12
15
  private suspendSubscriptions;
16
+ transmitPublish<U extends keyof TChannel & string>(channelName: U, data: TChannel[U]): Promise<void>;
17
+ private triggerChannelSubscribeFail;
13
18
  protected trySubscribe(channel: ChannelDetails): void;
14
- private processPendingSubscriptions;
15
- unsubscribe(channelName: keyof TChannel & string): void;
16
19
  protected tryUnsubscribe(channel: ChannelDetails): void;
17
- private triggerChannelSubscribeFail;
18
- transmitPublish<U extends keyof TChannel & string>(channelName: U, data: TChannel[U]): Promise<void>;
19
- invokePublish<U extends keyof TChannel & string>(channelName: keyof TChannel & string, data: TChannel[U]): Promise<void>;
20
+ unsubscribe(channelName: keyof TChannel & string): void;
20
21
  }
@@ -1,5 +1,9 @@
1
- import { Channels } from "@socket-mesh/channels";
1
+ import { Channels } from '@socket-mesh/channels';
2
+ import { toError } from '@socket-mesh/core';
2
3
  export class ClientChannels extends Channels {
4
+ _preparingPendingSubscriptions;
5
+ _transport;
6
+ autoSubscribeOnConnect;
3
7
  constructor(transport, options) {
4
8
  if (!options) {
5
9
  options = {};
@@ -9,20 +13,51 @@ export class ClientChannels extends Channels {
9
13
  this._transport = transport;
10
14
  this._preparingPendingSubscriptions = false;
11
15
  this._transport.plugins.push({
12
- type: 'channels',
13
16
  onAuthenticated: () => {
14
17
  if (!this._preparingPendingSubscriptions) {
15
18
  this.processPendingSubscriptions();
16
19
  }
17
20
  },
21
+ onClose: () => {
22
+ this.suspendSubscriptions();
23
+ },
18
24
  onReady: () => {
19
25
  if (this.autoSubscribeOnConnect) {
20
26
  this.processPendingSubscriptions();
21
27
  }
22
28
  },
23
- onClose: () => {
24
- this.suspendSubscriptions();
25
- },
29
+ type: 'channels'
30
+ });
31
+ }
32
+ invokePublish(channelName, data) {
33
+ const pubData = {
34
+ channel: this.decorateChannelName(channelName),
35
+ data
36
+ };
37
+ return this._transport.invoke('#publish', pubData)[0];
38
+ }
39
+ processPendingSubscriptions() {
40
+ this._preparingPendingSubscriptions = false;
41
+ const pendingChannels = [];
42
+ Object.keys(this._channelMap).forEach((channelName) => {
43
+ const channel = this._channelMap[channelName];
44
+ if (channel.state === 'pending') {
45
+ pendingChannels.push(channel);
46
+ }
47
+ });
48
+ pendingChannels.sort((a, b) => {
49
+ const ap = a.options.priority || 0;
50
+ const bp = b.options.priority || 0;
51
+ if (ap > bp) {
52
+ return -1;
53
+ }
54
+ if (ap < bp) {
55
+ return 1;
56
+ }
57
+ return 0;
58
+ });
59
+ pendingChannels.forEach((channel) => {
60
+ this.trySubscribe(channel);
26
61
  });
27
62
  }
28
63
  suspendSubscriptions() {
@@ -30,13 +65,37 @@ export class ClientChannels extends Channels {
30
65
  this.triggerChannelUnsubscribe(this._channelMap[channel], true);
31
66
  }
32
67
  }
68
+ transmitPublish(channelName, data) {
69
+ const pubData = {
70
+ channel: this.decorateChannelName(channelName),
71
+ data
72
+ };
73
+ return this._transport.transmit('#publish', pubData);
74
+ }
75
+ triggerChannelSubscribeFail(err, channel, options) {
76
+ const hasAuthRequirements = !channel.options.waitForAuth || !!this._transport.signedAuthToken;
77
+ const hasChannel = !!this._channelMap[channel.name];
78
+ if (hasChannel && hasAuthRequirements) {
79
+ delete this._channelMap[channel.name];
80
+ this._channelEventDemux.write(`${channel.name}/subscribeFail`, {
81
+ channel: channel.name,
82
+ error: err,
83
+ options
84
+ });
85
+ this.emit('subscribeFail', {
86
+ channel: channel.name,
87
+ error: err,
88
+ options
89
+ });
90
+ }
91
+ }
33
92
  trySubscribe(channel) {
34
- const meetsAuthRequirements = !channel.options.waitForAuth || !!this._transport.signedAuthToken;
93
+ const hasAuthRequirements = !channel.options.waitForAuth || !!this._transport.signedAuthToken;
35
94
  // 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) {
95
+ if (this._transport.status === 'ready'
96
+ && !this._preparingPendingSubscriptions
97
+ && !channel.subscribePromise
98
+ && hasAuthRequirements) {
40
99
  const subscriptionOptions = {};
41
100
  if (channel.options.waitForAuth) {
42
101
  subscriptionOptions.waitForAuth = true;
@@ -44,7 +103,7 @@ export class ClientChannels extends Channels {
44
103
  if (channel.options.data) {
45
104
  subscriptionOptions.data = channel.options.data;
46
105
  }
47
- [channel.subscribePromise, channel.subscribeAbort] = this._transport.invoke({ method: '#subscribe', ackTimeoutMs: false }, {
106
+ [channel.subscribePromise, channel.subscribeAbort] = this._transport.invoke({ ackTimeoutMs: false, method: '#subscribe' }, {
48
107
  channel: this.decorateChannelName(channel.name),
49
108
  ...subscriptionOptions
50
109
  });
@@ -52,14 +111,15 @@ export class ClientChannels extends Channels {
52
111
  delete channel.subscribePromise;
53
112
  delete channel.subscribeAbort;
54
113
  this.triggerChannelSubscribe(channel, subscriptionOptions);
55
- }).catch(err => {
56
- if (err.name === 'BadConnectionError') {
114
+ }).catch((err) => {
115
+ const error = toError(err);
116
+ if (error.name === 'BadConnectionError') {
57
117
  // In case of a failed connection, keep the subscription
58
118
  // as pending; it will try again on reconnect.
59
119
  return;
60
120
  }
61
- if (err.name !== 'AbortError') {
62
- this.triggerChannelSubscribeFail(err, channel, subscriptionOptions);
121
+ if (error.name !== 'AbortError') {
122
+ this.triggerChannelSubscribeFail(error, channel, subscriptionOptions);
63
123
  }
64
124
  delete channel.subscribePromise;
65
125
  delete channel.subscribeAbort;
@@ -70,36 +130,6 @@ export class ClientChannels extends Channels {
70
130
  });
71
131
  }
72
132
  }
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
133
  tryUnsubscribe(channel) {
104
134
  this.triggerChannelUnsubscribe(channel);
105
135
  if (this._transport.status === 'ready') {
@@ -112,38 +142,13 @@ export class ClientChannels extends Channels {
112
142
  // the operation on the server side.
113
143
  this._transport
114
144
  .transmit('#unsubscribe', decoratedChannelName)
115
- .catch(err => { });
145
+ .catch((_) => { });
116
146
  }
117
147
  }
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
- });
148
+ unsubscribe(channelName) {
149
+ const channel = this._channelMap[channelName];
150
+ if (channel) {
151
+ this.tryUnsubscribe(channel);
133
152
  }
134
153
  }
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
154
  }
@@ -1,24 +1,26 @@
1
- import ws from "isomorphic-ws";
2
- import { MethodMap, PrivateMethodMap, PublicMethodMap, ServiceMap, SocketOptions } from "@socket-mesh/core";
3
- import { ClientAuthEngine, LocalStorageAuthEngineOptions } from "./client-auth-engine.js";
4
- import { ClientPrivateMap } from "./maps/client-map.js";
5
- import { ServerPrivateMap } from "./maps/server-map.js";
1
+ import { BaseSocketOptions } from '@socket-mesh/core';
2
+ import ws from 'isomorphic-ws';
3
+ import { ClientAuthEngine, LocalStorageAuthEngineOptions } from './client-auth-engine.js';
6
4
  export interface AutoReconnectOptions {
7
5
  initialDelay: number;
8
- randomness: number;
9
- multiplier: number;
10
6
  maxDelayMs: number;
7
+ multiplier: number;
8
+ randomness: number;
9
+ }
10
+ export interface ClientSocketOptions<TState extends object = {}> extends BaseSocketOptions<TState> {
11
+ address: string | URL;
12
+ authEngine?: ClientAuthEngine | LocalStorageAuthEngineOptions | null;
13
+ autoConnect?: boolean;
14
+ autoReconnect?: boolean | Partial<AutoReconnectOptions>;
15
+ autoSubscribeOnConnect?: boolean;
16
+ channelPrefix?: string;
17
+ connectTimeoutMs?: number;
18
+ wsOptions?: ws.ClientOptions;
11
19
  }
12
20
  export interface ConnectOptions {
13
21
  address?: string | URL;
14
22
  connectTimeoutMs?: number;
15
23
  wsOptions?: ws.ClientOptions;
16
24
  }
17
- export interface ClientSocketOptions<TOutgoing extends PublicMethodMap = {}, TService extends ServiceMap = {}, TIncoming extends MethodMap = {}, TPrivateOutgoing extends PrivateMethodMap = {}, TState extends object = {}> extends SocketOptions<TIncoming & ClientPrivateMap, TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService, TState>, 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<TIncoming extends MethodMap, TService extends ServiceMap, TOutgoing extends PublicMethodMap, TPrivateOutgoing extends PrivateMethodMap, TState extends object>(options: ClientSocketOptions<TOutgoing, TService, TIncoming, TPrivateOutgoing, TState> | string | URL): ClientSocketOptions<TOutgoing, TService, TIncoming, TPrivateOutgoing, TState>;
25
+ export declare function parseAutoReconnectOptions(value?: boolean | Partial<AutoReconnectOptions>): AutoReconnectOptions | false;
26
+ export declare function parseClientOptions<TState extends object>(options: ClientSocketOptions<TState> | string | URL): ClientSocketOptions<TState>;
@@ -1,6 +1,18 @@
1
+ export function parseAutoReconnectOptions(value) {
2
+ if (value) {
3
+ return {
4
+ initialDelay: 10000,
5
+ maxDelayMs: 60000,
6
+ multiplier: 1.5,
7
+ randomness: 10000,
8
+ ...(value === true ? {} : value)
9
+ };
10
+ }
11
+ return false;
12
+ }
1
13
  export function parseClientOptions(options) {
2
14
  if (typeof options === 'string' || 'pathname' in options) {
3
15
  options = { address: options };
4
16
  }
5
- return Object.assign({}, options);
17
+ return { ...options };
6
18
  }
@@ -1,27 +1,72 @@
1
- import { AutoReconnectOptions, ClientSocketOptions, ConnectOptions } from "./client-socket-options.js";
2
- import { SignedAuthToken } from "@socket-mesh/auth";
3
- import { MethodMap, PrivateMethodMap, PublicMethodMap, ServiceMap, Socket } from "@socket-mesh/core";
4
- import { ClientChannels } from "./client-channels.js";
5
- import { ClientPrivateMap } from "./maps/client-map.js";
6
- import { ChannelMap } from "@socket-mesh/channels";
7
- import { ServerPrivateMap } from "./maps/server-map.js";
8
- export declare class ClientSocket<TOutgoing extends PublicMethodMap = {}, TChannel extends ChannelMap = ChannelMap, TService extends ServiceMap = {}, TState extends object = {}, TIncoming extends MethodMap = {}, TPrivateOutgoing extends PrivateMethodMap = {}> extends Socket<TIncoming & ClientPrivateMap, TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService, TState> {
1
+ import { SignedAuthToken } from '@socket-mesh/auth';
2
+ import { ChannelMap } from '@socket-mesh/channels';
3
+ import { AuthenticateEvent, AuthStateChangeEvent, BadAuthTokenEvent, BaseSocket, CloseEvent, ConnectEvent, ConnectingEvent, DeauthenticateEvent, DisconnectEvent, ErrorEvent, FunctionReturnType, InvokeMethodOptions, InvokeServiceOptions, MessageEvent, PingEvent, PongEvent, PrivateMethodMap, PublicMethodMap, RemoveAuthTokenEvent, RequestEvent, ResponseEvent, ServiceMap, ServiceMethodName, ServiceName, Socket, TypedRequestEvent, TypedResponseEvent, TypedSocketEvent } from '@socket-mesh/core';
4
+ import { DemuxedConsumableStream, StreamEvent } from '@socket-mesh/stream-demux';
5
+ import { ClientChannels } from './client-channels.js';
6
+ import { AutoReconnectOptions, ClientSocketOptions, ConnectOptions } from './client-socket-options.js';
7
+ import { ClientPrivateMap } from './maps/client-map.js';
8
+ import { ServerPrivateMap } from './maps/server-map.js';
9
+ export declare class ClientSocket<TIncoming extends PublicMethodMap = {}, TOutgoing extends PublicMethodMap = {}, TChannel extends ChannelMap = ChannelMap, TService extends ServiceMap = {}, TState extends object = {}, TPrivateOutgoing extends PrivateMethodMap = {}> extends BaseSocket<TState> implements Socket<TIncoming & ClientPrivateMap, TOutgoing, TState, TService, {}, TPrivateOutgoing & ServerPrivateMap> {
9
10
  private readonly _clientTransport;
10
- readonly channels: ClientChannels<TChannel, TIncoming, TService, TOutgoing, TPrivateOutgoing, TState>;
11
+ readonly channels: ClientChannels<TChannel, TState>;
11
12
  constructor(address: string | URL);
12
- constructor(options: ClientSocketOptions<TOutgoing, TService, TIncoming, TPrivateOutgoing, TState>);
13
+ constructor(options: ClientSocketOptions<TState>);
13
14
  authenticate(signedAuthToken: SignedAuthToken): Promise<void>;
14
15
  get autoReconnect(): AutoReconnectOptions | false;
15
- set autoReconnect(value: Partial<AutoReconnectOptions> | boolean);
16
+ set autoReconnect(value: boolean | Partial<AutoReconnectOptions>);
16
17
  connect(options?: ConnectOptions): void;
17
18
  get connectTimeoutMs(): number;
18
19
  set connectTimeoutMs(timeoutMs: number);
19
20
  deauthenticate(): Promise<boolean>;
21
+ emit(event: 'request', data: TypedRequestEvent<TIncoming & ClientPrivateMap, TService>): void;
22
+ emit(event: 'response', data: TypedResponseEvent<TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService>): void;
23
+ emit(event: 'authStateChange', data: AuthStateChangeEvent): void;
24
+ emit(event: 'authenticate', data: AuthenticateEvent): void;
25
+ emit(event: 'badAuthToken', data: BadAuthTokenEvent): void;
26
+ emit(event: 'close', data: CloseEvent): void;
27
+ emit(event: 'connect', data: ConnectEvent): void;
28
+ emit(event: 'connectAbort', data: DisconnectEvent): void;
29
+ emit(event: 'connecting', data: ConnectingEvent): void;
30
+ emit(event: 'deauthenticate', data: DeauthenticateEvent): void;
31
+ emit(event: 'disconnect', data: DisconnectEvent): void;
32
+ emit(event: 'end'): void;
33
+ emit(event: 'error', data: ErrorEvent): void;
34
+ emit(event: 'message', data: MessageEvent): void;
35
+ emit(event: 'ping', data: PingEvent): void;
36
+ emit(event: 'pong', data: PongEvent): void;
37
+ emit(event: 'removeAuthToken', data: RemoveAuthTokenEvent): void;
38
+ emit(event: 'request', data: RequestEvent): void;
39
+ emit(event: 'response', data: ResponseEvent): void;
40
+ invoke<TMethod extends keyof TOutgoing & string>(method: TMethod, arg?: Parameters<TOutgoing[TMethod]>[0]): Promise<FunctionReturnType<TOutgoing[TMethod]>>;
41
+ invoke<TServiceName extends ServiceName<TService>, TMethod extends ServiceMethodName<TService, TServiceName>>(options: [TServiceName, TMethod, (false | number)?], arg?: Parameters<TService[TServiceName][TMethod]>[0]): Promise<FunctionReturnType<TService[TServiceName][TMethod]>>;
42
+ invoke<TServiceName extends ServiceName<TService>, TMethod extends ServiceMethodName<TService, TServiceName>>(options: InvokeServiceOptions<TService, TServiceName, TMethod>, arg?: Parameters<TService[TServiceName][TMethod]>[0]): Promise<FunctionReturnType<TService[TServiceName][TMethod]>>;
43
+ invoke<TMethod extends keyof TOutgoing & string>(options: InvokeMethodOptions<TOutgoing, TMethod>, arg?: Parameters<TOutgoing[TMethod]>[0]): Promise<FunctionReturnType<TOutgoing[TMethod]>>;
20
44
  get isPingTimeoutDisabled(): boolean;
21
45
  set isPingTimeoutDisabled(isDisabled: boolean);
46
+ listen(): DemuxedConsumableStream<StreamEvent<TypedSocketEvent<TIncoming & ClientPrivateMap, TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService>>>;
47
+ listen(event: 'authStateChange'): DemuxedConsumableStream<AuthStateChangeEvent>;
48
+ listen(event: 'authenticate'): DemuxedConsumableStream<AuthenticateEvent>;
49
+ listen(event: 'badAuthToken'): DemuxedConsumableStream<BadAuthTokenEvent>;
50
+ listen(event: 'close'): DemuxedConsumableStream<CloseEvent>;
51
+ listen(event: 'connect'): DemuxedConsumableStream<ConnectEvent>;
52
+ listen(event: 'connectAbort'): DemuxedConsumableStream<DisconnectEvent>;
53
+ listen(event: 'connecting'): DemuxedConsumableStream<ConnectingEvent>;
54
+ listen(event: 'deauthenticate'): DemuxedConsumableStream<DeauthenticateEvent>;
55
+ listen(event: 'disconnect'): DemuxedConsumableStream<DisconnectEvent>;
56
+ listen(event: 'end'): DemuxedConsumableStream<void>;
57
+ listen(event: 'error'): DemuxedConsumableStream<ErrorEvent>;
58
+ listen(event: 'message'): DemuxedConsumableStream<MessageEvent>;
59
+ listen(event: 'ping'): DemuxedConsumableStream<PingEvent>;
60
+ listen(event: 'pong'): DemuxedConsumableStream<PongEvent>;
61
+ listen(event: 'removeAuthToken'): DemuxedConsumableStream<RemoveAuthTokenEvent>;
62
+ listen(event: 'request'): DemuxedConsumableStream<TypedRequestEvent<TIncoming & ClientPrivateMap, TService>>;
63
+ listen(event: 'response'): DemuxedConsumableStream<TypedResponseEvent<TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService>>;
64
+ listen<U extends TypedSocketEvent<TIncoming & ClientPrivateMap, TOutgoing, TPrivateOutgoing & ServerPrivateMap, TService>, V = U>(event: string): DemuxedConsumableStream<V>;
22
65
  get pingTimeoutMs(): number;
23
66
  set pingTimeoutMs(timeoutMs: number);
24
67
  reconnect(code?: number, reason?: string): void;
68
+ transmit<TMethod extends keyof TOutgoing & string>(method: TMethod, arg?: Parameters<TOutgoing[TMethod]>[0]): Promise<void>;
69
+ transmit<TServiceName extends ServiceName<TService>, TMethod extends ServiceMethodName<TService, TServiceName>>(options: [TServiceName, TMethod], arg?: Parameters<TService[TServiceName][TMethod]>[0]): Promise<void>;
25
70
  get type(): 'client';
26
71
  get uri(): URL;
27
72
  }
@@ -1,21 +1,23 @@
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 {
1
+ import { BaseSocket, toError, wait } from '@socket-mesh/core';
2
+ import { hydrateError } from '@socket-mesh/errors';
3
+ import { ClientChannels } from './client-channels.js';
4
+ import { parseClientOptions } from './client-socket-options.js';
5
+ import { ClientTransport } from './client-transport.js';
6
+ import { kickOutHandler } from './handlers/kickout.js';
7
+ import { publishHandler } from './handlers/publish.js';
8
+ import { removeAuthTokenHandler } from './handlers/remove-auth-token.js';
9
+ import { setAuthTokenHandler } from './handlers/set-auth-token.js';
10
+ export class ClientSocket extends BaseSocket {
11
+ _clientTransport;
12
+ channels;
11
13
  constructor(options) {
12
14
  options = parseClientOptions(options);
13
15
  options.handlers =
14
16
  Object.assign({
15
- "#kickOut": kickOutHandler,
16
- "#publish": publishHandler,
17
- "#setAuthToken": setAuthTokenHandler,
18
- "#removeAuthToken": removeAuthTokenHandler
17
+ '#kickOut': kickOutHandler,
18
+ '#publish': publishHandler,
19
+ '#removeAuthToken': removeAuthTokenHandler,
20
+ '#setAuthToken': setAuthTokenHandler
19
21
  }, options.handlers);
20
22
  const clientTransport = new ClientTransport(options);
21
23
  super(clientTransport, options);
@@ -33,14 +35,15 @@ export class ClientSocket extends Socket {
33
35
  await wait(0);
34
36
  }
35
37
  catch (err) {
36
- if (err.name !== 'BadConnectionError' && err.name !== 'TimeoutError') {
38
+ const error = toError(err);
39
+ if (error.name !== 'BadConnectionError' && error.name !== 'TimeoutError') {
37
40
  // In case of a bad/closed connection or a timeout, we maintain the last
38
41
  // known auth state since those errors don't mean that the token is invalid.
39
42
  await this._clientTransport.changeToUnauthenticatedState();
40
43
  // In order for the events to trigger we need to wait for the next tick.
41
44
  await wait(0);
42
45
  }
43
- throw hydrateError(err);
46
+ throw hydrateError(error);
44
47
  }
45
48
  }
46
49
  get autoReconnect() {
@@ -65,22 +68,33 @@ export class ClientSocket extends Socket {
65
68
  oldAuthToken = await this._clientTransport.authEngine.removeToken();
66
69
  }
67
70
  catch (err) {
68
- this._clientTransport.onError(err);
71
+ this._clientTransport.onError(toError(err));
69
72
  return;
70
73
  }
71
- this.emit('removeAuthToken', { oldAuthToken });
74
+ if (oldAuthToken) {
75
+ this.emit('removeAuthToken', { oldAuthToken });
76
+ }
72
77
  })();
73
78
  if (this.status !== 'closed') {
74
79
  await this._clientTransport.transmit('#removeAuthToken');
75
80
  }
76
81
  return await super.deauthenticate();
77
82
  }
83
+ emit(event, data) {
84
+ super.emit(event, data);
85
+ }
86
+ invoke(methodOptions, arg) {
87
+ return super.invoke(methodOptions, arg);
88
+ }
78
89
  get isPingTimeoutDisabled() {
79
90
  return this._clientTransport.isPingTimeoutDisabled;
80
91
  }
81
92
  set isPingTimeoutDisabled(isDisabled) {
82
93
  this._clientTransport.isPingTimeoutDisabled = isDisabled;
83
94
  }
95
+ listen(event) {
96
+ return super.listen(event ?? '');
97
+ }
84
98
  get pingTimeoutMs() {
85
99
  return this._clientTransport.pingTimeoutMs;
86
100
  }
@@ -91,6 +105,9 @@ export class ClientSocket extends Socket {
91
105
  this.disconnect(code, reason);
92
106
  this.connect();
93
107
  }
108
+ transmit(serviceAndMethod, arg) {
109
+ return super.transmit(serviceAndMethod, arg);
110
+ }
94
111
  get type() {
95
112
  return this._clientTransport.type;
96
113
  }