Experimental Typed RPC Support
Starting with the 0.6.0 release, we are experimentally introducing support for Typed RPC.
When dealing with a single Port that requires RPC definition, we encounter a problem related to the programming paradigm. It's necessary to define Request
and Response
messages such as:
export type IpcDefinition = {
a2b: {
callFoo: {
input: string;
};
};
b2a: {
callFooCallback: {
result: string;
};
};
};
In the case where an RPC call needs to be encapsulated, the API might look like this:
function rpcCall(request: { input: string; }): Promise<{ result: string; }>;
Consequently, to associate a callback function, it becomes a requirement to include a CallbackId
at the application layer for every RPC method:
export type IpcDefinition = {
a2b: {
callFoo: {
input: string;
+ callbackId: string;
};
};
b2a: {
callFooCallback: {
result: string;
+ callbackId: string;
};
};
};
Unrpc
is provided to address this issue, enabling support for Typed RPC starting from the protocol layer:
// "parentPort" is a Port defined based on Unport in the previous example.
const parent = new Unrpc(parentPort);
// Implementing an RPC method.
parent.implement('getParentInfo', request => ({
id: 'parent',
from: request.user,
}));
The implementation on the child
side is as follows:
// "parentPort" is a Port also defined based on Unport.
const child = new Unrpc(childPort);
const response = await child.call('getParentInfo', { user: "child" }); // => { id: "parent", from: "child" }
The types are defined as such:
import { Unport } from 'unport';
export type Definition = {
parent2child: {
getParentInfo__callback: {
content: string;
};
};
child2parent: {
getParentInfo: {
user: string;
};
};
};
export type ChildPort = Unport<Definition, 'child'>;
export type ParentPort = Unport<Definition, 'parent'>;
In comparison to Unport, the only new concept to grasp is that the RPC response message key must end with __callback
. Other than that, no additional changes are necessary! Unrpc
also offers comprehensive type inference based on this convention; for instance, you won't be able to implement an RPC method that is meant to serve as a response.
Note
You can find the full code example here: child-process-rpc.