This commit is contained in:
lhx-666-cool
2025-04-25 17:03:25 +08:00
parent 326a2a007c
commit f6cb277519
1677 changed files with 1232721 additions and 0 deletions

69
web/node_modules/@open-rpc/client-js/build/Client.d.ts generated vendored Normal file
View File

@@ -0,0 +1,69 @@
import RequestManager from "./RequestManager";
import { JSONRPCError } from "./Error";
import { IClient, RequestArguments, NotificationArguments } from "./ClientInterface";
import { IJSONRPCNotification } from "./Request";
/**
* OpenRPC Client JS is a browser-compatible JSON-RPC client with multiple transports and
* multiple request managers to enable features like round-robin or fallback-by-position.
*
* @example
* ```typescript
* import { RequestManager, HTTPTransport, Client } from '@open-rpc/client-js';
* const transport = new HTTPTransport('http://localhost:3333');
* const client = new Client(new RequestManager([transport]));
* const result = await client.request({method: 'addition', params: [2, 2]});
* // => { jsonrpc: '2.0', id: 1, result: 4 }
* ```
*
*/
declare class Client implements IClient {
requestManager: RequestManager;
constructor(requestManager: RequestManager);
/**
* Initiates [[RequestManager.startBatch]] in order to build a batch call.
*
* Subsequent calls to [[Client.request]] will be added to the batch. Once [[Client.stopBatch]] is called, the
* promises for the [[Client.request]] will then be resolved. If the [[RequestManager]] already has a batch in
* progress, this method is a noop.
*
* @example
* myClient.startBatch();
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
* myClient.request({method: "foo", params: ["baz"]}).then(() => console.log('foobaz'));
* myClient.stopBatch();
*/
startBatch(): void;
/**
* Initiates [[RequestManager.stopBatch]] in order to finalize and send the batch to the underlying transport.
*
* [[Client.stopBatch]] will send the [[Client.request]] calls made since the last [[Client.startBatch]] call. For
* that reason, [[Client.startBatch]] MUST be called before [[Client.stopBatch]].
*
* @example
* myClient.startBatch();
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
* myClient.request({method: "foo", params: ["baz"]}).then(() => console.log('foobaz'));
* myClient.stopBatch();
*/
stopBatch(): void;
/**
* A JSON-RPC call is represented by sending a Request object to a Server.
*
* @param requestObject.method A String containing the name of the method to be invoked. Method names that begin with the word rpc
* followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and
* MUST NOT be used for anything else.
* @param requestObject.params A Structured value that holds the parameter values to be used during the invocation of the method.
*
* @example
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
*/
request(requestObject: RequestArguments, timeout?: number): Promise<any>;
notify(requestObject: NotificationArguments): Promise<any>;
onNotification(callback: (data: IJSONRPCNotification) => void): void;
onError(callback: (data: JSONRPCError) => void): void;
/**
* Close connection
*/
close(): void;
}
export default Client;

143
web/node_modules/@open-rpc/client-js/build/Client.js generated vendored Normal file
View File

@@ -0,0 +1,143 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* OpenRPC Client JS is a browser-compatible JSON-RPC client with multiple transports and
* multiple request managers to enable features like round-robin or fallback-by-position.
*
* @example
* ```typescript
* import { RequestManager, HTTPTransport, Client } from '@open-rpc/client-js';
* const transport = new HTTPTransport('http://localhost:3333');
* const client = new Client(new RequestManager([transport]));
* const result = await client.request({method: 'addition', params: [2, 2]});
* // => { jsonrpc: '2.0', id: 1, result: 4 }
* ```
*
*/
var Client = /** @class */ (function () {
function Client(requestManager) {
this.requestManager = requestManager;
}
/**
* Initiates [[RequestManager.startBatch]] in order to build a batch call.
*
* Subsequent calls to [[Client.request]] will be added to the batch. Once [[Client.stopBatch]] is called, the
* promises for the [[Client.request]] will then be resolved. If the [[RequestManager]] already has a batch in
* progress, this method is a noop.
*
* @example
* myClient.startBatch();
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
* myClient.request({method: "foo", params: ["baz"]}).then(() => console.log('foobaz'));
* myClient.stopBatch();
*/
Client.prototype.startBatch = function () {
return this.requestManager.startBatch();
};
/**
* Initiates [[RequestManager.stopBatch]] in order to finalize and send the batch to the underlying transport.
*
* [[Client.stopBatch]] will send the [[Client.request]] calls made since the last [[Client.startBatch]] call. For
* that reason, [[Client.startBatch]] MUST be called before [[Client.stopBatch]].
*
* @example
* myClient.startBatch();
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
* myClient.request({method: "foo", params: ["baz"]}).then(() => console.log('foobaz'));
* myClient.stopBatch();
*/
Client.prototype.stopBatch = function () {
return this.requestManager.stopBatch();
};
/**
* A JSON-RPC call is represented by sending a Request object to a Server.
*
* @param requestObject.method A String containing the name of the method to be invoked. Method names that begin with the word rpc
* followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and
* MUST NOT be used for anything else.
* @param requestObject.params A Structured value that holds the parameter values to be used during the invocation of the method.
*
* @example
* myClient.request({method: "foo", params: ["bar"]}).then(() => console.log('foobar'));
*/
Client.prototype.request = function (requestObject, timeout) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.requestManager.connectPromise) return [3 /*break*/, 2];
return [4 /*yield*/, this.requestManager.connectPromise];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/, this.requestManager.request(requestObject, false, timeout)];
}
});
});
};
Client.prototype.notify = function (requestObject) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.requestManager.connectPromise) return [3 /*break*/, 2];
return [4 /*yield*/, this.requestManager.connectPromise];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/, this.requestManager.request(requestObject, true, null)];
}
});
});
};
Client.prototype.onNotification = function (callback) {
this.requestManager.requestChannel.addListener("notification", callback);
};
Client.prototype.onError = function (callback) {
this.requestManager.requestChannel.addListener("error", callback);
};
/**
* Close connection
*/
Client.prototype.close = function () {
this.requestManager.close();
};
return Client;
}());
exports.default = Client;

View File

@@ -0,0 +1,15 @@
import { IJSONRPCNotification } from "./Request";
interface Arguments {
readonly method: string;
readonly params?: readonly unknown[] | object;
}
export declare type RequestArguments = Arguments;
export declare type NotificationArguments = Arguments;
export declare type JSONRPCMessage = RequestArguments | NotificationArguments;
export interface IClient {
request(args: RequestArguments): Promise<unknown>;
notify(args: NotificationArguments): Promise<unknown>;
close(): void;
onNotification(callback: (data: IJSONRPCNotification) => void): void;
}
export {};

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

10
web/node_modules/@open-rpc/client-js/build/Error.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export declare const ERR_TIMEOUT = 7777;
export declare const ERR_MISSIING_ID = 7878;
export declare const ERR_UNKNOWN = 7979;
export declare class JSONRPCError extends Error {
message: string;
code: number;
data?: unknown;
constructor(message: string, code: number, data?: any);
}
export declare const convertJSONToRPCError: (payload: any) => JSONRPCError;

40
web/node_modules/@open-rpc/client-js/build/Error.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertJSONToRPCError = exports.JSONRPCError = exports.ERR_UNKNOWN = exports.ERR_MISSIING_ID = exports.ERR_TIMEOUT = void 0;
exports.ERR_TIMEOUT = 7777;
exports.ERR_MISSIING_ID = 7878;
exports.ERR_UNKNOWN = 7979;
var JSONRPCError = /** @class */ (function (_super) {
__extends(JSONRPCError, _super);
function JSONRPCError(message, code, data) {
var _newTarget = this.constructor;
var _this = _super.call(this, message) || this;
_this.message = message;
_this.code = code;
_this.data = data;
Object.setPrototypeOf(_this, _newTarget.prototype); // restore prototype chain: see https://github.com/open-rpc/client-js/issues/209
return _this;
}
return JSONRPCError;
}(Error));
exports.JSONRPCError = JSONRPCError;
exports.convertJSONToRPCError = function (payload) {
if (payload.error) {
var _a = payload.error, message = _a.message, code = _a.code, data = _a.data;
return new JSONRPCError(message, code, data);
}
return new JSONRPCError("Unknown error", exports.ERR_UNKNOWN, payload);
};

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Error_1 = require("./Error");
var requestData_1 = require("./__mocks__/requestData");
describe("Error test", function () {
it("should convert payload to JSONRPC error ", function () {
var err = Error_1.convertJSONToRPCError("message");
expect(err instanceof Error).toBe(true);
err = Error_1.convertJSONToRPCError(requestData_1.generateMockErrorResponse(1, "somedata"));
expect(err instanceof Error).toBe(true);
});
it("should construct JSONRPCError", function () {
var err = new Error_1.JSONRPCError("test", 9999);
var err2 = new Error_1.JSONRPCError("test", 9999, "testdata");
});
it("should be able to use instanceof", function () {
var err = new Error_1.JSONRPCError("test", 9999);
expect(err instanceof Error_1.JSONRPCError).toBe(true);
});
});

View File

@@ -0,0 +1,53 @@
export declare type JSONRPCRequestData = IJSONRPCData | IBatchRequest[];
export interface IJSONRPCData {
internalID: string | number;
request: IJSONRPCRequest | IJSONRPCNotification;
}
export interface IBatchRequest {
resolve: (data: any) => void;
reject: (data: any) => void;
request: IJSONRPCData;
}
export interface IJSONRPCRequest {
jsonrpc: "2.0";
id: string | number;
method: string;
params: any[] | object;
}
export interface IJSONRPCError {
code: number;
message: string;
data: any;
}
export interface IJSONRPCResponse {
jsonrpc: "2.0";
id?: string | number;
result?: any;
error?: IJSONRPCError;
}
export interface IJSONRPCNotificationResponse {
jsonrpc: "2.0";
id?: null | undefined;
result?: any;
error?: IJSONRPCError;
}
export interface IJSONRPCNotification {
jsonrpc: "2.0";
id?: null | undefined;
method: string;
params: any[] | object;
}
interface IRPCRequest {
method: string;
params: any[];
type: "single";
}
interface IBatchRPCRequest {
type: "batch";
batch: IJSONRPCRequest[];
}
export declare type Request = IRPCRequest | IBatchRPCRequest;
export declare const isNotification: (data: IJSONRPCData) => boolean;
export declare const getBatchRequests: (data: JSONRPCRequestData) => IJSONRPCData[];
export declare const getNotifications: (data: JSONRPCRequestData) => IJSONRPCData[];
export {};

30
web/node_modules/@open-rpc/client-js/build/Request.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getNotifications = exports.getBatchRequests = exports.isNotification = void 0;
exports.isNotification = function (data) {
return (data.request.id === undefined || data.request.id === null);
};
exports.getBatchRequests = function (data) {
if (data instanceof Array) {
return data.filter(function (datum) {
var id = datum.request.request.id;
return id !== null && id !== undefined;
}).map(function (batchRequest) {
return batchRequest.request;
});
}
return [];
};
exports.getNotifications = function (data) {
if (data instanceof Array) {
return data.filter(function (datum) {
return exports.isNotification(datum.request);
}).map(function (batchRequest) {
return batchRequest.request;
});
}
if (exports.isNotification(data)) {
return [data];
}
return [];
};

View File

@@ -0,0 +1,42 @@
/// <reference types="node" />
import { Transport } from "./transports/Transport";
import { IBatchRequest } from "./Request";
import { JSONRPCError } from "./Error";
import StrictEventEmitter from "strict-event-emitter-types";
import { EventEmitter } from "events";
import { JSONRPCMessage } from "./ClientInterface";
export declare type RequestChannel = StrictEventEmitter<EventEmitter, IRequestEvents>;
export interface IRequestEvents {
"error": (err: JSONRPCError) => void;
"notification": (data: any) => void;
}
export declare type RequestID = string | number;
export declare type INextRequestID = () => RequestID;
export declare const defaultNextRequest: () => () => number;
declare class RequestManager {
transports: Transport[];
connectPromise: Promise<any>;
batch: IBatchRequest[];
requestChannel: RequestChannel;
private requests;
private batchStarted;
private lastId;
private nextID;
constructor(transports: Transport[], nextID?: INextRequestID);
connect(): Promise<any>;
getPrimaryTransport(): Transport;
request(requestObject: JSONRPCMessage, notification?: boolean, timeout?: number | null): Promise<any>;
close(): void;
/**
* Begins a batch call by setting the [[RequestManager.batchStarted]] flag to `true`.
*
* [[RequestManager.batch]] is a singleton - only one batch can exist at a given time, per [[RequestManager]].
*
*/
startBatch(): void;
stopBatch(): void;
private makeRequest;
private handleError;
private handleNotification;
}
export default RequestManager;

View File

@@ -0,0 +1,142 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultNextRequest = void 0;
var events_1 = require("events");
exports.defaultNextRequest = function () {
var lastId = -1;
return function () { return ++lastId; };
};
/*
** Naive Request Manager, only use 1st transport.
* A more complex request manager could try each transport.
* If a transport fails, or times out, move on to the next.
*/
var RequestManager = /** @class */ (function () {
function RequestManager(transports, nextID) {
if (nextID === void 0) { nextID = exports.defaultNextRequest(); }
this.batch = [];
this.batchStarted = false;
this.lastId = -1;
this.transports = transports;
this.requests = {};
this.connectPromise = this.connect();
this.requestChannel = new events_1.EventEmitter();
this.nextID = nextID;
}
RequestManager.prototype.connect = function () {
var _this = this;
return Promise.all(this.transports.map(function (transport) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
transport.subscribe("error", this.handleError.bind(this));
transport.subscribe("notification", this.handleNotification.bind(this));
return [4 /*yield*/, transport.connect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); }));
};
RequestManager.prototype.getPrimaryTransport = function () {
return this.transports[0];
};
RequestManager.prototype.request = function (requestObject, notification, timeout) {
if (notification === void 0) { notification = false; }
return __awaiter(this, void 0, void 0, function () {
var internalID, id, payload, result;
var _this = this;
return __generator(this, function (_a) {
internalID = this.nextID().toString();
id = notification ? null : internalID;
payload = { request: this.makeRequest(requestObject.method, requestObject.params || [], id), internalID: internalID };
if (this.batchStarted) {
result = new Promise(function (resolve, reject) {
_this.batch.push({ resolve: resolve, reject: reject, request: payload });
});
return [2 /*return*/, result];
}
return [2 /*return*/, this.getPrimaryTransport().sendData(payload, timeout)];
});
});
};
RequestManager.prototype.close = function () {
this.requestChannel.removeAllListeners();
this.transports.forEach(function (transport) {
transport.unsubscribe();
transport.close();
});
};
/**
* Begins a batch call by setting the [[RequestManager.batchStarted]] flag to `true`.
*
* [[RequestManager.batch]] is a singleton - only one batch can exist at a given time, per [[RequestManager]].
*
*/
RequestManager.prototype.startBatch = function () {
this.batchStarted = true;
};
RequestManager.prototype.stopBatch = function () {
if (this.batchStarted === false) {
throw new Error("cannot end that which has never started");
}
if (this.batch.length === 0) {
this.batchStarted = false;
return;
}
this.getPrimaryTransport().sendData(this.batch);
this.batch = [];
this.batchStarted = false;
};
RequestManager.prototype.makeRequest = function (method, params, id) {
if (id) {
return { jsonrpc: "2.0", id: id, method: method, params: params };
}
return { jsonrpc: "2.0", method: method, params: params };
};
RequestManager.prototype.handleError = function (data) {
this.requestChannel.emit("error", data);
};
RequestManager.prototype.handleNotification = function (data) {
this.requestChannel.emit("notification", data);
};
return RequestManager;
}());
exports.default = RequestManager;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,233 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var RequestManager_1 = __importDefault(require("./RequestManager"));
var EventEmitterTransport_1 = __importDefault(require("./transports/EventEmitterTransport"));
var events_1 = require("events");
var eventEmitter_1 = require("./__mocks__/eventEmitter");
describe("client-js", function () {
it("can be constructed and connect", function () {
var emitter = new events_1.EventEmitter();
var transport = new EventEmitterTransport_1.default(emitter, "from1", "to1");
var c = new RequestManager_1.default([transport]);
expect(!!c).toEqual(true);
});
it("can close", function () {
var emitter = new events_1.EventEmitter();
var transport = new EventEmitterTransport_1.default(emitter, "from1", "to1");
var c = new RequestManager_1.default([transport]);
c.close();
});
it("can send a request", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-response");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-response");
c = new RequestManager_1.default([transport]);
return [4 /*yield*/, c.request({ method: "foo", params: ["bar"] })];
case 1:
result = _a.sent();
expect(result.method).toEqual("foo");
expect(result.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can error on error response", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-error");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-error");
c = new RequestManager_1.default([transport]);
return [4 /*yield*/, expect(c.request({ method: "foo", params: ["bar"] })).rejects.toThrowError("Error message")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can error on malformed response and recieve error", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c, unknownError, formatError;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-garbage");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-garbage");
c = new RequestManager_1.default([transport]);
unknownError = new Promise(function (resolve) {
c.requestChannel.on("error", function (d) {
resolve(d);
});
});
return [4 /*yield*/, expect(c.request({ method: "foo", params: ["bar"] }, false, 1000))
.rejects.toThrowError("Request timeout request took longer than 1000 ms to resolve")];
case 1:
_a.sent();
return [4 /*yield*/, unknownError];
case 2:
formatError = _a.sent();
expect(formatError.message).toContain("Bad response format");
return [2 /*return*/];
}
});
}); });
it("can error on batching a request", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c;
return __generator(this, function (_a) {
emitter = new events_1.EventEmitter();
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1");
c = new RequestManager_1.default([transport]);
expect(function () { return c.stopBatch(); }).toThrow();
return [2 /*return*/];
});
}); });
it("can return errors on batch requests", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c, requests;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-error");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-error");
c = new RequestManager_1.default([transport]);
c.startBatch();
requests = [
c.request({ method: "foo", params: ["bar"] }),
c.request({ method: "foo", params: ["bar"] }),
];
c.stopBatch();
return [4 /*yield*/, expect(Promise.all(requests)).rejects.toThrowError("Error message")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can batch a request", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c, requests, _a, a, b;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-response");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-response");
c = new RequestManager_1.default([transport]);
c.startBatch();
requests = [
c.request({ method: "foo", params: [] }),
c.request({ method: "foo", params: ["bar"] })
];
c.stopBatch();
return [4 /*yield*/, Promise.all(requests)];
case 1:
_a = _b.sent(), a = _a[0], b = _a[1];
expect(a.method).toEqual("foo");
expect(b.method).toEqual("foo");
expect(a.params).toEqual([]);
expect(b.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can batch a notifications", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c, requests, _a, a, b;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://local/rpc-response");
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1://local/rpc-response");
c = new RequestManager_1.default([transport]);
c.startBatch();
requests = [
c.request({ method: "foo", params: [] }, true),
c.request({ method: "foo", params: ["bar"] }, true),
];
c.stopBatch();
return [4 /*yield*/, Promise.all(requests)];
case 1:
_a = _b.sent(), a = _a[0], b = _a[1];
return [2 /*return*/];
}
});
}); });
describe("stopBatch", function () {
it("does nothing if the batch is empty", function () {
var emitter = new events_1.EventEmitter();
var transport = new EventEmitterTransport_1.default(emitter, "from1", "to1");
transport.sendData = jest.fn();
var c = new RequestManager_1.default([transport]);
c.startBatch();
c.stopBatch();
expect(transport.sendData).not.toHaveBeenCalled();
});
});
describe("startBatch", function () {
it("it does nothing if a batch is already started", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, transport, c;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
transport = new EventEmitterTransport_1.default(emitter, "from1", "to1");
c = new RequestManager_1.default([transport]);
return [4 /*yield*/, c.connect()];
case 1:
_a.sent();
c.startBatch();
c.request({ method: "foo", params: [] });
expect(c.batch.length).toBe(1);
c.startBatch();
c.request({ method: "foo", params: [] });
expect(c.batch.length).toBe(2);
return [2 /*return*/];
}
});
}); });
});
});

View File

@@ -0,0 +1,2 @@
import { EventEmitter } from "events";
export declare const addMockServerTransport: (emitter: EventEmitter, reqUri: string, resUri: string) => void;

View File

@@ -0,0 +1,31 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.addMockServerTransport = void 0;
var req = __importStar(require("./requestData"));
exports.addMockServerTransport = function (emitter, reqUri, resUri) {
emitter.on(reqUri, function (data) {
var res = req.generateMockResponseData(resUri, data);
if (res) {
emitter.emit(resUri, res);
}
});
};

View File

@@ -0,0 +1,3 @@
/// <reference types="jest" />
declare const Fetch: jest.Mock<Promise<any>, [string, any]>;
export default Fetch;

View File

@@ -0,0 +1,34 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var req = __importStar(require("./requestData"));
var Fetch = jest.fn(function (url, options) {
if (url.match(/crash/)) {
throw new Error("Random Segfault that crashes fetch");
}
var resultPromise = {
text: function () {
return Promise.resolve(req.generateMockResponseData(url, options.body));
},
};
return Promise.resolve(resultPromise);
});
exports.default = Fetch;

View File

@@ -0,0 +1,10 @@
declare class WebSocket {
private callbacks;
private url;
constructor(url: string, props: any);
addEventListener(eventName: string, callback: any): void;
removeEventListener(eventName: string, callback: any): void;
send(data: any): void;
close(): void;
}
export default WebSocket;

View File

@@ -0,0 +1,59 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var req = __importStar(require("./requestData"));
var WebSocket = /** @class */ (function () {
function WebSocket(url, props) {
this.callbacks = {};
this.url = url;
}
WebSocket.prototype.addEventListener = function (eventName, callback) {
this.callbacks[eventName] = callback;
if (eventName === "open") {
setTimeout(function () {
callback();
}, 10);
}
};
WebSocket.prototype.removeEventListener = function (eventName, callback) {
delete this.callbacks[eventName];
};
WebSocket.prototype.send = function (data) {
var _this = this;
if (this.url.match(/crash-null/)) {
return;
}
if (this.url.match(/crash/)) {
throw new Error("Random Segfault that crashes fetch");
}
Object.entries(this.callbacks).forEach(function (_a) {
var eventName = _a[0], cb = _a[1];
if (eventName === "message") {
cb({ data: req.generateMockResponseData(_this.url, data) });
}
});
};
WebSocket.prototype.close = function () {
this.callbacks = {};
};
return WebSocket;
}());
exports.default = WebSocket;

View File

@@ -0,0 +1,7 @@
import * as req from "../Request";
export declare const generateMockNotificationRequest: (method: string, params: any[]) => req.IJSONRPCNotification;
export declare const generateMockRequest: (id: number, method: string, params: any[]) => req.IJSONRPCRequest;
export declare const generateMockResponse: (id: number, result: any, error?: any) => req.IJSONRPCResponse;
export declare const generateMockNotificationResponse: (result: any, error?: any) => req.IJSONRPCNotificationResponse;
export declare const generateMockErrorResponse: (id: number | undefined, data: any) => req.IJSONRPCResponse;
export declare const generateMockResponseData: (uri: string, data: any) => any;

View File

@@ -0,0 +1,86 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateMockResponseData = exports.generateMockErrorResponse = exports.generateMockNotificationResponse = exports.generateMockResponse = exports.generateMockRequest = exports.generateMockNotificationRequest = void 0;
var url_1 = __importDefault(require("url"));
exports.generateMockNotificationRequest = function (method, params) {
return {
jsonrpc: "2.0",
method: method,
params: params,
};
};
exports.generateMockRequest = function (id, method, params) {
return {
id: id,
jsonrpc: "2.0",
method: method,
params: params,
};
};
exports.generateMockResponse = function (id, result, error) {
return {
id: id,
jsonrpc: "2.0",
result: result,
error: error,
};
};
exports.generateMockNotificationResponse = function (result, error) {
return {
jsonrpc: "2.0",
result: result,
error: error,
};
};
exports.generateMockErrorResponse = function (id, data) {
return {
id: id,
jsonrpc: "2.0",
error: {
code: -32000,
message: "Error message",
data: data,
},
};
};
exports.generateMockResponseData = function (uri, data) {
var parsedUrl = url_1.default.parse(uri);
var path = parsedUrl.path || "";
var rpcNotification = path.search("rpc-notification");
var rpcResponse = path.search("rpc-response");
var rpcRequest = path.search("rpc-request");
var rpcError = path.search("rpc-error");
var rpcGarbage = path.search("rpc-garbage");
if (rpcResponse > 0 || rpcRequest > 0) {
return generateRequestResponse(false, data);
}
if (rpcError > 0) {
return generateRequestResponse(true, data);
}
if (rpcNotification > 0) {
return;
}
if (rpcGarbage > 0) {
return "Garbage Response";
}
return data;
};
var generateSingleRequestResponse = function (error, data) {
if (error) {
return exports.generateMockErrorResponse(data.id, data);
}
return exports.generateMockResponse(data.id, data);
};
var generateRequestResponse = function (error, data) {
var parsedReq = data;
if (typeof data === "string") {
parsedReq = JSON.parse(data);
}
if (parsedReq instanceof Array) {
return JSON.stringify(parsedReq.map(function (parsed) { return generateSingleRequestResponse(error, parsed); }));
}
return JSON.stringify(generateSingleRequestResponse(error, parsedReq));
};

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _1 = require(".");
var t = new _1.HTTPTransport("http://localhost:3333");
var c = new _1.Client(new _1.RequestManager([t]));
c.request({ method: "addition", params: [2, 2] }).then(function (result) {
console.log('addition result: ', result); // tslint:disable-line
});

10
web/node_modules/@open-rpc/client-js/build/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import RequestManager from "./RequestManager";
import EventEmitterTransport from "./transports/EventEmitterTransport";
import HTTPTransport from "./transports/HTTPTransport";
import WebSocketTransport from "./transports/WebSocketTransport";
import PostMessageWindowTransport from "./transports/PostMessageWindowTransport";
import PostMessageIframeTransport from "./transports/PostMessageIframeTransport";
import { JSONRPCError } from "./Error";
import Client from "./Client";
export default Client;
export { Client, RequestManager, HTTPTransport, EventEmitterTransport, WebSocketTransport, JSONRPCError, PostMessageWindowTransport, PostMessageIframeTransport, };

23
web/node_modules/@open-rpc/client-js/build/index.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostMessageIframeTransport = exports.PostMessageWindowTransport = exports.JSONRPCError = exports.WebSocketTransport = exports.EventEmitterTransport = exports.HTTPTransport = exports.RequestManager = exports.Client = void 0;
var RequestManager_1 = __importDefault(require("./RequestManager"));
exports.RequestManager = RequestManager_1.default;
var EventEmitterTransport_1 = __importDefault(require("./transports/EventEmitterTransport"));
exports.EventEmitterTransport = EventEmitterTransport_1.default;
var HTTPTransport_1 = __importDefault(require("./transports/HTTPTransport"));
exports.HTTPTransport = HTTPTransport_1.default;
var WebSocketTransport_1 = __importDefault(require("./transports/WebSocketTransport"));
exports.WebSocketTransport = WebSocketTransport_1.default;
var PostMessageWindowTransport_1 = __importDefault(require("./transports/PostMessageWindowTransport"));
exports.PostMessageWindowTransport = PostMessageWindowTransport_1.default;
var PostMessageIframeTransport_1 = __importDefault(require("./transports/PostMessageIframeTransport"));
exports.PostMessageIframeTransport = PostMessageIframeTransport_1.default;
var Error_1 = require("./Error");
Object.defineProperty(exports, "JSONRPCError", { enumerable: true, get: function () { return Error_1.JSONRPCError; } });
var Client_1 = __importDefault(require("./Client"));
exports.Client = Client_1.default;
exports.default = Client_1.default;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,67 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var _1 = require(".");
var RequestManager_1 = __importDefault(require("./RequestManager"));
var EventEmitterTransport_1 = __importDefault(require("./transports/EventEmitterTransport"));
var events_1 = require("events");
var eventEmitter_1 = require("./__mocks__/eventEmitter");
var requestData_1 = require("./__mocks__/requestData");
describe("client-js", function () {
it("can be constructed", function () {
var emitter = new events_1.EventEmitter();
var c = new _1.Client(new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]));
expect(!!c).toEqual(true);
});
it("has a request method that returns a promise", function () {
var emitter = new events_1.EventEmitter();
var c = new _1.Client(new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]));
expect(typeof c.request).toEqual("function");
expect(typeof c.request({ method: "my_method" }).then).toEqual("function");
});
it("has a notify method that returns a promise", function () {
var emitter = new events_1.EventEmitter();
var c = new _1.Client(new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]));
expect(typeof c.request).toEqual("function");
expect(typeof c.notify({ method: "my_method" }).then).toEqual("function");
});
it("can recieve notifications", function (done) {
var emitter = new events_1.EventEmitter();
var c = new _1.Client(new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]));
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://asdf/rpc-notification");
c.onNotification(function () { return done(); });
emitter.emit("to1", JSON.stringify(requestData_1.generateMockNotificationRequest("foo", ["bar"])));
});
it("can register error and subscription handlers", function () {
var emitter = new events_1.EventEmitter();
var c = new _1.Client(new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]));
// tslint:disable-next-line:no-empty
c.onError(function (err) { });
// tslint:disable-next-line:no-empty
c.onNotification(function (data) { });
});
describe("startBatch", function () {
it("calls startBatch", function () {
var emitter = new events_1.EventEmitter();
var rm = new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]);
var c = new _1.Client(rm);
c.startBatch();
// expect(mockedRequestManager.mock.instances[0].startBatch).toHaveBeenCalled();
});
});
describe("can call stopBatch", function () {
var emitter = new events_1.EventEmitter();
var rm = new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]);
var c = new _1.Client(rm);
c.startBatch();
c.stopBatch();
});
describe("can close", function () {
var emitter = new events_1.EventEmitter();
var rm = new RequestManager_1.default([new EventEmitterTransport_1.default(emitter, "from1", "to1")]);
var c = new _1.Client(rm);
c.close();
});
});

View File

@@ -0,0 +1,14 @@
/// <reference types="node" />
import { EventEmitter } from "events";
import { Transport } from "./Transport";
import { JSONRPCRequestData } from "../Request";
declare class EventEmitterTransport extends Transport {
connection: EventEmitter;
private reqUri;
private resUri;
constructor(destEmitter: EventEmitter, reqUri: string, resUri: string);
connect(): Promise<any>;
sendData(data: JSONRPCRequestData, timeout?: number | null): Promise<any>;
close(): void;
}
export default EventEmitterTransport;

View File

@@ -0,0 +1,56 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Transport_1 = require("./Transport");
var Request_1 = require("../Request");
var Error_1 = require("../Error");
var EventEmitterTransport = /** @class */ (function (_super) {
__extends(EventEmitterTransport, _super);
function EventEmitterTransport(destEmitter, reqUri, resUri) {
var _this = _super.call(this) || this;
_this.connection = destEmitter;
_this.reqUri = reqUri;
_this.resUri = resUri;
return _this;
}
EventEmitterTransport.prototype.connect = function () {
var _this = this;
this.connection.on(this.resUri, function (data) {
_this.transportRequestManager.resolveResponse(data);
});
return Promise.resolve();
};
EventEmitterTransport.prototype.sendData = function (data, timeout) {
if (timeout === void 0) { timeout = null; }
var prom = this.transportRequestManager.addRequest(data, timeout);
var notifications = Request_1.getNotifications(data);
var parsedData = this.parseData(data);
try {
this.connection.emit(this.reqUri, parsedData);
this.transportRequestManager.settlePendingRequest(notifications);
return prom;
}
catch (e) {
var responseErr = new Error_1.JSONRPCError(e.message, Error_1.ERR_UNKNOWN, e);
this.transportRequestManager.settlePendingRequest(notifications, responseErr);
return Promise.reject(responseErr);
}
};
EventEmitterTransport.prototype.close = function () {
this.connection.removeAllListeners();
};
return EventEmitterTransport;
}(Transport_1.Transport));
exports.default = EventEmitterTransport;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,158 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var EventEmitterTransport_1 = __importDefault(require("./EventEmitterTransport"));
var events_1 = require("events");
var requestData_1 = require("../__mocks__/requestData");
var eventEmitter_1 = require("../__mocks__/eventEmitter");
describe("EventEmitterTransport", function () {
it("can connect", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, eventEmitterTransport;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitterTransport = new EventEmitterTransport_1.default(emitter, "foo://in", "foo://out");
return [4 /*yield*/, eventEmitterTransport.connect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can close", function () {
var emitter = new events_1.EventEmitter();
var reqUri = "from";
var resUri = "to";
var eventEmitterTransport = new EventEmitterTransport_1.default(emitter, reqUri, resUri);
eventEmitterTransport.close();
});
it("can send and receive data", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, eventEmitterTransport, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1://asdf/rpc-request", "to1://asdf/rpc-response");
eventEmitterTransport = new EventEmitterTransport_1.default(emitter, "from1://asdf/rpc-request", "to1://asdf/rpc-response");
return [4 /*yield*/, eventEmitterTransport.connect()];
case 1:
_a.sent();
return [4 /*yield*/, eventEmitterTransport.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
})];
case 2:
result = _a.sent();
expect(result.method).toEqual("foo");
expect(result.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can send notifications", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, eventEmitterTransport, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://asdf/rpc-notification");
eventEmitterTransport = new EventEmitterTransport_1.default(emitter, "from1", "to1://asdf/rpc-notification");
return [4 /*yield*/, eventEmitterTransport.connect()];
case 1:
_a.sent();
return [4 /*yield*/, eventEmitterTransport.sendData({
request: requestData_1.generateMockNotificationRequest("foo", ["bar"]),
internalID: 1,
})];
case 2:
result = _a.sent();
expect(result).toEqual(undefined);
return [2 /*return*/];
}
});
}); });
it("should throw error on bad response", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, eventEmitterTransport;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://asdf/rpc-error");
eventEmitterTransport = new EventEmitterTransport_1.default(emitter, "from1", "to1://asdf/rpc-error");
return [4 /*yield*/, eventEmitterTransport.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(eventEmitterTransport.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
}))
.rejects.toThrowError("Error message")];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should throw error on bad protocol", function () { return __awaiter(void 0, void 0, void 0, function () {
var emitter, eventEmitterTransport;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emitter = new events_1.EventEmitter();
eventEmitter_1.addMockServerTransport(emitter, "from1", "to1://asdf/rpc-error");
eventEmitterTransport = new EventEmitterTransport_1.default(emitter, "from1", "to1://asdf/rpc-error");
return [4 /*yield*/, eventEmitterTransport.connect()];
case 1:
_a.sent();
eventEmitterTransport.connection.emit = function () { throw new Error("failed protocol"); };
return [4 /*yield*/, expect(eventEmitterTransport.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
}))
.rejects.toThrowError("failed protocol")];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); });
});

View File

@@ -0,0 +1,23 @@
import fetch from "isomorphic-fetch";
import { Transport } from "./Transport";
import { JSONRPCRequestData } from "../Request";
declare type CredentialsOption = "omit" | "same-origin" | "include";
interface HTTPTransportOptions {
credentials?: CredentialsOption;
headers?: Record<string, string>;
fetcher?: typeof fetch;
}
declare class HTTPTransport extends Transport {
uri: string;
private readonly credentials?;
private readonly headers;
private readonly injectedFetcher?;
constructor(uri: string, options?: HTTPTransportOptions);
connect(): Promise<any>;
sendData(data: JSONRPCRequestData, timeout?: number | null): Promise<any>;
close(): void;
private onlyNotifications;
private static setupHeaders;
}
export default HTTPTransport;
export { HTTPTransport, HTTPTransportOptions, CredentialsOption };

View File

@@ -0,0 +1,142 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTTPTransport = void 0;
var isomorphic_fetch_1 = __importDefault(require("isomorphic-fetch"));
var Transport_1 = require("./Transport");
var Request_1 = require("../Request");
var Error_1 = require("../Error");
var HTTPTransport = /** @class */ (function (_super) {
__extends(HTTPTransport, _super);
function HTTPTransport(uri, options) {
var _this = _super.call(this) || this;
_this.onlyNotifications = function (data) {
if (data instanceof Array) {
return data.every(function (datum) {
return datum.request.request.id === null ||
datum.request.request.id === undefined;
});
}
return data.request.id === null || data.request.id === undefined;
};
_this.uri = uri;
_this.credentials = options && options.credentials;
_this.headers = HTTPTransport.setupHeaders(options && options.headers);
_this.injectedFetcher = options === null || options === void 0 ? void 0 : options.fetcher;
return _this;
}
HTTPTransport.prototype.connect = function () {
return Promise.resolve();
};
HTTPTransport.prototype.sendData = function (data, timeout) {
if (timeout === void 0) { timeout = null; }
return __awaiter(this, void 0, void 0, function () {
var prom, notifications, batch, fetcher, result, body, responseErr, e_1, responseErr;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
prom = this.transportRequestManager.addRequest(data, timeout);
notifications = Request_1.getNotifications(data);
batch = Request_1.getBatchRequests(data);
fetcher = this.injectedFetcher || isomorphic_fetch_1.default;
_a.label = 1;
case 1:
_a.trys.push([1, 4, , 5]);
return [4 /*yield*/, fetcher(this.uri, {
method: "POST",
headers: this.headers,
body: JSON.stringify(this.parseData(data)),
credentials: this.credentials,
})];
case 2:
result = _a.sent();
// requirements are that notifications are successfully sent
this.transportRequestManager.settlePendingRequest(notifications);
if (this.onlyNotifications(data)) {
return [2 /*return*/, Promise.resolve()];
}
return [4 /*yield*/, result.text()];
case 3:
body = _a.sent();
responseErr = this.transportRequestManager.resolveResponse(body);
if (responseErr) {
// requirements are that batch requuests are successfully resolved
// this ensures that individual requests within the batch request are settled
this.transportRequestManager.settlePendingRequest(batch, responseErr);
return [2 /*return*/, Promise.reject(responseErr)];
}
return [3 /*break*/, 5];
case 4:
e_1 = _a.sent();
responseErr = new Error_1.JSONRPCError(e_1.message, Error_1.ERR_UNKNOWN, e_1);
this.transportRequestManager.settlePendingRequest(notifications, responseErr);
this.transportRequestManager.settlePendingRequest(Request_1.getBatchRequests(data), responseErr);
return [2 /*return*/, Promise.reject(responseErr)];
case 5: return [2 /*return*/, prom];
}
});
});
};
// tslint:disable-next-line:no-empty
HTTPTransport.prototype.close = function () { };
HTTPTransport.setupHeaders = function (headerOptions) {
var headers = new Headers(headerOptions);
// Overwrite header options to ensure correct content type.
headers.set("Content-Type", "application/json");
return headers;
};
return HTTPTransport;
}(Transport_1.Transport));
exports.HTTPTransport = HTTPTransport;
exports.default = HTTPTransport;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,265 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var HTTPTransport_1 = require("./HTTPTransport");
var reqMocks = __importStar(require("../__mocks__/requestData"));
var isomorphic_fetch_1 = __importDefault(require("isomorphic-fetch"));
var fetchMock = isomorphic_fetch_1.default;
describe("HTTPTransport", function () {
it("can connect", function () {
var httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545");
return httpTransport.connect();
});
it("can close", function () {
var httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545");
httpTransport.close();
});
it("can send and retrieve request data", function () { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-request");
data = reqMocks.generateMockRequest(1, "foo", ["bar"]);
return [4 /*yield*/, httpTransport.sendData({
request: data,
internalID: 1,
})];
case 1:
result = _a.sent();
expect(result.method).toEqual("foo");
expect(result.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can send notification data", function () { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-notification");
data = reqMocks.generateMockNotificationRequest("foo", ["bar"]);
return [4 /*yield*/, httpTransport.sendData({
request: data,
internalID: 1,
})];
case 1:
result = _a.sent();
expect(result).toEqual(undefined);
return [2 /*return*/];
}
});
}); });
it("should throw error on error response", function () { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-error");
data = reqMocks.generateMockRequest(9, "foo", ["bar"]);
return [4 /*yield*/, expect(httpTransport.sendData({ request: data, internalID: 9 })).rejects.toThrowError("Error message")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should throw error on bad data response", function () { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-garbage");
data = {
request: reqMocks.generateMockRequest(9, "foo", ["bar"]),
internalID: 9,
};
return [4 /*yield*/, expect(httpTransport.sendData(data)).rejects.toThrowError("Bad response format")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should throw error on bad data response from a batch", function (done) { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-garbage");
data = {
resolve: function (d) { return ({}); },
reject: function (e) {
expect(e.message).toContain("Bad response format");
done();
},
request: {
request: reqMocks.generateMockRequest(9, "foo", ["bar"]),
internalID: 9,
},
};
return [4 /*yield*/, expect(httpTransport.sendData([data])).rejects.toThrow("Bad response format")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should throw error if unknown server crash", function () { return __awaiter(void 0, void 0, void 0, function () {
var httpTransport, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/crash");
data = {
request: reqMocks.generateMockRequest(9, "foo", ["bar"]),
internalID: 9,
};
return [4 /*yield*/, expect(httpTransport.sendData(data)).rejects.toThrowError("Random Segfault that crashes fetch")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
function callFetch(options) {
return __awaiter(this, void 0, void 0, function () {
var httpTransport, data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545", options);
data = reqMocks.generateMockRequest(1, "foo", ["bar"]);
return [4 /*yield*/, httpTransport.sendData({ request: data, internalID: 1 })];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
}
it("sets content type to application/json", function () { return __awaiter(void 0, void 0, void 0, function () {
var headers;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, callFetch({ headers: { "Content-Type": "image/png" } })];
case 1:
_a.sent();
headers = fetchMock.mock.calls[0][1].headers;
expect(headers.get("Content-Type")).toEqual("application/json");
return [2 /*return*/];
}
});
}); });
it("sets header passed from options", function () { return __awaiter(void 0, void 0, void 0, function () {
var headerName, headerValue, headers;
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
headerName = "Authorization";
headerValue = "Basic credentials";
return [4 /*yield*/, callFetch({ headers: (_a = {}, _a[headerName] = headerValue, _a) })];
case 1:
_b.sent();
headers = fetchMock.mock.calls[0][1].headers;
expect(headers.get(headerName)).toEqual(headerValue);
return [2 /*return*/];
}
});
}); });
it("sets credentials argument passed from options", function () { return __awaiter(void 0, void 0, void 0, function () {
var credentials;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
credentials = "include";
return [4 /*yield*/, callFetch({ credentials: credentials })];
case 1:
_a.sent();
expect(fetchMock.mock.calls[0][1].credentials).toEqual(credentials);
return [2 /*return*/];
}
});
}); });
it("accepts an injected fetcher", function () { return __awaiter(void 0, void 0, void 0, function () {
var injectedFetchMock, httpTransport, data, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
injectedFetchMock = isomorphic_fetch_1.default;
httpTransport = new HTTPTransport_1.HTTPTransport("http://localhost:8545/rpc-notification", {
fetcher: injectedFetchMock,
});
data = reqMocks.generateMockNotificationRequest("foo", ["bar"]);
return [4 /*yield*/, httpTransport.sendData({
request: data,
internalID: 1,
})];
case 1:
result = _a.sent();
expect(injectedFetchMock.mock.calls.length).toEqual(1);
expect(result).toEqual(undefined);
return [2 /*return*/];
}
});
}); });
});

View File

@@ -0,0 +1,14 @@
import { Transport } from "./Transport";
import { JSONRPCRequestData } from "../Request";
declare class PostMessageIframeTransport extends Transport {
uri: string;
frame: undefined | null | Window;
postMessageID: string;
constructor(uri: string);
createWindow(uri: string): Promise<Window | null>;
private messageHandler;
connect(): Promise<any>;
sendData(data: JSONRPCRequestData, timeout?: number | null): Promise<any>;
close(): void;
}
export default PostMessageIframeTransport;

View File

@@ -0,0 +1,126 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var Transport_1 = require("./Transport");
var Request_1 = require("../Request");
var PostMessageIframeTransport = /** @class */ (function (_super) {
__extends(PostMessageIframeTransport, _super);
function PostMessageIframeTransport(uri) {
var _this = _super.call(this) || this;
_this.messageHandler = function (ev) {
_this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
};
_this.uri = uri;
_this.postMessageID = "post-message-transport-" + Math.random();
return _this;
}
PostMessageIframeTransport.prototype.createWindow = function (uri) {
var _this = this;
return new Promise(function (resolve, reject) {
var frame;
var iframe = document.createElement("iframe");
iframe.setAttribute("id", _this.postMessageID);
iframe.setAttribute("width", "0px");
iframe.setAttribute("height", "0px");
iframe.setAttribute("style", "visiblity:hidden;border:none;outline:none;");
iframe.addEventListener("load", function () {
resolve(frame);
});
iframe.setAttribute("src", uri);
window.document.body.appendChild(iframe);
frame = iframe.contentWindow;
});
};
PostMessageIframeTransport.prototype.connect = function () {
var _this = this;
var urlRegex = /^(http|https):\/\/.*$/;
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!urlRegex.test(this.uri)) {
reject(new Error("Bad URI"));
}
_a = this;
return [4 /*yield*/, this.createWindow(this.uri)];
case 1:
_a.frame = _b.sent();
window.addEventListener("message", this.messageHandler);
resolve();
return [2 /*return*/];
}
});
}); });
};
PostMessageIframeTransport.prototype.sendData = function (data, timeout) {
if (timeout === void 0) { timeout = 5000; }
return __awaiter(this, void 0, void 0, function () {
var prom, notifications;
return __generator(this, function (_a) {
prom = this.transportRequestManager.addRequest(data, null);
notifications = Request_1.getNotifications(data);
if (this.frame) {
this.frame.postMessage(data.request, "*");
this.transportRequestManager.settlePendingRequest(notifications);
}
return [2 /*return*/, prom];
});
});
};
PostMessageIframeTransport.prototype.close = function () {
var el = document.getElementById(this.postMessageID);
el === null || el === void 0 ? void 0 : el.remove();
window.removeEventListener("message", this.messageHandler);
};
return PostMessageIframeTransport;
}(Transport_1.Transport));
exports.default = PostMessageIframeTransport;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,168 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var PostMessageIframeTransport_1 = __importDefault(require("./PostMessageIframeTransport"));
var requestData_1 = require("../__mocks__/requestData");
var serve_handler_1 = __importDefault(require("serve-handler"));
var http_1 = __importDefault(require("http"));
var server;
var port;
beforeAll(function (done) {
server = http_1.default.createServer(function (request, response) {
return serve_handler_1.default(request, response, {
public: "src/testiframe",
});
});
server.listen(0, function () {
if (server) {
port = server.address().port; //tslint:disable-line
}
done();
});
});
afterAll(function () {
if (server) {
server.close();
}
});
describe("PostMessageIframeTransport", function () {
describe("iframe", function () {
it("can connect", function () {
var pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
return pmt.connect();
});
it("can error connect with bad uri", function () {
var pmt = new PostMessageIframeTransport_1.default("foo://localhost:5000/iframe.html");
expect(pmt.connect()).rejects.toThrowError("Bad URI");
});
it("can close", function () {
var pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
pmt.close();
});
it("can send and receive data", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, pmt.sendData({
request: requestData_1.generateMockRequest(0, "foo", ["bar"]),
internalID: 0
})];
case 2:
result = _a.sent();
expect(result).toEqual("bar");
return [2 /*return*/];
}
});
}); });
it("can send and receive data against potential timeout", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, pmt.sendData({
request: requestData_1.generateMockRequest(0, "foo", ["bar"]),
internalID: 0
}, 10000)];
case 2:
result = _a.sent();
expect(result).toEqual("bar");
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can send and receive errors", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(pmt.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
})).rejects.toThrowError("Error message")];
case 2:
_a.sent();
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can handle underlying transport crash", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageIframeTransport_1.default("http://localhost:" + port + "/iframe.html");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(pmt.sendData({
request: requestData_1.generateMockRequest(2, "foo", ["bar"]),
internalID: 2,
})).rejects.toThrowError("Random Segfault that crashes fetch")];
case 2:
_a.sent();
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
});
});

View File

@@ -0,0 +1,14 @@
import { Transport } from "./Transport";
import { JSONRPCRequestData } from "../Request";
declare class PostMessageTransport extends Transport {
uri: string;
frame: undefined | null | Window;
postMessageID: string;
constructor(uri: string);
createWindow(uri: string): Promise<Window | null>;
private messageHandler;
connect(): Promise<any>;
sendData(data: JSONRPCRequestData, timeout?: number | undefined): Promise<any>;
close(): void;
}
export default PostMessageTransport;

View File

@@ -0,0 +1,126 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var Transport_1 = require("./Transport");
var Request_1 = require("../Request");
var openPopup = function (url) {
var width = 400;
var height = window.screen.height;
var left = 0;
var top = 0;
return window.open(url, "inspector:popup", "left=" + left + ",top=" + top + ",width=" + width + ",height=" + height + ",resizable,scrollbars=yes,status=1");
};
var PostMessageTransport = /** @class */ (function (_super) {
__extends(PostMessageTransport, _super);
function PostMessageTransport(uri) {
var _this = _super.call(this) || this;
_this.messageHandler = function (ev) {
_this.transportRequestManager.resolveResponse(JSON.stringify(ev.data));
};
_this.uri = uri;
_this.postMessageID = "post-message-transport-" + Math.random();
return _this;
}
PostMessageTransport.prototype.createWindow = function (uri) {
return new Promise(function (resolve, reject) {
var frame;
frame = openPopup(uri);
setTimeout(function () {
resolve(frame);
}, 3000);
});
};
PostMessageTransport.prototype.connect = function () {
var _this = this;
var urlRegex = /^(http|https):\/\/.*$/;
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!urlRegex.test(this.uri)) {
reject(new Error("Bad URI"));
}
_a = this;
return [4 /*yield*/, this.createWindow(this.uri)];
case 1:
_a.frame = _b.sent();
window.addEventListener("message", this.messageHandler);
resolve();
return [2 /*return*/];
}
});
}); });
};
PostMessageTransport.prototype.sendData = function (data, timeout) {
if (timeout === void 0) { timeout = 5000; }
return __awaiter(this, void 0, void 0, function () {
var prom, notifications;
return __generator(this, function (_a) {
prom = this.transportRequestManager.addRequest(data, null);
notifications = Request_1.getNotifications(data);
if (this.frame) {
this.frame.postMessage(data.request, this.uri);
this.transportRequestManager.settlePendingRequest(notifications);
}
return [2 /*return*/, prom];
});
});
};
PostMessageTransport.prototype.close = function () {
if (this.frame) {
window.removeEventListener("message", this.messageHandler);
this.frame.close();
}
};
return PostMessageTransport;
}(Transport_1.Transport));
exports.default = PostMessageTransport;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,210 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var PostMessageWindowTransport_1 = __importDefault(require("./PostMessageWindowTransport"));
var requestData_1 = require("../__mocks__/requestData");
window.open = function () {
return {
close: function () {
//
},
postMessage: function (message, targetOrigin) {
var data = {
jsonrpc: "2.0",
result: "bar",
id: 0,
};
if (message.id === 1) {
data = {
jsonrpc: "2.0",
error: {
code: 32009,
message: "Error message",
},
id: 1,
};
}
if (message.id === 2) {
data = {
jsonrpc: "2.0",
error: {
code: 32009,
message: "Random Segfault that crashes fetch",
},
id: 2,
};
}
var event = new window.MessageEvent("message", {
data: data,
});
event.initEvent("message", true, false);
setTimeout(function () {
window.dispatchEvent(event);
}, 0);
},
};
};
describe("PostMessageWindowTransport", function () {
describe("window", function () {
it("can connect", function () {
var pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
return pmt.connect();
});
it("can error connect with bad uri", function () {
var pmt = new PostMessageWindowTransport_1.default("foo://open-rpc.org");
expect(pmt.connect()).rejects.toThrowError("Bad URI");
});
it("can close", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
pmt.close();
return [2 /*return*/];
}
});
}); });
it("can send and receive data", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, pmt.sendData({
request: requestData_1.generateMockRequest(0, "foo", ["bar"]),
internalID: 0
})];
case 2:
result = _a.sent();
expect(result).toEqual("bar");
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can send and receive data against potential timeout", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, pmt.sendData({
request: requestData_1.generateMockRequest(0, "foo", ["bar"]),
internalID: 0
}, 10000)];
case 2:
result = _a.sent();
expect(result).toEqual("bar");
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can send and receive errors", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org/rpc-error");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(pmt.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
})).rejects.toThrowError("Error message")];
case 2:
_a.sent();
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can handle underlying transport crash", function () { return __awaiter(void 0, void 0, void 0, function () {
var pmt;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
return [4 /*yield*/, pmt.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(pmt.sendData({
request: requestData_1.generateMockRequest(2, "foo", ["bar"]),
internalID: 2,
})).rejects.toThrowError("Random Segfault that crashes fetch")];
case 2:
_a.sent();
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
case 3:
_a.sent();
return [2 /*return*/];
}
});
}); });
});
describe("iframe", function () {
it("can connect", function () {
var pmt = new PostMessageWindowTransport_1.default("https://open-rpc.org/");
return pmt.connect();
});
it("can close", function () {
var pmt = new PostMessageWindowTransport_1.default("http://open-rpc.org");
pmt.close();
});
});
});

View File

@@ -0,0 +1,46 @@
/// <reference types="node" />
import { JSONRPCRequestData, IJSONRPCNotificationResponse, IJSONRPCResponse } from "../Request";
import StrictEventEmitter from "strict-event-emitter-types";
import { EventEmitter } from "events";
import { JSONRPCError } from "../Error";
import { TransportRequestManager } from "./TransportRequestManager";
interface ITransportEvents {
pending: (data: JSONRPCRequestData) => void;
notification: (data: IJSONRPCNotificationResponse) => void;
response: (data: IJSONRPCResponse) => void;
error: (data: JSONRPCError) => void;
}
declare type TransportEventName = keyof ITransportEvents;
export declare type TransportEventChannel = StrictEventEmitter<EventEmitter, ITransportEvents>;
export declare abstract class Transport {
protected transportRequestManager: TransportRequestManager;
constructor();
abstract connect(): Promise<any>;
abstract close(): void;
abstract sendData(data: JSONRPCRequestData, timeout?: number | null): Promise<any>;
subscribe(event: TransportEventName, handler: ITransportEvents[TransportEventName]): void;
unsubscribe(event?: TransportEventName, handler?: ITransportEvents[TransportEventName]): EventEmitter | undefined;
protected parseData(data: JSONRPCRequestData): import("../Request").IJSONRPCRequest | import("../Request").IJSONRPCNotification | (import("../Request").IJSONRPCRequest | import("../Request").IJSONRPCNotification)[];
}
export declare type promiseResolve = (r?: {} | PromiseLike<{}> | undefined) => void;
export declare type promiseReject = (r?: any) => void;
export interface IRequestPromise {
resolve: promiseResolve;
reject: promiseReject;
}
export declare type NotificationResponse = "notification";
export declare type RequestResponse = "response";
export declare type BadResponse = "error";
export declare type TransportResponse = JSONRPCError | undefined;
interface IHttpTransportResponse {
type: "http";
id?: string | number;
error?: Error;
payload: string;
}
interface IWSTransportResponse {
type: "ws";
payload: string;
}
export declare type TransportResponseData = IHttpTransportResponse | IWSTransportResponse;
export {};

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transport = void 0;
var TransportRequestManager_1 = require("./TransportRequestManager");
var Transport = /** @class */ (function () {
function Transport() {
this.transportRequestManager = new TransportRequestManager_1.TransportRequestManager();
// add a noop for the error event to not require handling the error event
// tslint:disable-next-line:no-empty
this.transportRequestManager.transportEventChannel.on("error", function () { });
}
Transport.prototype.subscribe = function (event, handler) {
this.transportRequestManager.transportEventChannel.addListener(event, handler);
};
Transport.prototype.unsubscribe = function (event, handler) {
if (!event) {
return this.transportRequestManager.transportEventChannel.removeAllListeners();
}
if (event && handler) {
this.transportRequestManager.transportEventChannel.removeListener(event, handler);
}
};
Transport.prototype.parseData = function (data) {
if (data instanceof Array) {
return data.map(function (batch) { return batch.request.request; });
}
return data.request;
};
return Transport;
}());
exports.Transport = Transport;

View File

@@ -0,0 +1,23 @@
import { JSONRPCRequestData, IJSONRPCData } from "../Request";
import { promiseResolve, promiseReject, TransportEventChannel, TransportResponse } from "./Transport";
export interface IPendingRequest {
resolve: promiseResolve;
reject: promiseReject;
}
export declare class TransportRequestManager {
transportEventChannel: TransportEventChannel;
private pendingRequest;
private pendingBatchRequest;
constructor();
addRequest(data: JSONRPCRequestData, timeout: number | null): Promise<any>;
settlePendingRequest(request: IJSONRPCData[], error?: Error): void;
isPendingRequest(id: string | number): boolean;
resolveResponse(payload: string, emitError?: boolean): TransportResponse;
private addBatchReq;
private addReq;
private checkJSONRPC;
private processResult;
private resolveBatch;
private resolveRes;
private setRequestTimeout;
}

View File

@@ -0,0 +1,139 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransportRequestManager = void 0;
var events_1 = require("events");
var Error_1 = require("../Error");
var TransportRequestManager = /** @class */ (function () {
function TransportRequestManager() {
this.pendingRequest = {};
this.pendingBatchRequest = {};
this.transportEventChannel = new events_1.EventEmitter();
}
TransportRequestManager.prototype.addRequest = function (data, timeout) {
this.transportEventChannel.emit("pending", data);
if (data instanceof Array) {
this.addBatchReq(data, timeout);
return Promise.resolve();
}
return this.addReq(data.internalID, timeout);
};
TransportRequestManager.prototype.settlePendingRequest = function (request, error) {
var _this = this;
request.forEach(function (req) {
var resolver = _this.pendingRequest[req.internalID];
delete _this.pendingBatchRequest[req.internalID];
if (resolver === undefined) {
return;
}
if (error) {
resolver.reject(error);
return;
}
resolver.resolve();
// Notifications have no response and should clear their own pending requests
if (req.request.id === null || req.request.id === undefined) {
delete _this.pendingRequest[req.internalID];
}
});
};
TransportRequestManager.prototype.isPendingRequest = function (id) {
return this.pendingRequest.hasOwnProperty(id);
};
TransportRequestManager.prototype.resolveResponse = function (payload, emitError) {
if (emitError === void 0) { emitError = true; }
var data = payload;
try {
data = JSON.parse(payload);
if (this.checkJSONRPC(data) === false) {
return; // ignore messages that are not conforming to JSON-RPC
}
if (data instanceof Array) {
return this.resolveBatch(data, emitError);
}
return this.resolveRes(data, emitError);
}
catch (e) {
var err = new Error_1.JSONRPCError("Bad response format", Error_1.ERR_UNKNOWN, payload);
if (emitError) {
this.transportEventChannel.emit("error", err);
}
return err;
}
};
TransportRequestManager.prototype.addBatchReq = function (batches, timeout) {
var _this = this;
batches.forEach(function (batch) {
var resolve = batch.resolve, reject = batch.reject;
var internalID = batch.request.internalID;
_this.pendingBatchRequest[internalID] = true;
_this.pendingRequest[internalID] = { resolve: resolve, reject: reject };
});
return Promise.resolve();
};
TransportRequestManager.prototype.addReq = function (id, timeout) {
var _this = this;
return new Promise(function (resolve, reject) {
if (timeout !== null && timeout) {
_this.setRequestTimeout(id, timeout, reject);
}
_this.pendingRequest[id] = { resolve: resolve, reject: reject };
});
};
TransportRequestManager.prototype.checkJSONRPC = function (data) {
var payload = [data];
if (data instanceof Array) {
payload = data;
}
return payload.every(function (datum) { return (datum.result !== undefined || datum.error !== undefined || datum.method !== undefined); });
};
TransportRequestManager.prototype.processResult = function (payload, prom) {
if (payload.error) {
var err = Error_1.convertJSONToRPCError(payload);
prom.reject(err);
return;
}
prom.resolve(payload.result);
};
TransportRequestManager.prototype.resolveBatch = function (payload, emitError) {
var _this = this;
var results = payload.map(function (datum) {
return _this.resolveRes(datum, emitError);
});
var errors = results.filter(function (result) { return result; });
if (errors.length > 0) {
return errors[0];
}
return undefined;
};
TransportRequestManager.prototype.resolveRes = function (data, emitError) {
var id = data.id, error = data.error;
var status = this.pendingRequest[id];
if (status) {
delete this.pendingRequest[id];
this.processResult(data, status);
this.transportEventChannel.emit("response", data);
return;
}
if (id === undefined && error === undefined) {
this.transportEventChannel.emit("notification", data);
return;
}
var err;
if (error) {
err = Error_1.convertJSONToRPCError(data);
}
if (emitError && error && err) {
this.transportEventChannel.emit("error", err);
}
return err;
};
TransportRequestManager.prototype.setRequestTimeout = function (id, timeout, reject) {
var _this = this;
setTimeout(function () {
delete _this.pendingRequest[id];
reject(new Error_1.JSONRPCError("Request timeout request took longer than " + timeout + " ms to resolve", Error_1.ERR_TIMEOUT));
}, timeout);
};
return TransportRequestManager;
}());
exports.TransportRequestManager = TransportRequestManager;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,264 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var reqData = __importStar(require("../__mocks__/requestData"));
var TransportRequestManager_1 = require("./TransportRequestManager");
describe("Transport Request Manager", function () {
var transportReqMan;
beforeEach(function () {
transportReqMan = new TransportRequestManager_1.TransportRequestManager();
});
it("should emit pending request", function (done) {
transportReqMan.transportEventChannel.on("pending", function (data) {
expect(data).toBeDefined();
done();
});
transportReqMan.addRequest({ request: reqData.generateMockRequest(1, "foo", ["bar"]), internalID: 1 }, null);
});
it("should timeout pending request after 1s", function () { return __awaiter(void 0, void 0, void 0, function () {
var prom;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
transportReqMan.transportEventChannel.on("pending", function (data) {
expect(data).toBeDefined();
});
prom = transportReqMan.addRequest({
request: reqData.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
}, 1000);
return [4 /*yield*/, expect(prom).rejects.toThrowError("timeout")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should handle adding batch request", function () { return __awaiter(void 0, void 0, void 0, function () {
var req, resolve, reject, request;
return __generator(this, function (_a) {
req = { request: reqData.generateMockRequest(1, "foo", ["bar"]), internalID: 1 };
resolve = function () { };
reject = function () { };
request = [{ resolve: resolve, reject: reject, request: req }];
transportReqMan.addRequest(request, null);
return [2 /*return*/];
});
}); });
it("should not error on missing id to resolve", function () {
var payload = JSON.stringify(reqData.generateMockResponse(9, "haha"));
var res = transportReqMan.resolveResponse(payload, false);
expect(res).toBeUndefined();
});
it("should error on missing id but error response", function () {
var errPayload = reqData.generateMockErrorResponse(9, "haha");
delete errPayload.id;
var payload = JSON.stringify(errPayload);
var err = transportReqMan.resolveResponse(payload, false);
expect(err.message).toContain("Error message");
});
it("should error on error response without id", function () {
var errPayload = reqData.generateMockErrorResponse(undefined, "haha");
delete errPayload.id;
var payload = JSON.stringify(errPayload);
var err = transportReqMan.resolveResponse(payload, false);
expect(err.message).toContain("Error message");
});
it("should ignore on missing id", function () {
var payload = JSON.stringify(reqData.generateMockResponse(9, "haha"));
var err = transportReqMan.resolveResponse(payload);
expect(err).toBeUndefined();
});
it("should add and reject pending requests", function () { return __awaiter(void 0, void 0, void 0, function () {
var request, prom;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
request = { request: reqData.generateMockRequest(1, "foo", ["bar"]), internalID: 1 };
prom = transportReqMan.addRequest(request, null);
transportReqMan.settlePendingRequest([request], new Error("rejecting"));
return [4 /*yield*/, expect(prom).rejects.toThrowError("rejecting")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("should not fail on invalid pending requests", function () {
var request = { request: reqData.generateMockRequest(1, "foo", ["bar"]), internalID: 1 };
transportReqMan.settlePendingRequest([request], new Error("rejecting"));
});
it("should not error on bad format for resolving a response", function (done) {
transportReqMan.resolveResponse("{}");
done();
});
it("should emit response on response && resolve response", function (done) {
var res = reqData.generateMockResponse(1, false);
// Add request to queue
var prom = transportReqMan.addRequest({
request: reqData.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
}, null);
// Verify that the response resolves the pending request and the response event fires
transportReqMan.transportEventChannel.on("response", function (responseData) { return __awaiter(void 0, void 0, void 0, function () {
var result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, prom];
case 1:
result = _a.sent();
expect(responseData.result).toEqual(res.result);
expect(result).toEqual(res.result);
done();
return [2 /*return*/];
}
});
}); });
// Resolve pending request;
transportReqMan.resolveResponse(JSON.stringify(res));
});
it("should emit response on batch request && resolve response", function (done) { return __awaiter(void 0, void 0, void 0, function () {
var res, requestData, resolve, reject, prom, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
res = [reqData.generateMockResponse(1, "hello")];
requestData = {
request: reqData.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
};
resolve = function (data) {
done();
};
reject = function () {
};
prom = transportReqMan.addRequest([{ request: requestData, resolve: resolve, reject: reject }], null);
// Verify that the response resolves the pending request and the response event fires
transportReqMan.transportEventChannel.on("response", function (responseData) {
expect(responseData.result).toEqual(res[0].result);
expect(result).toEqual(res[0].result);
});
return [4 /*yield*/, prom];
case 1:
result = _a.sent();
// Resolve pending request;
transportReqMan.resolveResponse(JSON.stringify(res), false);
return [2 /*return*/];
}
});
}); });
it("should emit response on batch request && ignore invalid response", function () {
var res = reqData.generateMockResponse(2, "hello");
// Add request to queue
var requestData = {
request: reqData.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
};
// tslint:disable-next-line:no-empty
var resolve = function (data) {
};
// tslint:disable-next-line:no-empty
var reject = function () { };
transportReqMan.addRequest([{ request: requestData, resolve: resolve, reject: reject }], null);
// Resolve pending request;
var err = transportReqMan.resolveResponse(JSON.stringify([res]), false);
expect(err).toBeUndefined();
});
it("should allow notification to clean up after itself", function () {
var req = { request: reqData.generateMockNotificationRequest("foobar", []), internalID: 99 };
transportReqMan.addRequest(req, null);
expect(transportReqMan.isPendingRequest(99)).toEqual(true);
transportReqMan.settlePendingRequest([req]);
expect(transportReqMan.isPendingRequest(99)).toEqual(false);
});
it("should emit notification on notification response", function (done) {
transportReqMan.transportEventChannel.on("notification", function (data) {
expect(data.result).toEqual("hello");
done();
});
transportReqMan.resolveResponse(JSON.stringify(reqData.generateMockNotificationResponse("hello")));
});
it("should emit error on garbage response", function (done) {
transportReqMan.transportEventChannel.on("error", function (err) {
done();
});
transportReqMan.resolveResponse("garbage");
});
it("should emit data on proper error response and reject req prom.", function (done) {
var prom = transportReqMan.addRequest({
request: reqData.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
}, null);
transportReqMan.transportEventChannel.on("response", function (data) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (data.error === undefined) {
throw new Error("Missing error");
}
expect(data.error.data).toEqual("Bad terrible data");
return [4 /*yield*/, expect(prom).rejects.toThrowError("Error message")];
case 1:
_a.sent();
done();
return [2 /*return*/];
}
});
}); });
transportReqMan.resolveResponse(JSON.stringify(reqData.generateMockErrorResponse(1, "Bad terrible data")));
});
});

View File

@@ -0,0 +1,13 @@
/// <reference types="ws" />
import WS from "isomorphic-ws";
import { Transport } from "./Transport";
import { JSONRPCRequestData } from "../Request";
declare class WebSocketTransport extends Transport {
connection: WS;
uri: string;
constructor(uri: string);
connect(): Promise<any>;
sendData(data: JSONRPCRequestData, timeout?: number | null): Promise<any>;
close(): void;
}
export default WebSocketTransport;

View File

@@ -0,0 +1,107 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
var Transport_1 = require("./Transport");
var Request_1 = require("../Request");
var Error_1 = require("../Error");
var WebSocketTransport = /** @class */ (function (_super) {
__extends(WebSocketTransport, _super);
function WebSocketTransport(uri) {
var _this = _super.call(this) || this;
_this.uri = uri;
_this.connection = new isomorphic_ws_1.default(uri);
return _this;
}
WebSocketTransport.prototype.connect = function () {
var _this = this;
return new Promise(function (resolve, reject) {
var cb = function () {
_this.connection.removeEventListener("open", cb);
resolve();
};
_this.connection.addEventListener("open", cb);
_this.connection.addEventListener("message", function (message) {
var data = message.data;
_this.transportRequestManager.resolveResponse(data);
});
});
};
WebSocketTransport.prototype.sendData = function (data, timeout) {
if (timeout === void 0) { timeout = 5000; }
return __awaiter(this, void 0, void 0, function () {
var prom, notifications, jsonError;
return __generator(this, function (_a) {
prom = this.transportRequestManager.addRequest(data, timeout);
notifications = Request_1.getNotifications(data);
try {
this.connection.send(JSON.stringify(this.parseData(data)));
this.transportRequestManager.settlePendingRequest(notifications);
}
catch (err) {
jsonError = new Error_1.JSONRPCError(err.message, Error_1.ERR_UNKNOWN, err);
this.transportRequestManager.settlePendingRequest(notifications, jsonError);
this.transportRequestManager.settlePendingRequest(Request_1.getBatchRequests(data), jsonError);
prom = Promise.reject(jsonError);
}
return [2 /*return*/, prom];
});
});
};
WebSocketTransport.prototype.close = function () {
this.connection.close();
};
return WebSocketTransport;
}(Transport_1.Transport));
exports.default = WebSocketTransport;

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,127 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var WebSocketTransport_1 = __importDefault(require("./WebSocketTransport"));
var requestData_1 = require("../__mocks__/requestData");
describe("WebSocketTransport", function () {
it("can connect", function () {
var wst = new WebSocketTransport_1.default("http://localhost:8545");
return wst.connect();
});
it("can close", function () {
var wst = new WebSocketTransport_1.default("http://localhost:8545");
wst.close();
});
it("can send and receive data", function () { return __awaiter(void 0, void 0, void 0, function () {
var wst, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
wst = new WebSocketTransport_1.default("http://localhost:8545/rpc-request");
return [4 /*yield*/, wst.connect()];
case 1:
_a.sent();
return [4 /*yield*/, wst.sendData({ request: requestData_1.generateMockRequest(1, "foo", ["bar"]), internalID: 1 })];
case 2:
result = _a.sent();
expect(result.method).toEqual("foo");
expect(result.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can send and receive data against potential timeout", function () { return __awaiter(void 0, void 0, void 0, function () {
var wst, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
wst = new WebSocketTransport_1.default("http://localhost:8545/rpc-request");
return [4 /*yield*/, wst.connect()];
case 1:
_a.sent();
return [4 /*yield*/, wst.sendData({ request: requestData_1.generateMockRequest(1, "foo", ["bar"]), internalID: 1 }, 10000)];
case 2:
result = _a.sent();
expect(result.method).toEqual("foo");
expect(result.params).toEqual(["bar"]);
return [2 /*return*/];
}
});
}); });
it("can send and receive errors", function () { return __awaiter(void 0, void 0, void 0, function () {
var wst;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
wst = new WebSocketTransport_1.default("http://localhost:8545/rpc-error");
return [4 /*yield*/, wst.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(wst.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
})).rejects.toThrowError("Error message")];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); });
it("can handle underlying transport crash", function () { return __awaiter(void 0, void 0, void 0, function () {
var wst;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
wst = new WebSocketTransport_1.default("http://localhost:8545/crash");
return [4 /*yield*/, wst.connect()];
case 1:
_a.sent();
return [4 /*yield*/, expect(wst.sendData({
request: requestData_1.generateMockRequest(1, "foo", ["bar"]),
internalID: 1,
})).rejects.toThrowError("Random Segfault that crashes fetch")];
case 2:
_a.sent();
return [2 /*return*/];
}
});
}); });
});