jsonrpc-client-websocket 1.4.2 → 1.5.1
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/lib/deferred-promise.js +1 -5
- package/lib/index.js +2 -14
- package/lib/jsonrpc-websocket.d.ts +2 -2
- package/lib/jsonrpc-websocket.js +29 -33
- package/lib/jsonrpc.model.d.ts +2 -1
- package/lib/jsonrpc.model.js +6 -11
- package/package.json +19 -16
package/lib/deferred-promise.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DeferredPromise = void 0;
|
|
4
|
-
class DeferredPromise {
|
|
1
|
+
export class DeferredPromise {
|
|
5
2
|
constructor() {
|
|
6
3
|
this.promise = new Promise((resolve, reject) => {
|
|
7
4
|
this.deferResolve = resolve;
|
|
@@ -18,4 +15,3 @@ class DeferredPromise {
|
|
|
18
15
|
this.deferReject(error);
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
|
-
exports.DeferredPromise = DeferredPromise;
|
package/lib/index.js
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./jsonrpc-websocket"), exports);
|
|
14
|
-
__exportStar(require("./jsonrpc.model"), exports);
|
|
1
|
+
export * from './jsonrpc-websocket';
|
|
2
|
+
export * from './jsonrpc.model';
|
|
@@ -22,8 +22,8 @@ export declare class JsonRpcWebsocket {
|
|
|
22
22
|
close(): Promise<CloseEvent>;
|
|
23
23
|
on(methodName: string, callback: (...args: any[]) => any): void;
|
|
24
24
|
off(methodName: string): void;
|
|
25
|
-
call(method: string, params?:
|
|
26
|
-
notify(method: string, params?:
|
|
25
|
+
call(method: string, params?: unknown): Promise<JsonRpcResponse>;
|
|
26
|
+
notify(method: string, params?: unknown): void;
|
|
27
27
|
private createWebsocket;
|
|
28
28
|
private respondOk;
|
|
29
29
|
private respondError;
|
package/lib/jsonrpc-websocket.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const deferred_promise_1 = require("./deferred-promise");
|
|
6
|
-
const jsonrpc_model_1 = require("./jsonrpc.model");
|
|
7
|
-
var WebsocketReadyStates;
|
|
1
|
+
import * as getParameterNames from 'get-parameter-names';
|
|
2
|
+
import { DeferredPromise } from './deferred-promise';
|
|
3
|
+
import { JsonRpcErrorCodes } from './jsonrpc.model';
|
|
4
|
+
export var WebsocketReadyStates;
|
|
8
5
|
(function (WebsocketReadyStates) {
|
|
9
6
|
WebsocketReadyStates[WebsocketReadyStates["CONNECTING"] = 0] = "CONNECTING";
|
|
10
7
|
WebsocketReadyStates[WebsocketReadyStates["OPEN"] = 1] = "OPEN";
|
|
11
8
|
WebsocketReadyStates[WebsocketReadyStates["CLOSING"] = 2] = "CLOSING";
|
|
12
9
|
WebsocketReadyStates[WebsocketReadyStates["CLOSED"] = 3] = "CLOSED";
|
|
13
|
-
})(WebsocketReadyStates
|
|
14
|
-
class JsonRpcWebsocket {
|
|
10
|
+
})(WebsocketReadyStates || (WebsocketReadyStates = {}));
|
|
11
|
+
export class JsonRpcWebsocket {
|
|
15
12
|
constructor(url, requestTimeoutMs, onError) {
|
|
16
13
|
this.url = url;
|
|
17
14
|
this.requestTimeoutMs = requestTimeoutMs;
|
|
@@ -45,10 +42,9 @@ class JsonRpcWebsocket {
|
|
|
45
42
|
off(methodName) {
|
|
46
43
|
delete this.rpcMethods[methodName.toLowerCase()]; // case-insensitive!
|
|
47
44
|
}
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
49
45
|
call(method, params) {
|
|
50
46
|
if (!this.websocket || this.state !== WebsocketReadyStates.OPEN) {
|
|
51
|
-
return Promise.reject({ code:
|
|
47
|
+
return Promise.reject({ code: JsonRpcErrorCodes.INTERNAL_ERROR, message: 'The websocket is not opened' });
|
|
52
48
|
}
|
|
53
49
|
const request = {
|
|
54
50
|
id: this.getRequestId(),
|
|
@@ -61,11 +57,10 @@ class JsonRpcWebsocket {
|
|
|
61
57
|
}
|
|
62
58
|
catch (e) {
|
|
63
59
|
// istanbul ignore next
|
|
64
|
-
return Promise.reject({ code:
|
|
60
|
+
return Promise.reject({ code: JsonRpcErrorCodes.INTERNAL_ERROR, message: `Internal error. ${e}` });
|
|
65
61
|
}
|
|
66
62
|
return this.createPendingRequest(request);
|
|
67
63
|
}
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
|
69
64
|
notify(method, params) {
|
|
70
65
|
if (!this.websocket || this.state !== WebsocketReadyStates.OPEN) {
|
|
71
66
|
throw new Error('The websocket is not opened');
|
|
@@ -87,8 +82,8 @@ class JsonRpcWebsocket {
|
|
|
87
82
|
// See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent for close event codes
|
|
88
83
|
// this.websocket = new WebSocket(this.url, ['jsonrpc-2.0']);
|
|
89
84
|
this.websocket = new WebSocket(this.url);
|
|
90
|
-
const openDeferredPromise = new
|
|
91
|
-
this.closeDeferredPromise = new
|
|
85
|
+
const openDeferredPromise = new DeferredPromise();
|
|
86
|
+
this.closeDeferredPromise = new DeferredPromise();
|
|
92
87
|
this.websocket.onopen = (event) => {
|
|
93
88
|
openDeferredPromise.resolve(event);
|
|
94
89
|
};
|
|
@@ -111,14 +106,12 @@ class JsonRpcWebsocket {
|
|
|
111
106
|
this.websocket.onmessage = (message) => this.handleMessage(message.data);
|
|
112
107
|
return openDeferredPromise.asPromise();
|
|
113
108
|
}
|
|
114
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
115
109
|
respondOk(id, result) {
|
|
116
110
|
this.respond(id, result);
|
|
117
111
|
}
|
|
118
112
|
respondError(id, error) {
|
|
119
113
|
this.respond(id, undefined, error);
|
|
120
114
|
}
|
|
121
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
115
|
respond(id, result, error) {
|
|
123
116
|
// istanbul ignore if
|
|
124
117
|
if (!this.websocket || this.state !== WebsocketReadyStates.OPEN) {
|
|
@@ -132,7 +125,7 @@ class JsonRpcWebsocket {
|
|
|
132
125
|
jsonrpc: this.jsonRpcVersion,
|
|
133
126
|
error: error,
|
|
134
127
|
id: id,
|
|
135
|
-
result: result
|
|
128
|
+
result: result,
|
|
136
129
|
};
|
|
137
130
|
try {
|
|
138
131
|
this.websocket.send(JSON.stringify(response));
|
|
@@ -148,14 +141,14 @@ class JsonRpcWebsocket {
|
|
|
148
141
|
data = JSON.parse(msg);
|
|
149
142
|
}
|
|
150
143
|
catch (e) /* istanbul ignore next */ {
|
|
151
|
-
this.handleError(
|
|
144
|
+
this.handleError(JsonRpcErrorCodes.PARSE_ERROR, `Invalid JSON was received. ${e}`);
|
|
152
145
|
return;
|
|
153
146
|
}
|
|
154
147
|
const isResponse = !!data && this.hasProperty(data, 'id') && (this.hasProperty(data, 'result') || this.hasProperty(data, 'error'));
|
|
155
148
|
const isRequest = !!data && this.hasProperty(data, 'method');
|
|
156
149
|
const requestId = isRequest && data.id ? data.id : undefined;
|
|
157
150
|
if (!data.jsonrpc || data.jsonrpc !== this.jsonRpcVersion) {
|
|
158
|
-
this.handleError(
|
|
151
|
+
this.handleError(JsonRpcErrorCodes.INVALID_REQUEST, `Invalid JSON RPC protocol version. Expecting ${this.jsonRpcVersion}, but got ${data.jsonrpc}`, requestId);
|
|
159
152
|
return;
|
|
160
153
|
}
|
|
161
154
|
if (isResponse) {
|
|
@@ -165,13 +158,13 @@ class JsonRpcWebsocket {
|
|
|
165
158
|
this.handleRequest(data);
|
|
166
159
|
}
|
|
167
160
|
else {
|
|
168
|
-
this.handleError(
|
|
161
|
+
this.handleError(JsonRpcErrorCodes.INVALID_REQUEST, `Received unknown data: ${JSON.stringify(data)}`, requestId);
|
|
169
162
|
}
|
|
170
163
|
}
|
|
171
164
|
handleRequest(request) {
|
|
172
165
|
const method = this.rpcMethods[request.method.toLowerCase()]; // case-insensitive!
|
|
173
166
|
if (!method) {
|
|
174
|
-
this.handleError(
|
|
167
|
+
this.handleError(JsonRpcErrorCodes.METHOD_NOT_FOUND, `Method '${request.method}' was not found`, request.id);
|
|
175
168
|
return;
|
|
176
169
|
}
|
|
177
170
|
let requestParams = [];
|
|
@@ -179,12 +172,17 @@ class JsonRpcWebsocket {
|
|
|
179
172
|
requestParams = this.getRequestParams(method, request);
|
|
180
173
|
}
|
|
181
174
|
catch (error) {
|
|
182
|
-
this.handleError(
|
|
175
|
+
this.handleError(JsonRpcErrorCodes.INVALID_PARAMS, error.message, request.id);
|
|
183
176
|
return;
|
|
184
177
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
try {
|
|
179
|
+
const result = method(...requestParams);
|
|
180
|
+
if (request.id) {
|
|
181
|
+
this.respondOk(request.id, result);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
this.handleError(JsonRpcErrorCodes.REQUEST_FAILED, `Method '${request.method}' has thrown: '${error.message}'`, request.id);
|
|
188
186
|
}
|
|
189
187
|
}
|
|
190
188
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -202,7 +200,7 @@ class JsonRpcWebsocket {
|
|
|
202
200
|
if (method.length !== Object.keys(request.params).length) {
|
|
203
201
|
throw new Error(`Invalid parameters. Method '${request.method}' expects parameters [${parameterNames}], but got [${Object.keys(request.params)}]`);
|
|
204
202
|
}
|
|
205
|
-
parameterNames.forEach(paramName => {
|
|
203
|
+
parameterNames.forEach((paramName) => {
|
|
206
204
|
const paramValue = request.params[paramName];
|
|
207
205
|
if (paramValue === undefined) {
|
|
208
206
|
throw new Error(`Invalid parameters. Method '${request.method}' expects parameters [${parameterNames}], but got [${Object.keys(request.params)}]`);
|
|
@@ -220,7 +218,7 @@ class JsonRpcWebsocket {
|
|
|
220
218
|
const activeRequest = this.pendingRequests[response.id];
|
|
221
219
|
if (activeRequest === undefined) {
|
|
222
220
|
this.callOnError({
|
|
223
|
-
code:
|
|
221
|
+
code: JsonRpcErrorCodes.INTERNAL_ERROR,
|
|
224
222
|
message: `Received a response with id ${response.id}, which does not match any requests made by this client`,
|
|
225
223
|
});
|
|
226
224
|
return;
|
|
@@ -229,7 +227,7 @@ class JsonRpcWebsocket {
|
|
|
229
227
|
if (this.hasProperty(response, 'result') && this.hasProperty(response, 'error')) {
|
|
230
228
|
const errorResponse = {
|
|
231
229
|
error: {
|
|
232
|
-
code:
|
|
230
|
+
code: JsonRpcErrorCodes.INVALID_RESPONSE,
|
|
233
231
|
message: `Invalid response. Either result or error must be set, but not both. ${JSON.stringify(response)}`,
|
|
234
232
|
},
|
|
235
233
|
id: activeRequest.request.id,
|
|
@@ -253,7 +251,7 @@ class JsonRpcWebsocket {
|
|
|
253
251
|
}
|
|
254
252
|
}
|
|
255
253
|
createPendingRequest(request) {
|
|
256
|
-
const response = new
|
|
254
|
+
const response = new DeferredPromise();
|
|
257
255
|
this.pendingRequests[request.id] = {
|
|
258
256
|
request,
|
|
259
257
|
response,
|
|
@@ -270,7 +268,7 @@ class JsonRpcWebsocket {
|
|
|
270
268
|
}
|
|
271
269
|
const response = {
|
|
272
270
|
error: {
|
|
273
|
-
code:
|
|
271
|
+
code: JsonRpcErrorCodes.REQUEST_TIMEOUT,
|
|
274
272
|
message: `Request ${activeRequest.request.id} exceeded the maximum time of ${this.requestTimeoutMs}ms and was aborted`,
|
|
275
273
|
},
|
|
276
274
|
id: activeRequest.request.id,
|
|
@@ -288,9 +286,7 @@ class JsonRpcWebsocket {
|
|
|
288
286
|
getRequestId() {
|
|
289
287
|
return ++this.requestId;
|
|
290
288
|
}
|
|
291
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
289
|
hasProperty(object, propertyName) {
|
|
293
290
|
return !!Object.prototype.hasOwnProperty.call(object, propertyName);
|
|
294
291
|
}
|
|
295
292
|
}
|
|
296
|
-
exports.JsonRpcWebsocket = JsonRpcWebsocket;
|
package/lib/jsonrpc.model.d.ts
CHANGED
|
@@ -5,7 +5,8 @@ export declare enum JsonRpcErrorCodes {
|
|
|
5
5
|
INVALID_PARAMS = -32602,
|
|
6
6
|
INTERNAL_ERROR = -32603,
|
|
7
7
|
INVALID_RESPONSE = -32001,
|
|
8
|
-
REQUEST_TIMEOUT = -32002
|
|
8
|
+
REQUEST_TIMEOUT = -32002,
|
|
9
|
+
REQUEST_FAILED = -32003
|
|
9
10
|
}
|
|
10
11
|
export declare class JsonRpcError {
|
|
11
12
|
code: number;
|
package/lib/jsonrpc.model.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/* tslint:disable:max-classes-per-file */
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.JsonRpcRequest = exports.JsonRpcResponse = exports.JsonRpcError = exports.JsonRpcErrorCodes = void 0;
|
|
5
2
|
// See https://www.jsonrpc.org/specification for the protocol details
|
|
6
|
-
var JsonRpcErrorCodes;
|
|
3
|
+
export var JsonRpcErrorCodes;
|
|
7
4
|
(function (JsonRpcErrorCodes) {
|
|
8
5
|
JsonRpcErrorCodes[JsonRpcErrorCodes["PARSE_ERROR"] = -32700] = "PARSE_ERROR";
|
|
9
6
|
JsonRpcErrorCodes[JsonRpcErrorCodes["INVALID_REQUEST"] = -32600] = "INVALID_REQUEST";
|
|
@@ -13,13 +10,11 @@ var JsonRpcErrorCodes;
|
|
|
13
10
|
// App specific
|
|
14
11
|
JsonRpcErrorCodes[JsonRpcErrorCodes["INVALID_RESPONSE"] = -32001] = "INVALID_RESPONSE";
|
|
15
12
|
JsonRpcErrorCodes[JsonRpcErrorCodes["REQUEST_TIMEOUT"] = -32002] = "REQUEST_TIMEOUT";
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
JsonRpcErrorCodes[JsonRpcErrorCodes["REQUEST_FAILED"] = -32003] = "REQUEST_FAILED";
|
|
14
|
+
})(JsonRpcErrorCodes || (JsonRpcErrorCodes = {}));
|
|
15
|
+
export class JsonRpcError {
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
class JsonRpcResponse {
|
|
17
|
+
export class JsonRpcResponse {
|
|
21
18
|
}
|
|
22
|
-
|
|
23
|
-
class JsonRpcRequest {
|
|
19
|
+
export class JsonRpcRequest {
|
|
24
20
|
}
|
|
25
|
-
exports.JsonRpcRequest = JsonRpcRequest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsonrpc-client-websocket",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "A simple JSON RPC 2.0 websocket client",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -8,16 +8,17 @@
|
|
|
8
8
|
"lib/**/*"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "jest
|
|
11
|
+
"test": "jest",
|
|
12
12
|
"coverage": "jest --config jestconfig.json --coverage",
|
|
13
13
|
"build": "tsc",
|
|
14
|
-
"format": "prettier --write \"src/**/*.ts\"
|
|
14
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
15
15
|
"lint": "tsc --noEmit && eslint . --ext .js,.jsx,.ts,.tsx --fix",
|
|
16
16
|
"prepublishOnly": "npm test && npm run lint",
|
|
17
17
|
"prepare": "npm run build",
|
|
18
18
|
"preversion": "npm run lint",
|
|
19
19
|
"version": "npm run format && git add -A src",
|
|
20
|
-
"postversion": "git push && git push --tags"
|
|
20
|
+
"postversion": "git push && git push --tags",
|
|
21
|
+
"updateAll": "npm-check-updates --upgrade"
|
|
21
22
|
},
|
|
22
23
|
"repository": {
|
|
23
24
|
"type": "git",
|
|
@@ -37,18 +38,20 @@
|
|
|
37
38
|
"author": "Fabricio Bastian",
|
|
38
39
|
"license": "MIT",
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@types/jest": "^
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^4.
|
|
42
|
-
"@typescript-eslint/parser": "^4.
|
|
43
|
-
"eslint": "^
|
|
44
|
-
"eslint-config-prettier": "^
|
|
45
|
-
"eslint-plugin-jest": "^
|
|
46
|
-
"jest": "^
|
|
47
|
-
"jest-websocket-mock": "^2.2.
|
|
48
|
-
"mock-socket": "^9.0.
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
41
|
+
"@types/jest": "^27.0.3",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
43
|
+
"@typescript-eslint/parser": "^5.4.0",
|
|
44
|
+
"eslint": "^8.3.0",
|
|
45
|
+
"eslint-config-prettier": "^8.3.0",
|
|
46
|
+
"eslint-plugin-jest": "^25.3.0",
|
|
47
|
+
"jest": "^27.3.1",
|
|
48
|
+
"jest-websocket-mock": "^2.2.1",
|
|
49
|
+
"mock-socket": "^9.0.8",
|
|
50
|
+
"npm-check-updates": "^12.0.2",
|
|
51
|
+
"prettier": "^2.5.0",
|
|
52
|
+
"ts-jest": "^27.0.7",
|
|
53
|
+
"ts-node": "^10.4.0",
|
|
54
|
+
"typescript": "^4.5.2"
|
|
52
55
|
},
|
|
53
56
|
"dependencies": {
|
|
54
57
|
"get-parameter-names": "^0.3.0"
|