### Install RPC Anywhere via npm Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/demo/index.html This command installs the `rpc-anywhere` package, providing the necessary library for creating type-safe Remote Procedure Calls in your project. It's a prerequisite for setting up RPC communication. ```Bash npm i rpc-anywhere ``` -------------------------------- ### Set Up Symmetrical RPC with TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example illustrates a symmetrical RPC setup, enabling bidirectional communication and messaging between two parties. It defines a shared schema for both requests and messages, allowing one party to make requests and the other to listen for messages. The schema includes a 'hello' request and a 'goodbye' message. ```TypeScript // schema.ts type SymmetricalSchema = RPCSchema<{ requests: { hello: { params: { name: string }; response: string; }; }; messages: { goodbye: void; }; }>; // rpc-a.ts const rpcA = createRPC(/* ... */); rpcA.addMessageListener("goodbye", () => { console.log("Goodbye!"); }); // rpc-b.ts const rpcB = createRPC(/* ... */); const response = await rpcB.request.hello({ name: "world" }); console.log(response); // Hello, world! rpcB.send.goodbye(); ``` -------------------------------- ### Install RPC Anywhere with npm Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md Install the rpc-anywhere library using npm to add it to your project's dependencies. This command will fetch the package from the npm registry and save it in your `node_modules` folder. ```bash npm i rpc-anywhere ``` -------------------------------- ### Implement Client/Server RPC with TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example demonstrates setting up a basic client-server RPC communication using rpc-anywhere. It shows how to define a server-side request handler, create a server instance, and then connect a client to invoke remote methods. The server exposes a 'hello' method that takes a name and returns a greeting. ```TypeScript // server.ts const requestHandler = createRPCRequestHandler({ hello(name: string) { return `Hello, ${name}!`; }, }); export type ServerSchema = RPCSchema; const rpc = createServerRPC({ // ... requestHandler, }); // client.ts import { type ServerSchema } from "./server.js"; const rpc = createClientRPC(/* ... */).proxy.request; const response = await rpc.hello("world"); console.log(response); // Hello, world! ``` -------------------------------- ### Example: RPC Communication Between Iframe and Parent Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This example illustrates how to set up RPC communication between a parent window and an iframe using the dedicated transport functions. It demonstrates the asynchronous nature of transport creation and the importance of a matching `transportId` for reliable messaging. The parent waits for the iframe to load, and the iframe waits for an initialization message from the parent. ```TypeScript import { createIframeTransport } from "rpc-anywhere"; const iframeElement = document.getElementById("my-iframe") as HTMLIFrameElement; createIframeTransport(iframeElement, { transportId: "my-transport" }).then( (transport) => { const rpc = createRPC({ transport, // ... }); // ... }, ); ``` ```TypeScript import { createIframeParentTransport } from "rpc-anywhere"; createIframeParentTransport({ transportId: "my-transport" }).then( (transport) => { const rpc = createRPC({ transport, // ... }); // ... }, ); ``` -------------------------------- ### TypeScript: Initialize RPC with BroadcastChannel Transport Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This example demonstrates how to set up an RPC client using `rpc-anywhere` with a `BroadcastChannel`. It shows the basic configuration required to establish communication between different browsing contexts (e.g., tabs, windows, workers) that share the same broadcast channel name. ```TypeScript import { createTransportFromBroadcastChannel } from "rpc-anywhere"; const channel = new BroadcastChannel("my-channel"); const rpc = createRPC({ transport: createTransportFromBroadcastChannel(channel), // ... }); // ... ``` -------------------------------- ### TypeScript: Connect RPC via Browser Runtime Port Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This example demonstrates how to establish an RPC connection between a content script and a service worker using `browser.runtime.Port`. It shows the setup for both ends, creating a transport from the port and integrating it with `createRPC`. Users should manage port lifecycles and consider unique port names or `transportId` for clear communication. ```TypeScript import { createTransportFromBrowserRuntimePort } from "rpc-anywhere"; const port = browser.runtime.connect({ name: "my-rpc-port" }); const rpc = createRPC({ transport: createTransportFromBrowserRuntimePort(port), // ... }); // ... ``` ```TypeScript import { createTransportFromBrowserRuntimePort } from "rpc-anywhere"; browser.runtime.onConnect.addListener((port) => { if (port.name === "my-rpc-port") { const rpc = createRPC({ transport: createTransportFromBrowserRuntimePort(port), // ... }); // ... } }); ``` -------------------------------- ### TypeScript: Implement RPC with Web Workers Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This example demonstrates how to set up RPC communication between a parent context and a Web Worker. It shows the usage of `createWorkerTransport` in the parent to initiate the connection and `createWorkerParentTransport` within the worker to receive and respond to messages, establishing a full RPC channel. ```TypeScript import { createWorkerTransport } from "rpc-anywhere"; const worker = new Worker("worker.js"); const rpc = createRPC({ transport: createWorkerTransport(worker), // ... }); // ... ``` ```TypeScript import { createWorkerParentTransport } from "rpc-anywhere"; const rpc = createRPC({ transport: createWorkerParentTransport(), // ... }); // ... ``` -------------------------------- ### RPC Anywhere API Reference and Documentation Links Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This section provides links to the comprehensive documentation and API reference for RPC Anywhere. It includes guides on core RPC concepts, built-in transports, bridging transports, and creating custom transports, along with a link to the detailed TSDocs API reference for type definitions and method signatures. ```APIDOC Documentation:\n- RPC: ./docs/1-rpc.md\n- Built-in transports: ./docs/2-built-in-transports.md\n- Bridging transports: ./docs/3-bridging-transports.md\n- Creating a custom transport: ./docs/4-creating-a-custom-transport.md\n\nAPI Reference: https://tsdocs.dev/docs/rpc-anywhere/ ``` -------------------------------- ### TypeScript: Implementing Transport Bridges for RPC Communication Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/3-bridging-transports.md This TypeScript example demonstrates how to use `createRPC` at the endpoints (server and iframe) and `createTransportBridge` in intermediate layers (main and renderer scripts) to forward RPC messages. It shows the setup for a multi-hop connection involving WebSocket, Electron IPC, and Message Ports, ensuring seamless communication between the server and a nested iframe. ```typescript // server.ts const serverRPC = createRPC({ transport: createTransportFromWebSocket(webSocket), // ... }); // main.ts const bridge = createTransportBridge( createTransportFromWebSocket(webSocket), createTransportFromElectronIpcMain(ipcMain), ); bridge.start(); // renderer.ts createTransportBridge( createTransportFromElectronIpcRenderer(ipcRenderer), createTransportFromMessagePort(window, iframe.contentWindow), ); bridge.start(); // iframe.ts const iframeRPC = createRPC({ transport: createTransportFromMessagePort(window, window.parent), // ... }); ``` -------------------------------- ### Implement RPC in Iframe with TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This TypeScript example demonstrates setting up an RPC connection within an iframe using `rpc-anywhere`. It defines the iframe's schema, handles incoming requests from the parent, and sends messages. Key components include `createRPCRequestHandler` and `createIframeParentTransport` for communication. ```ts import { createIframeParentTransport, createRPC, createRPCRequestHandler, type RPCSchema, } from "rpc-anywhere"; // import the parent's (remote) schema import { type ParentSchema } from "./parent.js"; // handle incoming requests from the parent const requestHandler = createRPCRequestHandler({ /** Greet a given target. */ greet: ({ name, }: { /** The target of the greeting. */ name: string; }) => `Hello, ${name}!`, // respond to the parent }); // create the iframe's schema export type IframeSchema = RPCSchema< { messages: { buttonClicked: { /** The button that was clicked. */ button: string; }; }; }, // request types can be inferred from the handler typeof requestHandler >; async function main() { // create the iframe's RPC const rpc = createRPC({ // wait for a connection with the parent window and // pass the transport to our RPC transport: await createIframeParentTransport({ transportId: "my-rpc" }), // provide the request handler requestHandler, }); // send a message to the parent blueButton.addEventListener("click", () => { rpc.send.buttonClicked({ button: "blue" }); }); // listen for messages from the iframe rpc.addMessageListener("userLoggedIn", ({ name }) => { console.log(`The user "${name}" logged in`); }); } main(); ``` -------------------------------- ### Define Symmetrical RPC Schemas in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example shows how to define symmetrical RPC schemas where both endpoints handle the same requests and send the same messages. By omitting the second schema type parameter in `createRPC`, the single provided schema is interpreted as both the local and remote schema, simplifying setup for peer-to-peer or bidirectional communication. ```TypeScript // rpc-a.ts const rpcA = createRPC(/* ... */); // rpc-b.ts const rpcB = createRPC(/* ... */); ``` -------------------------------- ### Implement RPC in Parent Window with TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This TypeScript example shows how to establish an RPC connection from a parent window to an iframe using `rpc-anywhere`. It defines the parent's schema, connects via `createIframeTransport`, and uses the RPC proxy to make requests and send messages. This enables seamless cross-window communication. ```ts import { createIframeTransport, createRPC, type RPCSchema } from "rpc-anywhere"; // import the iframe's (remote) schema import { type IframeSchema } from "./iframe.js"; // create the parent window's schema export type ParentSchema = RPCSchema<{ messages: { userLoggedIn: { /** The user's name. */ name: string; }; }; }>; async function main() { // create the parent window's RPC const rpc = createRPC({ // wait for a connection with the iframe and // pass the transport to our RPC transport: await createIframeTransport( document.getElementById("my-iframe"), { transportId: "my-rpc" }, ), }); // use the proxy API as an alias ✨ const iframe = rpc.proxy; // make a request to the iframe const greeting = await iframe.request.greet({ name: "world" }); console.log(greeting); // Hello, world! // send a message to the iframe onUserLoggedIn((user) => iframe.send.userLoggedIn({ name: user.name })); // listen for messages from the iframe rpc.addMessageListener("buttonClicked", ({ button }) => { console.log(`The button "${button}" was clicked`); }); } main(); ``` -------------------------------- ### Make Basic RPC Requests in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example illustrates how to send requests to a remote endpoint using the `rpc.request` method. It shows that request parameters can be included or omitted based on the request's requirements. The method returns a promise that resolves with the response from the remote endpoint. ```ts const response = await rpc.request("requestName", { /* request parameters */ }); const response = await rpc.request("requestName"); ``` -------------------------------- ### Handle Empty RPC Schemas with EmptyRPCSchema in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example illustrates the use of `EmptyRPCSchema` for RPC instances that do not handle requests or send messages, creating a 'pure' client/server connection. It demonstrates how to define a remote schema and then use `createRPC` with `EmptyRPCSchema` for the local endpoint, ensuring proper type safety for one-way communication. ```TypeScript type RemoteSchema = RPCSchema<{ requests: { requestName: void; }; }>; // rpc-local.ts (client) const rpc = createRPC(/* ... */); rpc.request("requestName"); // rpc-remote.ts (server) const rpc = createRPC({ requestHandler: { requestName() { /* ... */ }, }, }); ``` -------------------------------- ### Define Flexible RPC Schemas in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This snippet demonstrates how to define highly flexible RPC schemas using `RPCSchema` in TypeScript. It provides examples for requests with optional parameters, no response, no parameters, or no parameters and no response. Additionally, it shows how to define messages with optional or no content, allowing for adaptable RPC interfaces. ```TypeScript type MySchema = RPCSchema<{ requests: { // request with optional parameters requestName: { params?: { direction: "up" | "down"; velocity?: number; }; response: string | number; }; // request with no response requestName: { params: string; }; // request with no parameters requestName: { response: [string, number]; }; // request with no parameters and no response requestName: void; }; messages: { // message with no content messageName: void; // message with optional content messageName?: { content?: string; }; }; }>; // schema with no requests type MySchema = RPCSchema<{ messages: { messageName: void; }; }>; // schema with no messages type MySchema = RPCSchema<{ requests: { requestName: void; }; }>; ``` -------------------------------- ### Initialize RPC with Browser Runtime Port Transport Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This example demonstrates how to initialize an RPC instance using `createTransportFromBrowserRuntimePort` for browser extension communication. It shows both direct initialization and lazily setting the transport on an existing RPC instance. This method facilitates communication between different parts of a browser extension, like content scripts and service workers. ```TypeScript import { createTransportFromBrowserRuntimePort } from "rpc-anywhere"; const port = browser.runtime.connect({ name: "my-rpc-port" }); const rpc = createRPC({ transport: createTransportFromBrowserRuntimePort(port), // ... }); // or const rpc = createRPC({ // ... }); rpc.setTransport(createTransportFromBrowserRuntimePort(port)); ``` -------------------------------- ### Listen for Incoming Messages in RPC Anywhere (TypeScript) Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This example illustrates how an RPC instance can listen for incoming messages using `addMessageListener`. It demonstrates defining a callback function that processes the received message data, which is strictly typed based on the defined schema, ensuring type safety for message content. ```ts // chef-rpc.ts chefRpc.addMessageListener("takingABreak", ({ duration, reason }) => { console.log( `The manager is taking a break for ${duration} minutes: ${reason}`, ); }); ``` -------------------------------- ### Handle Incoming RPC Requests in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This example demonstrates how to define a request handler within an RPC instance configuration. The `requestHandler` object maps method names to functions that process incoming requests and return responses, supporting both synchronous and asynchronous operations and ensuring type-safe handling of request parameters and return values. ```ts // chef-rpc.ts const chefRpc = createRPC({ // ... requestHandler: { cook({ recipe }) { return prepareDish(recipe, availableIngredients); }, }, }); // ... ``` -------------------------------- ### Set RPC Request Timeout in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This example shows how to configure the maximum time an RPC request will wait for a response using the `maxRequestTime` option in `createRPC`. The default timeout is 1000ms, and setting it to `Infinity` disables the timeout, though this should be used with caution. This helps prevent requests from hanging indefinitely. ```ts const rpc = createRPC({ // ... maxRequestTime: 5000, }); ``` -------------------------------- ### Integrate RPC Schemas into createRPC Instances in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md After declaring RPC schemas, they are applied to `createRPC` instances to establish type-safe communication. The `createRPC` function takes two type parameters: the local schema (this instance's capabilities) and the remote schema (the other endpoint's capabilities). This setup enables strong type-checking for both sending and receiving operations, even accommodating circular type imports for schemas. ```TypeScript import { createRPC } from "rpc-anywhere"; const rpc = createRPC({ // ... }); ``` ```TypeScript // rpc-a.ts import { type SchemaB } from "./rpc-b.js"; export type SchemaA = RPCSchema; const rpcA = createRPC(); // rpc-b.ts import { type SchemaA } from "./rpc-a.js"; export type SchemaB = RPCSchema; const rpcB = createRPC(); ``` -------------------------------- ### Create a Custom RPC Transport Function (Initial TypeScript) Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/4-creating-a-custom-transport.md This function demonstrates how to encapsulate a transport's creation, allowing for multiple instances with different configurations. It integrates with a fictional `ExampleChannel` to send and receive messages, but notably omits the `unregisterHandler` implementation, which can lead to resource leaks. ```typescript function createMyCustomTransport(channel: ExampleChannel): RPCTransport { let handler: MessageHandler | null = null; return { send(message) { channel.postMessage(message); }, registerHandler(handler) { channel.addMessageListener((message) => handler(message)); }, }; } ``` -------------------------------- ### Simplify Client/Server RPC with createClientRPC/createServerRPC in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This snippet demonstrates the simplified approach to creating client and server RPC instances using `createClientRPC` and `createServerRPC`. These helper functions automatically handle the local schema as empty, requiring only the remote (server) schema as a type parameter for convenience and cleaner code in typical client-server architectures. ```TypeScript // rpc-local.ts (client) const rpc = createClientRPC(/* ... */); await rpc.request("requestName"); // rpc-remote.ts (server) const rpc = createServerRPC({ requestHandler: { requestName() { /* ... */ }, }, }); ``` -------------------------------- ### Document RPC Schemas with JSDoc in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This snippet demonstrates how to document RPC schemas using JSDoc comments for requests, parameters, responses, messages, and their contents. These comments enhance code readability and provide rich IDE support, displaying documentation and types on hover for a better developer experience when interacting with RPC methods. ```TypeScript type MySchema = RPCSchema<{ requests: { /** * Move the car. * * @example * * ``` * const result = await rpc.request.move({ direction: "left", duration: 1000 }); * ``` */ move: { params: { /** * The direction of the movement. */ direction: "left" | "right"; /** * The total duration of the movement. */ duration: number; /** * The velocity of the car. * * @default 100 */ velocity?: number; }; response: { /** * The total distance traveled by the car. */ distance: number; /** * The final position of the car. */ position: number; }; }; }; }>; ``` ```TypeScript const { distance, position } = await rpc.request.move({ // ^ ^ ^ direction: "left", // ^ duration: 1000, // ^ velocity: 200, // ^ }); ``` -------------------------------- ### Configure RPC Transport in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This snippet demonstrates how to set up a transport for an RPC instance using `createRPC` or `setTransport`. It highlights that lazy setting makes the RPC unusable until the transport is configured and that built-in transports support hot-swapping, which custom transports can also implement by cleaning up resources. ```ts const rpc = createRPC({ transport: createTransportFromMessagePort(window, iframe.contentWindow), }); // or const rpc = createRPC(); rpc.setTransport(createTransportFromMessagePort(window, iframe.contentWindow)); ``` -------------------------------- ### RPC Anywhere Core API Reference Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This section outlines the core API for RPC Anywhere, including the main `createRPC` function and interfaces for defining RPC schemas, transports, and managing RPC communication. It provides a conceptual overview of how to interact with the library. ```APIDOC interface RPCSchema { // Define the structure of requests and messages // Example: // requests: { // myMethod: { // params: [param1: string, param2: number], // returns: boolean // } // }, // messages: { // myEvent: { // payload: string // } // } } interface Transport { // Represents the communication channel between endpoints. // Must implement methods for sending and receiving messages. send: (message: any) => void; onMessage: (handler: (message: any) => void) => void; // ... other transport-specific methods } interface RPCInstance { // Proxy API for making requests request: Schema['requests']; // Dynamically typed based on schema // Method to set or change the transport layer setTransport: (transport: Transport) => void; // Method to send messages (not requests expecting a response) send: Schema['messages']; // Dynamically typed based on schema // Method to register handlers for incoming requests onRequest: (handlers: { [K in keyof Schema['requests']]: (...args: Schema['requests'][K]['params']) => Schema['requests'][K]['returns'] }) => void; // Method to register handlers for incoming messages onMessage: (handlers: { [K in keyof Schema['messages']]: (payload: Schema['messages'][K]['payload']) => void }) => void; } /** * Creates a new RPC instance. * @param options - Configuration options for the RPC. * @param options.transport - (Optional) The initial transport layer for communication. * @param options.schema - (Optional) The schema definition for type safety. Can be inferred from handlers. * @returns A new RPC instance. */ declare function createRPC(options?: { transport?: Transport; schema?: Schema; // This is conceptual, schema is often inferred }): RPCInstance; ``` -------------------------------- ### Create RPC Instances with TypeScript in RPC Anywhere Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This snippet demonstrates how to create RPC instances using `createRPC` from the `rpc-anywhere` library. It shows how to pass local and remote schema types as type parameters, emphasizing the library's transport-agnostic nature which requires a specified transport for message exchange. ```ts import { createRPC } from "rpc-anywhere"; // chef-rpc.ts const chefRpc = createRPC({ transport: createRestaurantTransport(), }); // manager-rpc.ts const managerRpc = createRPC({ transport: createRestaurantTransport(), }); ``` -------------------------------- ### Define a Basic RPC Transport Object in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/4-creating-a-custom-transport.md This snippet illustrates the fundamental structure required for an RPC transport. It defines three essential methods: `send` for dispatching messages, `registerHandler` for setting a message callback, and `unregisterHandler` for cleanup. This object serves as the interface for any custom transport implementation. ```typescript const transport = { send(message) { // send the message }, registerHandler(handler) { // register the handler }, unregisterHandler() { // unregister the handler }, }; ``` -------------------------------- ### Iframe Transport API for Parent and Child Windows Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This section defines the API for creating transports between an iframe and its parent window. `createIframeTransport` is used in the parent, while `createIframeParentTransport` is used within the child iframe. Both functions return a Promise that resolves to an `RPCTransport` once the secure MessageChannel connection is established. ```APIDOC export async function createIframeTransport( iframe: HTMLIFrameElement, options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; targetOrigin?: string; // default: "*" }, ): Promise; export async function createIframeParentTransport(options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; }): Promise; ``` -------------------------------- ### Utilize RPC Request Proxy API in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md This snippet demonstrates the alternative request proxy API, allowing requests like `rpc.request.requestName`. It also introduces `requestProxy` as a cleaner alternative for improved TypeScript autocompletion. This API provides a more direct and type-safe way to invoke remote methods. ```ts const response = await rpc.request.requestName({ /* request parameters */ }); const chef = chefRPC.requestProxy; const dish = await chef.cook({ recipe: "rice" }); ``` -------------------------------- ### Make RPC Requests in TypeScript using RPC Anywhere Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This snippet illustrates two ways to make requests to a remote RPC instance: using the `.request()` method or the request proxy API. Both methods are functionally equivalent and allow sending structured parameters to a remote method, with the response being strictly typed based on the remote schema. ```ts // manager-rpc.ts // using ".request()" const dish = await managerRpc.request("cook", { recipe: "pizza" }); // using the request proxy API const dish = await managerRpc.request.cook({ recipe: "pizza" }); ``` -------------------------------- ### Listen for RPC Messages with `addMessageListener` in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md Messages are received by adding a listener using `addMessageListener`, which can target specific message names or all messages using the `*` wildcard. Listeners can be removed with `removeMessageListener`. This enables flexible message handling within RPC Anywhere. ```ts rpc.addMessageListener("messageName", (messageContent) => { /* handle the message */ }); ``` ```ts rpc.addMessageListener("*", (messageName, messageContent) => { /* handle the message */ }); ``` ```ts rpc.removeMessageListener("messageName", listener); rpc.removeMessageListener("*", listener); ``` -------------------------------- ### Utilize `proxy` Property for RPC Requests and Messages in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md RPC instances expose a `proxy` property, which consolidates `request` and `send` proxies for convenience. This alternative API simplifies calling requests and sending messages. It provides a more streamlined way to interact with the RPC instance. ```ts const rpc = createRPC(/* ... */).proxy; rpc.request.requestName(/* ... */); rpc.send.messageName(/* ... */); ``` -------------------------------- ### Declare RPC Schemas with RPCSchema in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md RPC schemas define the structure for requests an endpoint can respond to and messages it can send. Declared using `RPCSchema`, they provide type safety by specifying `requests` with `params` and `response` types, and `messages` with their content. This ensures clear communication contracts between RPC instances. ```TypeScript import { type RPCSchema } from "rpc-anywhere"; type MySchema = RPCSchema<{ requests: { requestName: { params: { /* request parameters */ }; response: { /* response content */ }; }; }; messages: { messageName: { /* message content */ }; }; }>; ``` -------------------------------- ### Define RPC Schemas in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This TypeScript snippet illustrates defining RPC schemas using `RPCSchema` from `rpc-anywhere`. Schemas specify the structure of requests (with parameters and responses) and messages exchanged between endpoints. This is crucial for type safety and clear communication contracts in RPC applications. ```ts import { type RPCSchema } from "rpc-anywhere"; type ChefSchema = RPCSchema<{ requests: { cook: { params: { recipe: Recipe }; response: Dish; }; }; messages: { kitchenOpened: void; kitchenClosed: { reason: string }; }; }>; type ManagerSchema = RPCSchema<{ requests: { getIngredients: { params: { neededIngredients: IngredientList }; response: Ingredient[]; }; }; messages: { shiftStarted: void; shiftEnded: void; takingABreak: { reason: string; duration: number }; }; }>; ``` -------------------------------- ### APIDOC: `createTransportFromBroadcastChannel` Function Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md API documentation for creating an RPC transport using a `BroadcastChannel`. This function enables communication between different browsing contexts (e.g., windows, tabs, iframes, workers) sharing the same channel name. It supports `transportId` and `filter` options, but users should be aware of the multi-endpoint nature of broadcast channels and exercise caution with request-response patterns. ```TypeScript export function createTransportFromBroadcastChannel( channel: BroadcastChannel, options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; }, ): RPCTransport; ``` -------------------------------- ### Send RPC Messages with `send` Method in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md Messages in RPC Anywhere are sent using the `send` method, allowing optional content. An alternative message proxy API is also available for convenience. This method facilitates communication between RPC instances. ```ts rpc.send("messageName", { /* message content */ }); ``` ```ts rpc.send("messageName"); ``` ```ts rpc.send.messageName({ /* message content */ }); // or rpc.sendProxy.messageName({ /* message content */ }); ``` -------------------------------- ### Handle RPC Requests with `requestHandler` in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md Requests in RPC Anywhere are managed via the `requestHandler` option of `createRPC`. This can be defined as an object for type safety and fallback support, or as a function for dynamic handling. All handlers can be asynchronous. ```ts const rpc = createRPC({ // ... requestHandler: { requestName(/* request parameters */) { /* handle the request */ return /* response */; }, // or async requestName(/* request parameters */) { await doSomething(); /* handle the request */ return /* response */; }, // fallback handler _(method, params) { /* handle requests that don't have a handler defined (not type-safe) */ return /* response */; }, // or async _(method, params) { await doSomething(); /* handle requests that don't have a handler defined (not type-safe) */ return /* response */; } } }); ``` ```ts const rpc = createRPC({ // ... requestHandler(method, params) { /* handle the request */ return /* response */; }, // or async requestHandler(method, params) { await doSomething(); /* handle the request */ return /* response */; } }); ``` ```ts const rpc = createRPC(); rpc.setRequestHandler(/* ... */); ``` -------------------------------- ### APIDOC: `createWorkerTransport` and `createWorkerParentTransport` Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md API documentation for functions that create RPC transports between a Web Worker and its parent context. `createWorkerTransport` is used from the parent to communicate with the worker, while `createWorkerParentTransport` is used within the worker to communicate with its parent. Both functions accept optional `transportId` and `filter` parameters for message handling. ```TypeScript export function createWorkerTransport( worker: Worker, options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; }, ): RPCTransport; ``` ```TypeScript export function createWorkerParentTransport( worker: Worker, options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; }, ): RPCTransport; ``` -------------------------------- ### Implement `unregisterHandler` in a Custom RPC Transport (TypeScript) Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/4-creating-a-custom-transport.md This refined function provides a complete custom RPC transport implementation, including a proper `unregisterHandler` method. By storing the message listener in a local variable, it ensures that the handler can be correctly removed when the transport is no longer needed, preventing memory leaks and ensuring clean resource management. ```typescript function createMyCustomTransport(channel: ExampleChannel): RPCTransport { let listener: ExampleMessageListener | null = null; return { send(message) { channel.postMessage(message); }, registerHandler(handler) { listener = (message) => handler(message); channel.addMessageListener(listener); }, unregisterHandler() { if (listener) channel.removeMessageListener(listener); }, }; } ``` -------------------------------- ### Browser Extension Runtime Port Transport API Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This API defines `createTransportFromBrowserRuntimePort`, a function used to create an RPC transport from a browser runtime port. This is crucial for enabling communication within browser extensions, such as between content scripts and background scripts. It supports an optional `transportId` for message filtering. ```APIDOC function createTransportFromBrowserRuntimePort( port: Browser.Runtime.Port | Chrome.runtime.Port, options?: { transportId?: string | number; filter?: (message: any, port: Browser.Runtime.Port) => boolean; }, ): RPCTransport; ``` -------------------------------- ### APIDOC: createTransportFromMessagePort Function Reference Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/2-built-in-transports.md This section provides the API reference for `createTransportFromMessagePort`, a low-level function in `rpc-anywhere` for creating RPC transports from various message port interfaces. It details the `port` parameter, which accepts `MessagePort`, `Window`, `Worker`, `ServiceWorkerContainer`, or `BroadcastChannel`, and the optional `options` for `transportId`, `filter`, and `remotePort` to manage complex communication scenarios. ```APIDOC export function createTransportFromMessagePort( port: | MessagePort | Window | Worker | ServiceWorkerContainer | BroadcastChannel, options?: { transportId?: string | number; filter?: (event: MessageEvent) => boolean; remotePort?: | MessagePort | Window | Worker | ServiceWorker | Client | BroadcastChannel; }, ): RPCTransport; ``` -------------------------------- ### Send Messages Between RPC Instances in RPC Anywhere (TypeScript) Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/README.md This snippet shows how to send a message from one RPC instance to another using the `send` proxy API. It demonstrates passing structured data that is strictly typed according to the remote schema, ensuring correct message payload and enabling seamless communication. ```ts // manager-rpc.ts managerRpc.send.takingABreak({ duration: 30, reason: "lunch" }); ``` -------------------------------- ### Infer RPC Schema from Request Handler in TypeScript Source: https://github.com/daniguardiola/rpc-anywhere/blob/main/docs/1-rpc.md RPC Anywhere allows inferring the schema type directly from the request handler, reducing redundancy. This is achieved by creating the handler with `createRPCRequestHandler` and then using `typeof` to pass its type as a schema parameter. This method streamlines schema definition for requests. ```ts const myRequestHandler = createRPCRequestHandler({ myRequest({ a, b }: { a: number; b: string }) { return { c: a > 0 && b.length > 0 }; } }); type Schema = RPCSchema< { messages: { myMessage: void } }, typeof myRequestHandler >; const rpc = createRPC({ // ... requestHandler: myRequestHandler }); ``` ```ts type Schema = RPCSchema; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.