@ch1/rpc
Version:
JavaScript Remote Procedure Call (RPC)
227 lines • 5.83 kB
JavaScript
import { DEFAULT_ASYNC_TYPE } from './constants';
/**
* This function is for creating new instances of functions. This is handy for
* "enhancing" and enforcing correctness with certain event emitter libraries
*
* __Note__ this function will likely not work with arrow functions
*
* __Note__ this function uses `new Function`. Consequently functions will be
* created in the global context. In other words, make sure your function is
* pure and does not rely on external variables, unless those variables are
* global.
*/
export function createNewFunctionFrom(func) {
const rawFunctionString = func.toString();
/** Eliminate references to Istanbul code coverage */
const functionString = rawFunctionString.replace(/__cov_(.+?)\+\+;?/g, '');
// proceed with normal logic
const firstCurly = functionString.indexOf('{') + 1;
const lastCurly = functionString.lastIndexOf('}');
const firstBracket = functionString.indexOf('(') + 1;
const lastBracket = functionString.indexOf(')');
const functionContents = functionString.slice(firstCurly, lastCurly);
const args = functionString
.slice(firstBracket, lastBracket)
.split(',')
.filter(Boolean)
.map(s => s.trim());
return new Function(...args, functionContents);
}
export function isRPC(arg) {
if (!arg) {
return false;
}
if (!isFunction(arg.destroy)) {
return false;
}
if (!arg.remote) {
return false;
}
return true;
}
export const isRPCDefaultAsync = arg => {
if (arg === DEFAULT_ASYNC_TYPE) {
return true;
}
return false;
};
export function isDefer(thing) {
if (!thing) {
return false;
}
if (!isFunction(thing.resolve)) {
return false;
}
if (!isFunction(thing.reject)) {
return false;
}
if (!isPromise(thing.promise)) {
return false;
}
return true;
}
export function isError(err) {
return err instanceof Error;
}
export function isFunction(fn) {
return typeof fn === 'function';
}
export function isObject(obj) {
if (!obj) {
return false;
}
return typeof obj === 'object';
}
export function isString(arg) {
return typeof arg === 'string';
}
export function isDictionary(dict) {
return isObject(dict);
}
export function isPromise(promise) {
if (!promise) {
return false;
}
if (!isFunction(promise.then)) {
return false;
}
if (!isFunction(promise.catch)) {
return false;
}
return true;
}
export function isRPCNodeCallback(arg) {
return isFunction(arg);
}
export function isRPCNotify(arg) {
return isFunction(arg);
}
export function isRPCEvent(event) {
if (!event) {
return false;
}
if (typeof event.uid !== 'string') {
return false;
}
if (typeof event.type !== 'number') {
return false;
}
if (isRPCErrorPayload(event.payload) ||
isRPCInvocationPayload(event.payload) ||
isRPCReturnPayload(event.payload)) {
return true;
}
return false;
}
export function isRPCError(error) {
if (!error) {
return false;
}
if (!error.message) {
return false;
}
return true;
}
export function isRPCErrorPayload(payload) {
if (!payload) {
return false;
}
return isRPCError(payload.error);
}
export function isRPCInvocationPayload(payload) {
if (!payload) {
return false;
}
if (!Array.isArray(payload.args)) {
return false;
}
if (typeof payload.fn !== 'string') {
return false;
}
return true;
}
export function isRPCReturnPayload(payload) {
if (!payload) {
return false;
}
return Array.isArray(payload.result);
}
export function noop() { }
export const pnoop = () => new Promise(resolve => resolve());
export function createUidGenerator() {
let uidCount = 0;
const rpcId = Math.floor(Math.random() * 100000).toString(32);
return () => {
// increment the counter
uidCount += 1;
// return a uid
return [rpcId, uidCount.toString(32)].join('-');
};
}
export function defer() {
let pass = noop;
let fail = noop;
const promise = new Promise((resolve, reject) => {
pass = resolve;
fail = reject;
});
return {
promise,
reject: fail,
resolve: pass,
};
}
export function createRangeError(message) {
return new RangeError('js-rpc: ' + message);
}
export function createTypeError(message) {
return new TypeError('js-rpc: ' + message);
}
export function rangeError(message) {
throw createRangeError(message);
}
export function safeInstantiate(fn, args) {
try {
return new (Function.prototype.bind.apply(fn, arguments))();
}
catch (err) {
return err;
}
}
export function safeInvoke(fn, args) {
try {
return fn.apply(null, args);
}
catch (err) {
return err;
}
}
export function throwIfNotDefer(d, message) {
if (!isDefer(d)) {
typeError(message || 'given value is not a defer');
}
}
export function throwIfNotError(err, message) {
if (!isError(err)) {
typeError(message || 'given value is not an Error');
}
}
export function throwIfNotFunction(fn, message) {
if (!isFunction(fn)) {
typeError(message || 'given value is not a function');
}
}
export function throwIfNotRPCEvent(event, message) {
if (!isRPCEvent(event)) {
typeError(message || 'given value is not an RPCEvent');
}
}
export function throwIfNotObject(obj, message) {
if (!isObject(obj)) {
typeError(message || 'given value is not an object');
}
}
export function typeError(message) {
throw createTypeError(message);
}
//# sourceMappingURL=utils.js.map