@shinka-rpc/core
v0.0.2
Published
Symmetric RPC bus. This page explains basic concepts only. [Documentation is here](https://shinka-rpc-js.readthedocs.io/latest/core/)
Maintainers
Readme
@shinka-rpc/core
Symmetric RPC bus. This page explains basic concepts only. Documentation is here
This package implements the main functionality of @shinka-rpc. Ironically the
core know how to do everything but it is made so abstract that as is unable to
do anything. So to make @shinka-rpc be able to do things, you have to pass the
transport -- commonly very small function, returning 2 functions: send and
close, and subscribing the bus instance to onMessage. Here you are able to
implement the custom one (or more) or use any already existing:
@shinka-rpc/browser-extension implements the RPC bus between the page and browser extension environment
TODO: @shinka-rpc/iframe implements the RPC bus between the main page and the page inside iframe
@shinka-rpc/dedicated-worker implements the RPC bus between the page and Worker
@shinka-rpc/shared-worker implements the RPC bus between the page and SharedWorker
@shinka-rpc/web-socket implements the RPC bus over the WebSocket
TODO: @shinka-rpc/webrtc-data implements the RPC bus over the RTCDataChannel
Also there are some default serializers available:
The main advantage of @shinka-rpc is in re-using of the same core with all
transports. And when you decided to build many RPC communication buses, your
bundle would contain only one core
Symmetricity
It means both server and client may register request and event handlers, and then send requests and events to each other, and both may initialize connections
request and event
Scopes are separated. The difference is that request requires for the
response and waits for it, and the event does not support response and
does not wait for any feedback from other side -- shoot and forget
Usage
There are 2 scenarios: server and client usage. The only difference is
server handles N clients. There are some strange cases: dedicated
Worker or
iframe.
Who is a server and client if each of them are alone? Simple answer -- both of
them are clients, it's OK to make RPC bus for client-client case
The first thing what we have to do is a bus initialization. I'll use as an
example @shinka-rpc/shared-worker package
client initialization
import { ClientBus, FactoryClient } from "@shinka-rpc/core";
import { SharedWorker2FactoryData } from "@shinka-rpc/shared-worker/client";
import serializer from "@shinka-rpc/serializer-json"; // for example
const factory: FactoryClient<ClientBus> = async (bus) =>
SharedWorker2FactoryData(
new SharedWorker(new URL("./worker.ts", import.meta.url)),
bus,
);
export const bus = new ClientBus({ factory, serializer });
bus.start();server initialization
// @ts-nocheck
declare let onconnect: (event: MessageEvent) => void;
import { ServerBus } from "@shinka-rpc/core";
import { SharedWorkerServer } from "@shinka-rpc/shared-worker/server";
import serializer from "@shinka-rpc/serializer-json"; // for example
export const server = new ServerBus({ serializer });
onconnect = SharedWorkerServer(server);Register event and request handlers
Both server and client provide the same API:
1-st handler arg:
anypayload. UseObjectandArrayto pass multiple args, and then unpack them2nd handler arg:
thisArg- In
clientcase it'sClientBusitself - In
servercase it'sCommonBus--client's representation
- In
server.onRequest("load-meta", async () => {
const response = await fetch("/meta.json", { cache: "no-store" });
return await response.json();
});
let token: string | null = null;
server.onDataEvent("set-token", ([newToken]: [string]) => {
token = newToken;
});IMPORTANT: request handler can NOT return
Promise.
If you need to something asyncronous, just use async function as a handler
Call registered event and request handlers
Both server and client provide the same API:
type Meta = {};
const loadMeta = () => bus.request<Meta>("load-meta"); // returns Promise<Meta>
const setToken = (token: string) => bus.event("set-token", [token]);