nydus-client 4.0.0 → 4.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/dist/index.d.ts CHANGED
@@ -1,103 +1,103 @@
1
- import { SocketOptions as EngineIoSocketOptions, Socket as EngineIoSocket } from 'engine.io-client';
2
- import { protocolVersion } from 'nydus-protocol';
3
- import { TypedEventEmitter, EventMap } from './typed-emitter';
4
- export { protocolVersion };
5
- export interface NydusClientOptions extends EngineIoSocketOptions {
6
- /**
7
- * How long before a connection attempt should be considered failed. Optional, will not timeout
8
- * if not specified.
9
- */
10
- connectTimeout?: number;
11
- /** How many times to attempt to reconnect before giving up. */
12
- reconnectionAttempts: number;
13
- /**
14
- * How long to wait before attempting to reconnect, in milliseconds. This time will be backed off
15
- * if successive attempts fail.
16
- */
17
- reconnectionDelay: number;
18
- /**
19
- * The maximum amount of time to wait before attempting to reconnect, in milliseconds, when backed
20
- * off. */
21
- reconnectionDelayMax: number;
22
- /**
23
- * How much to jitter reconnection attempts, to avoid all clients connecting at once. This value
24
- * should be between 0 and 1.
25
- */
26
- reconnectionJitter: number;
27
- }
28
- interface ExpandedSocket extends Omit<EngineIoSocket, 'readyState'> {
29
- readonly readyState: string;
30
- }
31
- export interface RouteInfo {
32
- route: string;
33
- params: Record<string, string>;
34
- splats: string[];
35
- }
36
- export declare type RouteHandler = (routeInfo: RouteInfo, data: any) => void;
37
- interface NydusEvents extends EventMap {
38
- /** Fired when the connection succeeds. */
39
- connect: () => void;
40
- /** Fired when the connection has been closed */
41
- disconnect: (reason: string, details?: Error) => void;
42
- /** Fired when a reconnect attempt is being initiated. */
43
- reconnecting: (attempts: number) => void;
44
- /** Fired when a publish occurred that wasn't handled by any registered routes. */
45
- unhandled: (published: {
46
- path: string;
47
- data: any;
48
- }) => void;
49
- /** Fired when a general error occurs. */
50
- error: (err: Error) => void;
51
- /** Fired when the connection attempt times out. */
52
- connect_timeout: () => void;
53
- /** Fired when the reconnection attempts exceeded the maximum allowed without success. */
54
- reconnect_failed: () => void;
55
- /** Fired when the connection attempt failed. */
56
- connect_failed: () => void;
57
- }
58
- export declare class InvokeError extends Error {
59
- readonly status: number;
60
- readonly body: any;
61
- constructor(message: string, status: number, body?: any);
62
- }
63
- export declare class NydusClient extends TypedEventEmitter<NydusEvents> {
64
- readonly host: string;
65
- readonly opts: Partial<NydusClientOptions>;
66
- conn: ExpandedSocket | null;
67
- private outstanding;
68
- private router;
69
- private backoff;
70
- private backoffTimer;
71
- private connectTimer;
72
- private wasOpened;
73
- private skipReconnect;
74
- constructor(host: string, opts?: Partial<NydusClientOptions>);
75
- get readyState(): string;
76
- private doConnect;
77
- connect(): void;
78
- reconnect(): void;
79
- disconnect(): void;
80
- /**
81
- * Registers a handler function to respond to PUBLISHes to paths matching a specified pattern.
82
- * Handlers are normal functions of the form:
83
- * `function({ route, params, splats }, data)`
84
- *
85
- * PUBLISHes that don't match a route will be emitted as an 'unhandled' event on this object,
86
- * which can be useful to track in development mode.
87
- */
88
- registerRoute(pathPattern: string, handler: RouteHandler): void;
89
- private onPublish;
90
- /**
91
- * Invoke a remote method on the server, specified via a path. Optionally, data can be specified
92
- * to send along with the call (will be JSON encoded). A Promise will be returned, resolved or
93
- * rejected with the result or error (respectively) from the server.
94
- */
95
- invoke(path: string, data?: any): Promise<unknown>;
96
- private onInvokeResponse;
97
- private onOpen;
98
- private onMessage;
99
- private onClose;
100
- private onError;
101
- clearConnectTimer(): void;
102
- }
103
- export default function createClient(host: string, opts?: Partial<NydusClientOptions>): NydusClient;
1
+ import { SocketOptions as EngineIoSocketOptions, Socket as EngineIoSocket } from 'engine.io-client';
2
+ import { protocolVersion } from 'nydus-protocol';
3
+ import { TypedEventEmitter, EventMap } from './typed-emitter';
4
+ export { protocolVersion };
5
+ export interface NydusClientOptions extends EngineIoSocketOptions {
6
+ /**
7
+ * How long before a connection attempt should be considered failed. Optional, will not timeout
8
+ * if not specified.
9
+ */
10
+ connectTimeout?: number;
11
+ /** How many times to attempt to reconnect before giving up. */
12
+ reconnectionAttempts: number;
13
+ /**
14
+ * How long to wait before attempting to reconnect, in milliseconds. This time will be backed off
15
+ * if successive attempts fail.
16
+ */
17
+ reconnectionDelay: number;
18
+ /**
19
+ * The maximum amount of time to wait before attempting to reconnect, in milliseconds, when backed
20
+ * off. */
21
+ reconnectionDelayMax: number;
22
+ /**
23
+ * How much to jitter reconnection attempts, to avoid all clients connecting at once. This value
24
+ * should be between 0 and 1.
25
+ */
26
+ reconnectionJitter: number;
27
+ }
28
+ interface ExpandedSocket extends Omit<EngineIoSocket, 'readyState'> {
29
+ readonly readyState: string;
30
+ }
31
+ export interface RouteInfo {
32
+ route: string;
33
+ params: Record<string, string>;
34
+ splats: string[];
35
+ }
36
+ export type RouteHandler = (routeInfo: RouteInfo, data: any) => void;
37
+ interface NydusEvents extends EventMap {
38
+ /** Fired when the connection succeeds. */
39
+ connect: () => void;
40
+ /** Fired when the connection has been closed */
41
+ disconnect: (reason: string, details?: Error) => void;
42
+ /** Fired when a reconnect attempt is being initiated. */
43
+ reconnecting: (attempts: number) => void;
44
+ /** Fired when a publish occurred that wasn't handled by any registered routes. */
45
+ unhandled: (published: {
46
+ path: string;
47
+ data: any;
48
+ }) => void;
49
+ /** Fired when a general error occurs. */
50
+ error: (err: Error) => void;
51
+ /** Fired when the connection attempt times out. */
52
+ connect_timeout: () => void;
53
+ /** Fired when the reconnection attempts exceeded the maximum allowed without success. */
54
+ reconnect_failed: () => void;
55
+ /** Fired when the connection attempt failed. */
56
+ connect_failed: () => void;
57
+ }
58
+ export declare class InvokeError extends Error {
59
+ readonly status: number;
60
+ readonly body: any;
61
+ constructor(message: string, status: number, body?: any);
62
+ }
63
+ export declare class NydusClient extends TypedEventEmitter<NydusEvents> {
64
+ readonly host: string;
65
+ readonly opts: Partial<NydusClientOptions>;
66
+ conn: ExpandedSocket | null;
67
+ private outstanding;
68
+ private router;
69
+ private backoff;
70
+ private backoffTimer;
71
+ private connectTimer;
72
+ private wasOpened;
73
+ private skipReconnect;
74
+ constructor(host: string, opts?: Partial<NydusClientOptions>);
75
+ get readyState(): string;
76
+ private doConnect;
77
+ connect(): void;
78
+ reconnect(): void;
79
+ disconnect(): void;
80
+ /**
81
+ * Registers a handler function to respond to PUBLISHes to paths matching a specified pattern.
82
+ * Handlers are normal functions of the form:
83
+ * `function({ route, params, splats }, data)`
84
+ *
85
+ * PUBLISHes that don't match a route will be emitted as an 'unhandled' event on this object,
86
+ * which can be useful to track in development mode.
87
+ */
88
+ registerRoute(pathPattern: string, handler: RouteHandler): void;
89
+ private onPublish;
90
+ /**
91
+ * Invoke a remote method on the server, specified via a path. Optionally, data can be specified
92
+ * to send along with the call (will be JSON encoded). A Promise will be returned, resolved or
93
+ * rejected with the result or error (respectively) from the server.
94
+ */
95
+ invoke(path: string, data?: any): Promise<unknown>;
96
+ private onInvokeResponse;
97
+ private onOpen;
98
+ private onMessage;
99
+ private onClose;
100
+ private onError;
101
+ clearConnectTimer(): void;
102
+ }
103
+ export default function createClient(host: string, opts?: Partial<NydusClientOptions>): NydusClient;
@@ -1,216 +1,216 @@
1
- import { Socket as EngineIoSocket } from 'engine.io-client';
2
- import cuid from 'cuid';
3
- import ruta from 'ruta3';
4
- import Backoff from 'backo2';
5
- import { encode, decode, protocolVersion, MessageType, } from 'nydus-protocol';
6
- import { TypedEventEmitter } from './typed-emitter';
7
- export { protocolVersion };
8
- function isTransportError(err) {
9
- return err.type === 'TransportError';
10
- }
11
- export class InvokeError extends Error {
12
- constructor(message, status, body) {
13
- super(message);
14
- this.status = status;
15
- this.body = body;
16
- }
17
- }
18
- export class NydusClient extends TypedEventEmitter {
19
- constructor(host, opts = {}) {
20
- super();
21
- this.conn = null;
22
- this.outstanding = new Map();
23
- this.router = ruta();
24
- this.backoffTimer = null;
25
- this.connectTimer = null;
26
- this.wasOpened = false;
27
- this.skipReconnect = false;
28
- this.host = host;
29
- this.opts = opts;
30
- this.opts.reconnectionAttempts = this.opts.reconnectionAttempts || Infinity;
31
- this.backoff = new Backoff({
32
- min: opts.reconnectionDelay || 1000,
33
- max: opts.reconnectionDelayMax || 10000,
34
- jitter: opts.reconnectionJitter || 0.5,
35
- });
36
- }
37
- // One of: opening, open, closing, closed.
38
- get readyState() {
39
- return this.conn != null ? this.conn.readyState : 'closed';
40
- }
41
- doConnect() {
42
- if (this.opts.connectTimeout) {
43
- this.connectTimer = setTimeout(() => {
44
- this.emit('connect_timeout');
45
- this.disconnect();
46
- this.skipReconnect = false;
47
- this.onClose('connect timeout');
48
- }, this.opts.connectTimeout);
49
- }
50
- this.conn = new EngineIoSocket(this.host, this.opts);
51
- this.conn
52
- .on('open', this.onOpen.bind(this))
53
- .on('message', data => this.onMessage(data))
54
- .on('close', this.onClose.bind(this))
55
- .on('error', this.onError.bind(this));
56
- }
57
- // Connect to the server. If already connected, this will be a no-op.
58
- connect() {
59
- if (this.conn)
60
- return;
61
- this.skipReconnect = false;
62
- this.wasOpened = false;
63
- this.doConnect();
64
- }
65
- reconnect() {
66
- if (this.conn || this.skipReconnect || this.backoffTimer) {
67
- return;
68
- }
69
- if (this.backoff.attempts >= this.opts.reconnectionAttempts) {
70
- this.backoff.reset();
71
- this.emit('reconnect_failed');
72
- return;
73
- }
74
- this.backoffTimer = setTimeout(() => {
75
- this.backoffTimer = null;
76
- this.emit('reconnecting', this.backoff.attempts);
77
- if (this.skipReconnect || this.conn)
78
- return;
79
- this.doConnect();
80
- }, this.backoff.duration());
81
- }
82
- // Disconnect from the server. If not already connected, this will be a no-op.
83
- disconnect() {
84
- this.skipReconnect = true;
85
- if (this.backoffTimer) {
86
- clearTimeout(this.backoffTimer);
87
- this.backoffTimer = null;
88
- }
89
- if (!this.conn)
90
- return;
91
- this.conn.close();
92
- }
93
- /**
94
- * Registers a handler function to respond to PUBLISHes to paths matching a specified pattern.
95
- * Handlers are normal functions of the form:
96
- * `function({ route, params, splats }, data)`
97
- *
98
- * PUBLISHes that don't match a route will be emitted as an 'unhandled' event on this object,
99
- * which can be useful to track in development mode.
100
- */
101
- registerRoute(pathPattern, handler) {
102
- this.router.addRoute(pathPattern, handler);
103
- }
104
- onPublish({ path, data }) {
105
- const route = this.router.match(path);
106
- if (!route) {
107
- this.emit('unhandled', { path, data });
108
- return;
109
- }
110
- route.action({ route: route.route, params: route.params, splats: route.splats }, data);
111
- }
112
- /**
113
- * Invoke a remote method on the server, specified via a path. Optionally, data can be specified
114
- * to send along with the call (will be JSON encoded). A Promise will be returned, resolved or
115
- * rejected with the result or error (respectively) from the server.
116
- */
117
- invoke(path, data) {
118
- const id = cuid();
119
- const p = new Promise((resolve, reject) => {
120
- if (!this.conn) {
121
- reject(new Error('Not connected'));
122
- return;
123
- }
124
- this.outstanding.set(id, { resolve, reject });
125
- this.conn.send(encode(MessageType.Invoke, data, id, path), undefined);
126
- }).catch(err => {
127
- // Convert error-like objects back to Errors
128
- if (err.message && err.status) {
129
- const converted = new InvokeError(err.message, err.status, err.body);
130
- throw converted;
131
- }
132
- throw err;
133
- });
134
- p.finally(() => this.outstanding.delete(id));
135
- return p;
136
- }
137
- onInvokeResponse({ type, id, data }) {
138
- const p = this.outstanding.get(id);
139
- if (!p) {
140
- this.emit('error', new Error('Unknown invoke id'));
141
- return;
142
- }
143
- p[type === MessageType.Result ? 'resolve' : 'reject'](data);
144
- }
145
- onOpen() {
146
- this.clearConnectTimer();
147
- this.wasOpened = true;
148
- this.backoff.reset();
149
- this.emit('connect');
150
- }
151
- onMessage(msg) {
152
- var _a, _b;
153
- const decoded = decode(msg);
154
- switch (decoded.type) {
155
- case MessageType.ParserError:
156
- (_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(); // will cause a call to _onClose
157
- break;
158
- case MessageType.Welcome:
159
- if (decoded.data !== protocolVersion) {
160
- this.emit('error', new Error('Server has incompatible protocol version: ' + protocolVersion));
161
- (_b = this.conn) === null || _b === void 0 ? void 0 : _b.close();
162
- }
163
- break;
164
- case MessageType.Result:
165
- case MessageType.Error:
166
- this.onInvokeResponse(decoded);
167
- break;
168
- case MessageType.Publish:
169
- this.onPublish(decoded);
170
- break;
171
- }
172
- }
173
- onClose(reason, details) {
174
- this.clearConnectTimer();
175
- this.conn = null;
176
- if (!this.wasOpened) {
177
- this.emit('connect_failed');
178
- this.reconnect();
179
- // Sockets can emit 'close' even if the connection was never actually opened. Don't emit emits
180
- // upstream in that case, since they're rather unnecessary
181
- return;
182
- }
183
- this.emit('disconnect', reason, details);
184
- this.outstanding.clear();
185
- this.wasOpened = false;
186
- this.reconnect();
187
- }
188
- onError(err) {
189
- this.clearConnectTimer();
190
- if (isTransportError(err) && err.message === 'xhr poll error') {
191
- this.onClose('error', err);
192
- return;
193
- }
194
- if (this.skipReconnect &&
195
- isTransportError(err) &&
196
- err.description &&
197
- err.description.message &&
198
- err.description.message.includes('closed before the connection was established')) {
199
- // ws sometimes throws errors if you disconnect a socket that was in the process of
200
- // reconnecting. Since the disconnect was requested (_skipReconnect is true), this seems
201
- // spurious, so we just ignore it
202
- return;
203
- }
204
- this.emit('error', err);
205
- }
206
- clearConnectTimer() {
207
- if (this.connectTimer) {
208
- clearTimeout(this.connectTimer);
209
- this.connectTimer = null;
210
- }
211
- }
212
- }
213
- export default function createClient(host, opts) {
214
- return new NydusClient(host, opts);
215
- }
1
+ import { Socket as EngineIoSocket } from 'engine.io-client';
2
+ import cuid from 'cuid';
3
+ import ruta from 'ruta3';
4
+ import Backoff from 'backo2';
5
+ import { encode, decode, protocolVersion, MessageType, } from 'nydus-protocol';
6
+ import { TypedEventEmitter } from './typed-emitter';
7
+ export { protocolVersion };
8
+ function isTransportError(err) {
9
+ return err.type === 'TransportError';
10
+ }
11
+ export class InvokeError extends Error {
12
+ constructor(message, status, body) {
13
+ super(message);
14
+ this.status = status;
15
+ this.body = body;
16
+ }
17
+ }
18
+ export class NydusClient extends TypedEventEmitter {
19
+ constructor(host, opts = {}) {
20
+ super();
21
+ this.conn = null;
22
+ this.outstanding = new Map();
23
+ this.router = ruta();
24
+ this.backoffTimer = null;
25
+ this.connectTimer = null;
26
+ this.wasOpened = false;
27
+ this.skipReconnect = false;
28
+ this.host = host;
29
+ this.opts = opts;
30
+ this.opts.reconnectionAttempts = this.opts.reconnectionAttempts || Infinity;
31
+ this.backoff = new Backoff({
32
+ min: opts.reconnectionDelay || 1000,
33
+ max: opts.reconnectionDelayMax || 10000,
34
+ jitter: opts.reconnectionJitter || 0.5,
35
+ });
36
+ }
37
+ // One of: opening, open, closing, closed.
38
+ get readyState() {
39
+ return this.conn != null ? this.conn.readyState : 'closed';
40
+ }
41
+ doConnect() {
42
+ if (this.opts.connectTimeout) {
43
+ this.connectTimer = setTimeout(() => {
44
+ this.emit('connect_timeout');
45
+ this.disconnect();
46
+ this.skipReconnect = false;
47
+ this.onClose('connect timeout');
48
+ }, this.opts.connectTimeout);
49
+ }
50
+ this.conn = new EngineIoSocket(this.host, this.opts);
51
+ this.conn
52
+ .on('open', this.onOpen.bind(this))
53
+ .on('message', data => this.onMessage(data))
54
+ .on('close', this.onClose.bind(this))
55
+ .on('error', this.onError.bind(this));
56
+ }
57
+ // Connect to the server. If already connected, this will be a no-op.
58
+ connect() {
59
+ if (this.conn)
60
+ return;
61
+ this.skipReconnect = false;
62
+ this.wasOpened = false;
63
+ this.doConnect();
64
+ }
65
+ reconnect() {
66
+ if (this.conn || this.skipReconnect || this.backoffTimer) {
67
+ return;
68
+ }
69
+ if (this.backoff.attempts >= this.opts.reconnectionAttempts) {
70
+ this.backoff.reset();
71
+ this.emit('reconnect_failed');
72
+ return;
73
+ }
74
+ this.backoffTimer = setTimeout(() => {
75
+ this.backoffTimer = null;
76
+ this.emit('reconnecting', this.backoff.attempts);
77
+ if (this.skipReconnect || this.conn)
78
+ return;
79
+ this.doConnect();
80
+ }, this.backoff.duration());
81
+ }
82
+ // Disconnect from the server. If not already connected, this will be a no-op.
83
+ disconnect() {
84
+ this.skipReconnect = true;
85
+ if (this.backoffTimer) {
86
+ clearTimeout(this.backoffTimer);
87
+ this.backoffTimer = null;
88
+ }
89
+ if (!this.conn)
90
+ return;
91
+ this.conn.close();
92
+ }
93
+ /**
94
+ * Registers a handler function to respond to PUBLISHes to paths matching a specified pattern.
95
+ * Handlers are normal functions of the form:
96
+ * `function({ route, params, splats }, data)`
97
+ *
98
+ * PUBLISHes that don't match a route will be emitted as an 'unhandled' event on this object,
99
+ * which can be useful to track in development mode.
100
+ */
101
+ registerRoute(pathPattern, handler) {
102
+ this.router.addRoute(pathPattern, handler);
103
+ }
104
+ onPublish({ path, data }) {
105
+ const route = this.router.match(path);
106
+ if (!route) {
107
+ this.emit('unhandled', { path, data });
108
+ return;
109
+ }
110
+ route.action({ route: route.route, params: route.params, splats: route.splats }, data);
111
+ }
112
+ /**
113
+ * Invoke a remote method on the server, specified via a path. Optionally, data can be specified
114
+ * to send along with the call (will be JSON encoded). A Promise will be returned, resolved or
115
+ * rejected with the result or error (respectively) from the server.
116
+ */
117
+ invoke(path, data) {
118
+ const id = cuid();
119
+ return new Promise((resolve, reject) => {
120
+ if (!this.conn) {
121
+ reject(new Error('Not connected'));
122
+ return;
123
+ }
124
+ this.outstanding.set(id, { resolve, reject });
125
+ this.conn.send(encode(MessageType.Invoke, data, id, path), undefined);
126
+ })
127
+ .catch(err => {
128
+ // Convert error-like objects back to Errors
129
+ if (err.message && err.status) {
130
+ const converted = new InvokeError(err.message, err.status, err.body);
131
+ throw converted;
132
+ }
133
+ throw err;
134
+ })
135
+ .finally(() => this.outstanding.delete(id));
136
+ }
137
+ onInvokeResponse({ type, id, data }) {
138
+ const p = this.outstanding.get(id);
139
+ if (!p) {
140
+ this.emit('error', new Error('Unknown invoke id'));
141
+ return;
142
+ }
143
+ p[type === MessageType.Result ? 'resolve' : 'reject'](data);
144
+ }
145
+ onOpen() {
146
+ this.clearConnectTimer();
147
+ this.wasOpened = true;
148
+ this.backoff.reset();
149
+ this.emit('connect');
150
+ }
151
+ onMessage(msg) {
152
+ var _a, _b;
153
+ const decoded = decode(msg);
154
+ switch (decoded.type) {
155
+ case MessageType.ParserError:
156
+ (_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(); // will cause a call to _onClose
157
+ break;
158
+ case MessageType.Welcome:
159
+ if (decoded.data !== protocolVersion) {
160
+ this.emit('error', new Error('Server has incompatible protocol version: ' + protocolVersion));
161
+ (_b = this.conn) === null || _b === void 0 ? void 0 : _b.close();
162
+ }
163
+ break;
164
+ case MessageType.Result:
165
+ case MessageType.Error:
166
+ this.onInvokeResponse(decoded);
167
+ break;
168
+ case MessageType.Publish:
169
+ this.onPublish(decoded);
170
+ break;
171
+ }
172
+ }
173
+ onClose(reason, details) {
174
+ this.clearConnectTimer();
175
+ this.conn = null;
176
+ if (!this.wasOpened) {
177
+ this.emit('connect_failed');
178
+ this.reconnect();
179
+ // Sockets can emit 'close' even if the connection was never actually opened. Don't emit emits
180
+ // upstream in that case, since they're rather unnecessary
181
+ return;
182
+ }
183
+ this.emit('disconnect', reason, details);
184
+ this.outstanding.clear();
185
+ this.wasOpened = false;
186
+ this.reconnect();
187
+ }
188
+ onError(err) {
189
+ this.clearConnectTimer();
190
+ if (isTransportError(err) && err.message === 'xhr poll error') {
191
+ this.onClose('error', err);
192
+ return;
193
+ }
194
+ if (this.skipReconnect &&
195
+ isTransportError(err) &&
196
+ err.description &&
197
+ err.description.message &&
198
+ err.description.message.includes('closed before the connection was established')) {
199
+ // ws sometimes throws errors if you disconnect a socket that was in the process of
200
+ // reconnecting. Since the disconnect was requested (_skipReconnect is true), this seems
201
+ // spurious, so we just ignore it
202
+ return;
203
+ }
204
+ this.emit('error', err);
205
+ }
206
+ clearConnectTimer() {
207
+ if (this.connectTimer) {
208
+ clearTimeout(this.connectTimer);
209
+ this.connectTimer = null;
210
+ }
211
+ }
212
+ }
213
+ export default function createClient(host, opts) {
214
+ return new NydusClient(host, opts);
215
+ }
216
216
  //# sourceMappingURL=index.js.map