mirror of
https://github.com/idanoo/GoScrobble
synced 2025-07-01 13:42:20 +00:00
0.2.0 - Mid migration
This commit is contained in:
parent
139e6a915e
commit
7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions
4
web/node_modules/worker-rpc/.travis.yml
generated
vendored
Normal file
4
web/node_modules/worker-rpc/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- node
|
||||
|
21
web/node_modules/worker-rpc/LICENSE
generated
vendored
Normal file
21
web/node_modules/worker-rpc/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Christian Speckner <cnspeckn@googlemail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
180
web/node_modules/worker-rpc/README.md
generated
vendored
Normal file
180
web/node_modules/worker-rpc/README.md
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
[](https://travis-ci.org/DirtyHairy/worker-rpc)
|
||||
[](https://badge.fury.io/js/worker-rpc)
|
||||
|
||||
# What is it?
|
||||
|
||||
This package provides a simple RPC mechanism on top of any transport that transfers
|
||||
JSON data. It was initially conceived to provide communication with web workers
|
||||
(and as such supports transferables), but it can be used on top of many other
|
||||
different transport channels, i.e. `postMessage` between frames, websockets via
|
||||
`socket.io` or JSON encoded messages over pipes.
|
||||
|
||||
# How to use it?
|
||||
|
||||
## Installation
|
||||
|
||||
You can install the library into your project via npm
|
||||
|
||||
npm install worker-rpc
|
||||
|
||||
The library is written in Typescript and will work in any environment that
|
||||
supports ES5 and ES6-style promises (either native or through a shim).
|
||||
No external typings are required for using this library with Typescript (version >= 2).
|
||||
|
||||
## Web worker example
|
||||
|
||||
In this example, we use the library to set up communication with a web worker.
|
||||
|
||||
### Web worker
|
||||
|
||||
import {RpcProvider} from 'worker-rpc';
|
||||
|
||||
const rpcProvider = new RpcProvider(
|
||||
(message, transfer) => postMessage(message, transfer)
|
||||
);
|
||||
|
||||
onmessage = e => rpcProvider.dispatch(e.data);
|
||||
|
||||
rpcProvider.registerRpcHandler('add', ({x, y}) => x + y);
|
||||
|
||||
The RPC provider is initialized with a function that dispatches a message.
|
||||
This function will receive an opaque message object as first argument, and
|
||||
a list of transferables as second argument. This allows to leverage transfer
|
||||
of ownership instead of copying between worker and host page.
|
||||
|
||||
On incoming messages, `dispatch` is called on the RPC provider in order to
|
||||
handle the message.
|
||||
|
||||
Each registered RPC handler is identified by a message ID (`add` in this example)
|
||||
and has a handler function that receives the message object and can return a
|
||||
result either as an immediate value or as a promise.
|
||||
|
||||
### Page
|
||||
|
||||
import {RpcProvider} from 'worker-rpc';
|
||||
|
||||
const worker = new Worker('worker.js'),
|
||||
rpcProvider = new RpcProvider(
|
||||
(message, transfer) => worker.postMessage(message, transfer)
|
||||
);
|
||||
|
||||
worker.onmessage = e => rpcProvider.dispatch(e.data);
|
||||
|
||||
rpcProvider
|
||||
.rpc('add', {x: 1, y: 2})
|
||||
.then(result => console.log(result)); // 3
|
||||
|
||||
## Importing
|
||||
|
||||
ES5 / CommonJS
|
||||
|
||||
var RpcProvider = require('worker-rpc').RpcProvider;
|
||||
|
||||
ES6
|
||||
|
||||
import {RpcProvider} from 'worker-rpc';
|
||||
|
||||
Typescript
|
||||
|
||||
import {RpcProvider, RpcProviderInterface} from 'worker-rpc';
|
||||
|
||||
## API
|
||||
|
||||
The API is built around the `RpcProvider` class. A `RpcProvider` acts both as
|
||||
client and server for RPC calls and event-like signals. The library uses ES6
|
||||
promises and can consume any A+ compliant promises.
|
||||
|
||||
### Creating a new provider
|
||||
|
||||
const rpc = new RpcProvider(dispatcher, timeout);
|
||||
|
||||
* `dispatcher`: A function that will be called for dispatching messages. The
|
||||
first argument will be an opaque message object, and the second argument
|
||||
an error of `Transferable` objects that are to be passed via ownership
|
||||
transfer (if supported by the transport).
|
||||
* `timeout` (optional): The timeout for RPC transactions in milliseconds.
|
||||
Values of `0` or smaller disable the timeout (this is the default).
|
||||
|
||||
### Incoming messages
|
||||
|
||||
rpc.dispatch(message);
|
||||
|
||||
Similar to message dispatch, `worker-rpc` does not provide a built-in mechanism
|
||||
for receiving messages. Instead, incoming messages must be relayed to the provider
|
||||
by invoking `dispatch`.
|
||||
|
||||
* `message`: The received message.
|
||||
|
||||
### Registering RPC handlers
|
||||
|
||||
rpc.registerRpcHandler(id, handler);
|
||||
|
||||
Register a handler function for RPC calls with id `id`. Returns the provider instance.
|
||||
|
||||
* `id`: RPC call id. Only a single handler can be registered for any id. Ids should
|
||||
be strings.
|
||||
* `handler`: The handler function. This function receives the payload object as
|
||||
its argument and can return its result either as an immediate value or as a
|
||||
promise.
|
||||
|
||||
### Registering signal handlers
|
||||
|
||||
rpc.registerSignalHandler(id, handler));
|
||||
|
||||
Register a handler function for signals with id `id`. Returns the provider instance.
|
||||
|
||||
* `id`: Signal id. The namespace for signal ids is seperate from that of RPC ids,
|
||||
and multiple handlers my be attached tp a single signal. Ids should be strings
|
||||
* `handler`: The handler function. This function receives the payload object as
|
||||
its argument; the result is ignored.
|
||||
|
||||
### Dispatching RPC calls
|
||||
|
||||
const result = rpc.rpc(id, payload, transfer);
|
||||
|
||||
Dispatch a RPC call and returns a promise for its result. The promise is rejected
|
||||
if the call times out or if no handler is registered (or if the handler rejects
|
||||
the operation).
|
||||
|
||||
* `id`: RPC call id.
|
||||
* `payload` (optional): RPC call payload.
|
||||
* `transfer` (optional): List of `Transferables` that will be passed to dispatched
|
||||
(see above).
|
||||
|
||||
### Dispatching signals
|
||||
|
||||
rpc.signal(id, payload, transfer);
|
||||
|
||||
Dispatch a signal. Returns the provider instance.
|
||||
|
||||
* `id`: Signal id.
|
||||
* `payload` (optional): Signal payload.
|
||||
* `transfer` (optional): List of `Transferables` that will be passed to dispatched
|
||||
(see above).
|
||||
|
||||
### Deregistering RPC handlers
|
||||
|
||||
rpc.deregisterRpcHandler(id, handler);
|
||||
|
||||
`id` and `handler` must be the same arguments used for `registerRpcHandler`.
|
||||
Returns the provider instance.
|
||||
|
||||
### Deregistering signal handlers
|
||||
|
||||
rpc.deregisterSignalHandler(id, handler);
|
||||
|
||||
`id` and `handler` must be the same arguments used for `registerSignalHandler`.
|
||||
Returns the provider instance.
|
||||
|
||||
### Errors
|
||||
|
||||
rpc.error.addHandler(errorHandler);
|
||||
|
||||
The error event is dispatched if there is either a local or remote communcation
|
||||
error (timeout, invalid id, etc.). Checkout the
|
||||
[microevent.ts](https://github.com/DirtyHairy/microevent)
|
||||
documentation for the event API.
|
||||
|
||||
# License
|
||||
|
||||
Feel free to use this library under the conditions of the MIT license.
|
42
web/node_modules/worker-rpc/lib/RpcProvider.d.ts
generated
vendored
Normal file
42
web/node_modules/worker-rpc/lib/RpcProvider.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { Event } from 'microevent.ts';
|
||||
import RpcProviderInterface from './RpcProviderInterface';
|
||||
declare class RpcProvider implements RpcProviderInterface {
|
||||
private _dispatch;
|
||||
private _rpcTimeout;
|
||||
constructor(_dispatch: RpcProvider.Dispatcher, _rpcTimeout?: number);
|
||||
dispatch(payload: any): void;
|
||||
rpc<T, U>(id: string, payload?: T, transfer?: any): Promise<U>;
|
||||
signal<T>(id: string, payload?: T, transfer?: any): this;
|
||||
registerRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
registerSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
deregisterRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
deregisterSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
private _raiseError;
|
||||
private _handleSignal;
|
||||
private _handeRpc;
|
||||
private _handleInternal;
|
||||
private _transactionTimeout;
|
||||
private _clearTransaction;
|
||||
error: Event<Error>;
|
||||
private _rpcHandlers;
|
||||
private _signalHandlers;
|
||||
private _pendingTransactions;
|
||||
private _nextTransactionId;
|
||||
}
|
||||
declare module RpcProvider {
|
||||
enum MessageType {
|
||||
signal = 0,
|
||||
rpc = 1,
|
||||
internal = 2
|
||||
}
|
||||
interface Dispatcher {
|
||||
(message: Message, transfer?: Array<any>): void;
|
||||
}
|
||||
interface Message {
|
||||
type: MessageType;
|
||||
transactionId?: number;
|
||||
id: string;
|
||||
payload?: any;
|
||||
}
|
||||
}
|
||||
export default RpcProvider;
|
166
web/node_modules/worker-rpc/lib/RpcProvider.js
generated
vendored
Normal file
166
web/node_modules/worker-rpc/lib/RpcProvider.js
generated
vendored
Normal file
|
@ -0,0 +1,166 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var microevent_ts_1 = require("microevent.ts");
|
||||
var MSG_RESOLVE_TRANSACTION = "resolve_transaction", MSG_REJECT_TRANSACTION = "reject_transaction", MSG_ERROR = "error";
|
||||
var RpcProvider = /** @class */ (function () {
|
||||
function RpcProvider(_dispatch, _rpcTimeout) {
|
||||
if (_rpcTimeout === void 0) { _rpcTimeout = 0; }
|
||||
this._dispatch = _dispatch;
|
||||
this._rpcTimeout = _rpcTimeout;
|
||||
this.error = new microevent_ts_1.Event();
|
||||
this._rpcHandlers = {};
|
||||
this._signalHandlers = {};
|
||||
this._pendingTransactions = {};
|
||||
this._nextTransactionId = 0;
|
||||
}
|
||||
RpcProvider.prototype.dispatch = function (payload) {
|
||||
var message = payload;
|
||||
switch (message.type) {
|
||||
case RpcProvider.MessageType.signal:
|
||||
return this._handleSignal(message);
|
||||
case RpcProvider.MessageType.rpc:
|
||||
return this._handeRpc(message);
|
||||
case RpcProvider.MessageType.internal:
|
||||
return this._handleInternal(message);
|
||||
default:
|
||||
this._raiseError("invalid message type " + message.type);
|
||||
}
|
||||
};
|
||||
RpcProvider.prototype.rpc = function (id, payload, transfer) {
|
||||
var _this = this;
|
||||
var transactionId = this._nextTransactionId++;
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.rpc,
|
||||
transactionId: transactionId,
|
||||
id: id,
|
||||
payload: payload
|
||||
}, transfer ? transfer : undefined);
|
||||
return new Promise(function (resolve, reject) {
|
||||
var transaction = _this._pendingTransactions[transactionId] = {
|
||||
id: transactionId,
|
||||
resolve: resolve,
|
||||
reject: reject
|
||||
};
|
||||
if (_this._rpcTimeout > 0) {
|
||||
_this._pendingTransactions[transactionId].timeoutHandle =
|
||||
setTimeout(function () { return _this._transactionTimeout(transaction); }, _this._rpcTimeout);
|
||||
}
|
||||
});
|
||||
};
|
||||
;
|
||||
RpcProvider.prototype.signal = function (id, payload, transfer) {
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.signal,
|
||||
id: id,
|
||||
payload: payload,
|
||||
}, transfer ? transfer : undefined);
|
||||
return this;
|
||||
};
|
||||
RpcProvider.prototype.registerRpcHandler = function (id, handler) {
|
||||
if (this._rpcHandlers[id]) {
|
||||
throw new Error("rpc handler for " + id + " already registered");
|
||||
}
|
||||
this._rpcHandlers[id] = handler;
|
||||
return this;
|
||||
};
|
||||
;
|
||||
RpcProvider.prototype.registerSignalHandler = function (id, handler) {
|
||||
if (!this._signalHandlers[id]) {
|
||||
this._signalHandlers[id] = [];
|
||||
}
|
||||
this._signalHandlers[id].push(handler);
|
||||
return this;
|
||||
};
|
||||
RpcProvider.prototype.deregisterRpcHandler = function (id, handler) {
|
||||
if (this._rpcHandlers[id]) {
|
||||
delete this._rpcHandlers[id];
|
||||
}
|
||||
return this;
|
||||
};
|
||||
;
|
||||
RpcProvider.prototype.deregisterSignalHandler = function (id, handler) {
|
||||
if (this._signalHandlers[id]) {
|
||||
this._signalHandlers[id] = this._signalHandlers[id].filter(function (h) { return handler !== h; });
|
||||
}
|
||||
return this;
|
||||
};
|
||||
RpcProvider.prototype._raiseError = function (error) {
|
||||
this.error.dispatch(new Error(error));
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_ERROR,
|
||||
payload: error
|
||||
});
|
||||
};
|
||||
RpcProvider.prototype._handleSignal = function (message) {
|
||||
if (!this._signalHandlers[message.id]) {
|
||||
return this._raiseError("invalid signal " + message.id);
|
||||
}
|
||||
this._signalHandlers[message.id].forEach(function (handler) { return handler(message.payload); });
|
||||
};
|
||||
RpcProvider.prototype._handeRpc = function (message) {
|
||||
var _this = this;
|
||||
if (!this._rpcHandlers[message.id]) {
|
||||
return this._raiseError("invalid rpc " + message.id);
|
||||
}
|
||||
Promise.resolve(this._rpcHandlers[message.id](message.payload))
|
||||
.then(function (result) { return _this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_RESOLVE_TRANSACTION,
|
||||
transactionId: message.transactionId,
|
||||
payload: result
|
||||
}); }, function (reason) { return _this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_REJECT_TRANSACTION,
|
||||
transactionId: message.transactionId,
|
||||
payload: reason
|
||||
}); });
|
||||
};
|
||||
RpcProvider.prototype._handleInternal = function (message) {
|
||||
switch (message.id) {
|
||||
case MSG_RESOLVE_TRANSACTION:
|
||||
if (!this._pendingTransactions[message.transactionId]) {
|
||||
return this._raiseError("no pending transaction with id " + message.transactionId);
|
||||
}
|
||||
this._pendingTransactions[message.transactionId].resolve(message.payload);
|
||||
this._clearTransaction(this._pendingTransactions[message.transactionId]);
|
||||
break;
|
||||
case MSG_REJECT_TRANSACTION:
|
||||
if (!this._pendingTransactions[message.transactionId]) {
|
||||
return this._raiseError("no pending transaction with id " + message.transactionId);
|
||||
}
|
||||
this._pendingTransactions[message.transactionId].reject(message.payload);
|
||||
this._clearTransaction(this._pendingTransactions[message.transactionId]);
|
||||
break;
|
||||
case MSG_ERROR:
|
||||
this.error.dispatch(new Error("remote error: " + message.payload));
|
||||
break;
|
||||
default:
|
||||
this._raiseError("unhandled internal message " + message.id);
|
||||
break;
|
||||
}
|
||||
};
|
||||
RpcProvider.prototype._transactionTimeout = function (transaction) {
|
||||
transaction.reject('transaction timed out');
|
||||
this._raiseError("transaction " + transaction.id + " timed out");
|
||||
delete this._pendingTransactions[transaction.id];
|
||||
return;
|
||||
};
|
||||
RpcProvider.prototype._clearTransaction = function (transaction) {
|
||||
if (typeof (transaction.timeoutHandle) !== 'undefined') {
|
||||
clearTimeout(transaction.timeoutHandle);
|
||||
}
|
||||
delete this._pendingTransactions[transaction.id];
|
||||
};
|
||||
return RpcProvider;
|
||||
}());
|
||||
(function (RpcProvider) {
|
||||
var MessageType;
|
||||
(function (MessageType) {
|
||||
MessageType[MessageType["signal"] = 0] = "signal";
|
||||
MessageType[MessageType["rpc"] = 1] = "rpc";
|
||||
MessageType[MessageType["internal"] = 2] = "internal";
|
||||
})(MessageType = RpcProvider.MessageType || (RpcProvider.MessageType = {}));
|
||||
;
|
||||
})(RpcProvider || (RpcProvider = {}));
|
||||
exports.default = RpcProvider;
|
20
web/node_modules/worker-rpc/lib/RpcProviderInterface.d.ts
generated
vendored
Normal file
20
web/node_modules/worker-rpc/lib/RpcProviderInterface.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { EventInterface } from 'microevent.ts';
|
||||
interface RpcProviderInterface {
|
||||
dispatch(message: any): void;
|
||||
rpc<T, U>(id: string, payload?: T, transfer?: Array<any>): Promise<U>;
|
||||
signal<T>(id: string, payload?: T, transfer?: Array<any>): this;
|
||||
registerRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
registerSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
deregisterRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
deregisterSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
error: EventInterface<Error>;
|
||||
}
|
||||
declare module RpcProviderInterface {
|
||||
interface RpcHandler<T, U> {
|
||||
(payload?: T): Promise<U> | U;
|
||||
}
|
||||
interface SignalHandler<T> {
|
||||
(payload?: T): void;
|
||||
}
|
||||
}
|
||||
export default RpcProviderInterface;
|
2
web/node_modules/worker-rpc/lib/RpcProviderInterface.js
generated
vendored
Normal file
2
web/node_modules/worker-rpc/lib/RpcProviderInterface.js
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
2
web/node_modules/worker-rpc/lib/index.d.ts
generated
vendored
Normal file
2
web/node_modules/worker-rpc/lib/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default as RpcProvider } from './RpcProvider';
|
||||
export { default as RpcProviderInterface } from './RpcProviderInterface';
|
4
web/node_modules/worker-rpc/lib/index.js
generated
vendored
Normal file
4
web/node_modules/worker-rpc/lib/index.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var RpcProvider_1 = require("./RpcProvider");
|
||||
exports.RpcProvider = RpcProvider_1.default;
|
30
web/node_modules/worker-rpc/package.json
generated
vendored
Normal file
30
web/node_modules/worker-rpc/package.json
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "worker-rpc",
|
||||
"version": "0.1.1",
|
||||
"description": "A simple RPC layer for communicating with web workers and over other transports",
|
||||
"scripts": {
|
||||
"prepublish": "tsc",
|
||||
"pretest": "typings install && tsc -p tsconfig.test.json",
|
||||
"test": "mocha -R spec -u tdd test"
|
||||
},
|
||||
"author": "Christian Speckner <cnspeckn@googlemail.com> (https://github.com/DirtyHairy/)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DirtyHairy/worker-rpc"
|
||||
},
|
||||
"keywords": [
|
||||
"worker",
|
||||
"rpc"
|
||||
],
|
||||
"devDependencies": {
|
||||
"mocha": "~6.1.4",
|
||||
"typescript": "~3.4.5",
|
||||
"typings": "~2.1.1"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"microevent.ts": "~0.1.1"
|
||||
}
|
||||
}
|
233
web/node_modules/worker-rpc/src/RpcProvider.ts
generated
vendored
Normal file
233
web/node_modules/worker-rpc/src/RpcProvider.ts
generated
vendored
Normal file
|
@ -0,0 +1,233 @@
|
|||
import {Event} from 'microevent.ts';
|
||||
|
||||
import RpcProviderInterface from './RpcProviderInterface';
|
||||
|
||||
const MSG_RESOLVE_TRANSACTION = "resolve_transaction",
|
||||
MSG_REJECT_TRANSACTION = "reject_transaction",
|
||||
MSG_ERROR = "error";
|
||||
|
||||
interface Transaction {
|
||||
id: number;
|
||||
timeoutHandle?: any;
|
||||
resolve(result: any): void;
|
||||
reject(error: string): void;
|
||||
}
|
||||
|
||||
class RpcProvider implements RpcProviderInterface {
|
||||
|
||||
constructor(
|
||||
private _dispatch: RpcProvider.Dispatcher,
|
||||
private _rpcTimeout = 0
|
||||
) {}
|
||||
|
||||
dispatch(payload: any): void {
|
||||
const message = payload as RpcProvider.Message;
|
||||
|
||||
switch (message.type) {
|
||||
case RpcProvider.MessageType.signal:
|
||||
return this._handleSignal(message);
|
||||
|
||||
case RpcProvider.MessageType.rpc:
|
||||
return this._handeRpc(message);
|
||||
|
||||
case RpcProvider.MessageType.internal:
|
||||
return this._handleInternal(message);
|
||||
|
||||
default:
|
||||
this._raiseError(`invalid message type ${message.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
rpc<T, U>(id: string, payload?: T, transfer?: any): Promise<U> {
|
||||
const transactionId = this._nextTransactionId++;
|
||||
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.rpc,
|
||||
transactionId,
|
||||
id,
|
||||
payload
|
||||
}, transfer ? transfer : undefined);
|
||||
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
const transaction = this._pendingTransactions[transactionId] = {
|
||||
id: transactionId,
|
||||
resolve,
|
||||
reject
|
||||
};
|
||||
|
||||
if (this._rpcTimeout > 0) {
|
||||
this._pendingTransactions[transactionId].timeoutHandle =
|
||||
setTimeout(() => this._transactionTimeout(transaction), this._rpcTimeout);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
signal<T>(id: string, payload?: T, transfer?: any): this {
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.signal,
|
||||
id,
|
||||
payload,
|
||||
}, transfer ? transfer : undefined);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
registerRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this {
|
||||
if (this._rpcHandlers[id]) {
|
||||
throw new Error(`rpc handler for ${id} already registered`);
|
||||
}
|
||||
|
||||
this._rpcHandlers[id] = handler;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
registerSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this {
|
||||
if (!this._signalHandlers[id]) {
|
||||
this._signalHandlers[id] = [];
|
||||
}
|
||||
|
||||
this._signalHandlers[id].push(handler);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
deregisterRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this {
|
||||
if (this._rpcHandlers[id]) {
|
||||
delete this._rpcHandlers[id];
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
deregisterSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this {
|
||||
if (this._signalHandlers[id]) {
|
||||
this._signalHandlers[id] = this._signalHandlers[id].filter(h => handler !== h);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private _raiseError(error: string): void {
|
||||
this.error.dispatch(new Error(error));
|
||||
|
||||
this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_ERROR,
|
||||
payload: error
|
||||
});
|
||||
}
|
||||
|
||||
private _handleSignal(message: RpcProvider.Message): void {
|
||||
if (!this._signalHandlers[message.id]) {
|
||||
return this._raiseError(`invalid signal ${message.id}`);
|
||||
}
|
||||
|
||||
this._signalHandlers[message.id].forEach(handler => handler(message.payload));
|
||||
}
|
||||
|
||||
private _handeRpc(message: RpcProvider.Message): void {
|
||||
if (!this._rpcHandlers[message.id]) {
|
||||
return this._raiseError(`invalid rpc ${message.id}`);
|
||||
}
|
||||
|
||||
Promise.resolve(this._rpcHandlers[message.id](message.payload))
|
||||
.then(
|
||||
(result: any) => this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_RESOLVE_TRANSACTION,
|
||||
transactionId: message.transactionId,
|
||||
payload: result
|
||||
}),
|
||||
(reason: string) => this._dispatch({
|
||||
type: RpcProvider.MessageType.internal,
|
||||
id: MSG_REJECT_TRANSACTION,
|
||||
transactionId: message.transactionId,
|
||||
payload: reason
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private _handleInternal(message: RpcProvider.Message): void {
|
||||
switch (message.id) {
|
||||
case MSG_RESOLVE_TRANSACTION:
|
||||
if (!this._pendingTransactions[message.transactionId]) {
|
||||
return this._raiseError(`no pending transaction with id ${message.transactionId}`);
|
||||
}
|
||||
|
||||
this._pendingTransactions[message.transactionId].resolve(message.payload);
|
||||
this._clearTransaction(this._pendingTransactions[message.transactionId]);
|
||||
|
||||
break;
|
||||
|
||||
case MSG_REJECT_TRANSACTION:
|
||||
if (!this._pendingTransactions[message.transactionId]) {
|
||||
return this._raiseError(`no pending transaction with id ${message.transactionId}`);
|
||||
}
|
||||
|
||||
this._pendingTransactions[message.transactionId].reject(message.payload);
|
||||
this._clearTransaction(this._pendingTransactions[message.transactionId]);
|
||||
|
||||
break;
|
||||
|
||||
case MSG_ERROR:
|
||||
this.error.dispatch(new Error(`remote error: ${message.payload}`));
|
||||
break;
|
||||
|
||||
default:
|
||||
this._raiseError(`unhandled internal message ${message.id}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private _transactionTimeout(transaction: Transaction): void {
|
||||
transaction.reject('transaction timed out');
|
||||
|
||||
this._raiseError(`transaction ${transaction.id} timed out`);
|
||||
|
||||
delete this._pendingTransactions[transaction.id];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private _clearTransaction(transaction: Transaction): void {
|
||||
if (typeof(transaction.timeoutHandle) !== 'undefined') {
|
||||
clearTimeout(transaction.timeoutHandle);
|
||||
}
|
||||
|
||||
delete this._pendingTransactions[transaction.id];
|
||||
}
|
||||
|
||||
error = new Event<Error>();
|
||||
|
||||
private _rpcHandlers: {[id: string]: RpcProviderInterface.RpcHandler<any, any>} = {};
|
||||
private _signalHandlers: {[id: string]: Array<RpcProviderInterface.SignalHandler<any>>} = {};
|
||||
private _pendingTransactions: {[id: number]: Transaction} = {};
|
||||
|
||||
private _nextTransactionId = 0;
|
||||
}
|
||||
|
||||
module RpcProvider {
|
||||
|
||||
export enum MessageType {
|
||||
signal,
|
||||
rpc,
|
||||
internal
|
||||
};
|
||||
|
||||
export interface Dispatcher {
|
||||
(message: Message, transfer?: Array<any>): void;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
type: MessageType;
|
||||
transactionId?: number;
|
||||
id: string;
|
||||
payload?: any;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RpcProvider;
|
35
web/node_modules/worker-rpc/src/RpcProviderInterface.ts
generated
vendored
Normal file
35
web/node_modules/worker-rpc/src/RpcProviderInterface.ts
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
import {EventInterface} from 'microevent.ts';
|
||||
|
||||
interface RpcProviderInterface {
|
||||
|
||||
dispatch(message: any): void;
|
||||
|
||||
rpc<T, U>(id: string, payload?: T, transfer?: Array<any>): Promise<U>;
|
||||
|
||||
signal<T>(id: string, payload?: T, transfer?: Array<any>): this;
|
||||
|
||||
registerRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
|
||||
registerSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
|
||||
deregisterRpcHandler<T, U>(id: string, handler: RpcProviderInterface.RpcHandler<T, U>): this;
|
||||
|
||||
deregisterSignalHandler<T>(id: string, handler: RpcProviderInterface.SignalHandler<T>): this;
|
||||
|
||||
error: EventInterface<Error>;
|
||||
|
||||
}
|
||||
|
||||
module RpcProviderInterface {
|
||||
|
||||
export interface RpcHandler<T, U> {
|
||||
(payload?: T): Promise<U>|U;
|
||||
}
|
||||
|
||||
export interface SignalHandler<T> {
|
||||
(payload?: T): void;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RpcProviderInterface;
|
2
web/node_modules/worker-rpc/src/index.ts
generated
vendored
Normal file
2
web/node_modules/worker-rpc/src/index.ts
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
export {default as RpcProvider} from './RpcProvider';
|
||||
export {default as RpcProviderInterface} from './RpcProviderInterface';
|
242
web/node_modules/worker-rpc/test/rpcProvider.ts
generated
vendored
Normal file
242
web/node_modules/worker-rpc/test/rpcProvider.ts
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
/// <reference path="../typings/index.d.ts"/>
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
import RpcProvider from '../src/RpcProvider';
|
||||
|
||||
suite('RPC provider', function() {
|
||||
|
||||
let local: RpcProvider,
|
||||
remote: RpcProvider,
|
||||
transferLocalToRemote: Array<any>,
|
||||
transferRemoteToLocal: Array<any>,
|
||||
errorLocal: Error,
|
||||
errorRemote: Error;
|
||||
|
||||
setup(function() {
|
||||
local = new RpcProvider(
|
||||
(message, transfer) => (transferLocalToRemote = transfer, remote.dispatch(message)),
|
||||
50
|
||||
);
|
||||
|
||||
local.error.addHandler(err => errorLocal = err);
|
||||
|
||||
remote = new RpcProvider(
|
||||
(message, transfer) => (transferRemoteToLocal = transfer, local.dispatch(message)),
|
||||
50
|
||||
);
|
||||
|
||||
remote.error.addHandler(err => errorRemote = err);
|
||||
|
||||
transferLocalToRemote = transferRemoteToLocal = undefined;
|
||||
errorRemote = errorLocal = undefined
|
||||
});
|
||||
|
||||
suite('signals', function() {
|
||||
|
||||
test('Signals are propagated', function() {
|
||||
let x = -1;
|
||||
|
||||
remote.registerSignalHandler('action', (value: number) => x = value);
|
||||
|
||||
local.signal('action', 5);
|
||||
|
||||
assert(!errorLocal);
|
||||
assert(!errorRemote);
|
||||
assert.strictEqual(x, 5);
|
||||
});
|
||||
|
||||
test('Unregistered signals raise an error', function() {
|
||||
local.signal('action', 10);
|
||||
|
||||
assert(errorLocal);
|
||||
assert(errorRemote);
|
||||
});
|
||||
|
||||
test('Multiple signals do not interfere', function() {
|
||||
let x = -1, y = -1;
|
||||
|
||||
remote.registerSignalHandler('setx', (value: number) => x = value);
|
||||
remote.registerSignalHandler('sety', (value: number) => y = value);
|
||||
|
||||
local.signal('setx', 5);
|
||||
local.signal('sety', 6);
|
||||
|
||||
assert(!errorLocal);
|
||||
assert(!errorRemote);
|
||||
assert.strictEqual(x, 5);
|
||||
assert.strictEqual(y, 6);
|
||||
});
|
||||
|
||||
test('Multiple handlers can be bound to one signal', function() {
|
||||
let x = -1;
|
||||
|
||||
remote.registerSignalHandler('action', (value: number) => x = value);
|
||||
|
||||
local.signal('action', 1);
|
||||
local.signal('action', 2);
|
||||
|
||||
assert(!errorLocal);
|
||||
assert(!errorRemote);
|
||||
assert.strictEqual(x, 2);
|
||||
});
|
||||
|
||||
test('Handlers can be deregistered', function() {
|
||||
let x = -1;
|
||||
|
||||
const handler = (value: number) => x = value;
|
||||
|
||||
remote.registerSignalHandler('action', handler);
|
||||
remote.deregisterSignalHandler('action', handler);
|
||||
|
||||
local.signal('action', 5);
|
||||
|
||||
assert(!errorLocal);
|
||||
assert(!errorRemote);
|
||||
assert.strictEqual(x, -1);
|
||||
});
|
||||
|
||||
test('Transfer is honored', function() {
|
||||
let x = -1;
|
||||
const transfer = [1, 2, 3];
|
||||
|
||||
remote.registerSignalHandler('action', (value: number) => x = value);
|
||||
|
||||
local.signal('action', 2, transfer);
|
||||
|
||||
assert(!errorLocal);
|
||||
assert(!errorRemote);
|
||||
assert.strictEqual(x, 2);
|
||||
assert.strictEqual(transferLocalToRemote, transfer);
|
||||
assert(!transferRemoteToLocal);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('RPC', function() {
|
||||
|
||||
test('RPC handlers can return values', function() {
|
||||
remote.registerRpcHandler('action', () => 10);
|
||||
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(result => (
|
||||
assert.strictEqual(result, 10),
|
||||
assert(!errorLocal),
|
||||
assert(!errorRemote)
|
||||
));
|
||||
});
|
||||
|
||||
test('RPC handlers can return promises', function() {
|
||||
remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 15)));
|
||||
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(result => (
|
||||
assert.strictEqual(result, 10),
|
||||
assert(!errorLocal),
|
||||
assert(!errorRemote)
|
||||
));
|
||||
})
|
||||
|
||||
test('Promise rejection is transferred', function() {
|
||||
remote.registerRpcHandler('action', () => new Promise((resolve, reject) => setTimeout(() => reject(10), 15)));
|
||||
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(
|
||||
() => Promise.reject('should have been rejected'),
|
||||
result => (
|
||||
assert.strictEqual(result, 10),
|
||||
assert(!errorLocal),
|
||||
assert(!errorRemote)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test('Invalid RPC calls are rejected', function() {
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(
|
||||
() => Promise.reject('should have been rejected'),
|
||||
() => undefined
|
||||
);
|
||||
});
|
||||
|
||||
test('Invalid RPC calls throw on both ends', function() {
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(
|
||||
() => Promise.reject('should have been rejected'),
|
||||
() => undefined
|
||||
)
|
||||
.then(() => (
|
||||
assert(errorLocal),
|
||||
assert(errorRemote)
|
||||
));
|
||||
});
|
||||
|
||||
test('RPC calls time out', function() {
|
||||
remote.registerRpcHandler('action', () => new Promise(r => setTimeout(() => r(10), 100)));
|
||||
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(
|
||||
() => Promise.reject('should have been rejected'),
|
||||
() => (assert(errorLocal), new Promise(r => setTimeout(r, 100)))
|
||||
)
|
||||
.then(() => assert(errorRemote));
|
||||
});
|
||||
|
||||
test('Multiple RPC handlers do not interfere', function() {
|
||||
remote.registerRpcHandler('a1', (value: number) => new Promise(r => setTimeout(() => r(value), 30)));
|
||||
remote.registerRpcHandler('a2', (value: number) => 2 * value);
|
||||
|
||||
return Promise
|
||||
.all([
|
||||
local.rpc('a1', 10),
|
||||
local.rpc('a2', 20)
|
||||
])
|
||||
.then(([r1, r2]) => (
|
||||
assert.strictEqual(r1, 10),
|
||||
assert.strictEqual(r2, 40),
|
||||
assert(!errorLocal),
|
||||
assert(!errorRemote)
|
||||
));
|
||||
});
|
||||
|
||||
test('RPC handler can be deregistered', function() {
|
||||
const handler = () => 10;
|
||||
|
||||
remote.registerRpcHandler('action', handler);
|
||||
remote.deregisterRpcHandler('action', handler);
|
||||
|
||||
return local
|
||||
.rpc('action')
|
||||
.then(
|
||||
() => Promise.reject('should have been rejected'),
|
||||
() => (
|
||||
assert(errorLocal),
|
||||
assert(errorRemote)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test('Transfer is honored', function() {
|
||||
const transfer = [1, 2, 3];
|
||||
|
||||
remote.registerRpcHandler('action', () => 10);
|
||||
|
||||
return local
|
||||
.rpc('action', undefined, transfer)
|
||||
.then(x => (
|
||||
assert.strictEqual(transferLocalToRemote, transfer),
|
||||
assert.strictEqual(x, 10),
|
||||
assert(!errorLocal),
|
||||
assert(!errorRemote)
|
||||
));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
15
web/node_modules/worker-rpc/tsconfig.json
generated
vendored
Normal file
15
web/node_modules/worker-rpc/tsconfig.json
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": false,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"declaration": true,
|
||||
"outDir": "lib",
|
||||
"lib": ["es5", "es6", "dom"],
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
12
web/node_modules/worker-rpc/tsconfig.test.json
generated
vendored
Normal file
12
web/node_modules/worker-rpc/tsconfig.test.json
generated
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": false,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"lib": ["es5", "es6", "dom"]
|
||||
},
|
||||
"include": ["test/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
6
web/node_modules/worker-rpc/typings.json
generated
vendored
Normal file
6
web/node_modules/worker-rpc/typings.json
generated
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"globalDependencies": {
|
||||
"mocha": "registry:dt/mocha#2.2.5+20160720003353",
|
||||
"node": "registry:dt/node#6.0.0+20161019125345"
|
||||
}
|
||||
}
|
1789
web/node_modules/worker-rpc/yarn.lock
generated
vendored
Normal file
1789
web/node_modules/worker-rpc/yarn.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue