@ch1/rpc
Version:
JavaScript Remote Procedure Call (RPC)
83 lines • 2.89 kB
JavaScript
/**
* Functions related to creating and using remote objects
*/
import * as rpc from './remote-procedure';
import { createTypeError, isFunction, isDictionary, isObject, isRPCDefaultAsync, safeInvoke, } from './utils';
export function getFinalFunction(remote, fnName) {
const names = fnName.split('.').filter(Boolean);
// invalid function name case
if (names.length === 0) {
return createTypeError(`getFinalFunction: ${fnName} not found on remote`);
}
// "first level" case
if (names.length === 1) {
if (isFunction(remote[names[0]])) {
return remote[names[0]];
}
return createTypeError(`getFinalFunction: ${fnName} is not a function: ` +
typeof remote[names[0]]);
}
// invalid sub object case
if (!remote[names[0]]) {
return createTypeError(`getFinalFunction: ${names[0]} is not a ` +
'namespace (sub-object) on remote');
}
// sub object case
if (names.length === 2) {
return getFinalFunction(remote[names[0]], names[1]);
}
// deeper object case
return getFinalFunction(remote[names.shift()], names.join('.'));
}
/**
* Safely finds and executes a proxy for a remote procedure
*/
export function safeCall(c, fnName, args) {
const fn = getFinalFunction(c.remote, fnName);
if (!Array.isArray(args)) {
args = [];
}
if (fn instanceof Error) {
return fn;
}
return safeInvoke(fn, args);
}
export function create(c, callbacks, remoteDesc, remote, prefix) {
remoteDesc = remoteDesc || Object.create(null);
remote = remote || Object.create(null);
return Object.keys(remoteDesc).reduce((state, prop) => {
const desc = remoteDesc[prop];
prefix = prefix || '';
if (isDictionary(desc)) {
state[prop] = create(c, callbacks, desc, remote[prop], prop + '.');
}
else if (isRPCDefaultAsync(desc)) {
state[prop] = rpc.create(c, callbacks, prefix + prop, desc);
}
return state;
}, remote);
}
export function createRemoteDescFrom(c, remote, remoteDesc) {
remote = remote || Object.create(null);
remoteDesc = remoteDesc || Object.create(null);
const newRemoteDesc = Object.create(null);
/* tslint:disable forin */
for (let prop in remote) {
if (isObject(remote[prop])) {
let newDesc;
if (isDictionary(remoteDesc[prop])) {
newDesc = remoteDesc[prop];
}
else {
newDesc = Object.create(null);
}
newRemoteDesc[prop] = createRemoteDescFrom(c, remote[prop], newDesc);
}
if (isFunction(remote[prop])) {
const type = remoteDesc[prop] || c.defaultAsyncType;
newRemoteDesc[prop] = type;
}
}
return newRemoteDesc;
}
//# sourceMappingURL=remote.js.map