### Example of SimpleJSONRPCMethod Usage Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md This example shows how to define and use a SimpleJSONRPCMethod with custom server parameters for user ID and database access. ```typescript import { SimpleJSONRPCMethod } from "json-rpc-2.0"; type MyServerParams = { userId: string; db: Database }; const myMethod: SimpleJSONRPCMethod = (params, { userId, db }) => { return db.getUserName(userId); }; server.addMethod("getUsername", myMethod); ``` -------------------------------- ### Basic JSON-RPC Client Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Demonstrates how to initialize a JSONRPCClient and make a request and notification. The client requires a function to send JSON-RPC requests. ```javascript import { JSONRPCClient } from "json-rpc-2.0"; // JSONRPCClient needs to know how to send a JSON-RPC request. // Tell it by passing a function to its constructor. The function must take a JSON-RPC request and send it. const client = new JSONRPCClient((jsonRPCRequest) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { if (response.status === 200) { // Use client.receive when you received a JSON-RPC response. return response .json() .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); } else if (jsonRPCRequest.id !== undefined) { return Promise.reject(new Error(response.statusText)); } }) ); // Use client.request to make a JSON-RPC request call. // The function returns a promise of the result. client .request("echo", { text: "Hello, World!" }) .then((result) => console.log(result)); // Use client.notify to make a JSON-RPC notification call. // By definition, JSON-RPC notification does not respond. client.notify("log", { message: "Hello, World!" }); ``` -------------------------------- ### Basic HTTP Server Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server.md Demonstrates how to create a basic JSON-RPC 2.0 server using Express.js, add methods, and handle incoming requests. ```APIDOC ## Basic HTTP Server This example shows how to set up a simple HTTP server that handles JSON-RPC 2.0 requests. ### Server Initialization ```typescript import express from "express"; import { JSONRPCServer } from "json-rpc-2.0"; const server = new JSONRPCServer(); // Add methods to the server server.addMethod("echo", ({ text }) => text); server.addMethod("add", ({ x, y }) => x + y); const app = express(); app.use(express.json()); // Handle POST requests to the /json-rpc endpoint app.post("/json-rpc", (req, res) => { server.receive(req.body).then((response) => { if (response) { res.json(response); } else { // No response means it was a notification res.sendStatus(204); } }); }); app.listen(3000, () => { console.log("Server listening on port 3000"); }); ``` ``` -------------------------------- ### Minimal JSON-RPC 2.0 Client Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Instantiate a JSONRPCClient and make a request. You need to provide your own send logic for the client. ```typescript const client = new JSONRPCClient((req) => Promise.resolve() // Your send logic ); const result = await client.request("echo", { text: "hello" }); ``` -------------------------------- ### JSONRPCParams Usage Examples Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Illustrates the flexibility of the JSONRPCParams type by showing examples of an object, an array, and a string being used as parameters. ```typescript import { JSONRPCParams } from "json-rpc-2.0"; const params1: JSONRPCParams = { name: "John", age: 30 }; const params2: JSONRPCParams = [1, 2, 3]; const params3: JSONRPCParams = "hello"; ``` -------------------------------- ### Example of JSONRPCServerMiddleware Usage Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md This example implements a logging middleware that logs the method being called and its response result before passing control to the next handler in the chain. ```typescript import { JSONRPCServerMiddleware } from "json-rpc-2.0"; const loggingMiddleware: JSONRPCServerMiddleware = (next, request, serverParams) => { console.log(`Calling ${request.method}`); return next(request, serverParams).then((response) => { console.log(`Response for ${request.method}:`, response?.result); return response; }); }; server.applyMiddleware(loggingMiddleware); ``` -------------------------------- ### WebSocket Bidirectional Communication Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Illustrates setting up a WebSocket connection for bidirectional JSON-RPC communication. This example defines a WebSocketPeer class that manages both the server and client aspects of the JSON-RPC protocol over a WebSocket. ```typescript import { JSONRPCServerAndClient, JSONRPCServer, JSONRPCClient } from "json-rpc-2.0"; class WebSocketPeer { private serverAndClient: JSONRPCServerAndClient; constructor(private webSocket: WebSocket) { this.serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { if (this.webSocket.readyState === WebSocket.OPEN) { this.webSocket.send(JSON.stringify(request)); } return Promise.resolve(); }) ); this.setupMethods(); this.setupListeners(); } private setupMethods() { this.serverAndClient.addMethod("ping", () => "pong"); this.serverAndClient.addMethod("add", ({ x, y }) => x + y); } private setupListeners() { this.webSocket.onmessage = (event) => { const payload = JSON.parse(event.data); this.serverAndClient.receiveAndSend(payload, {}, {}); }; this.webSocket.onclose = () => { this.serverAndClient.rejectAllPendingRequests("Connection closed"); }; } public async remotePing() { return this.serverAndClient.request("ping"); } public async remoteAdd(x: number, y: number) { return this.serverAndClient.request("add", { x, y }); } } ``` -------------------------------- ### Minimal JSON-RPC 2.0 Server Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Instantiate a JSONRPCServer and add a method. This snippet demonstrates how to handle an incoming request and generate a response. ```typescript const server = new JSONRPCServer(); server.addMethod("echo", ({ text }) => text); const response = await server.receive({ jsonrpc: "2.0", id: 1, method: "echo", params: { text: "hello" } }); ``` -------------------------------- ### Example of JSONRPCMethod Usage Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md This example demonstrates creating an advanced JSONRPCMethod that returns a custom response, controlling the JSON-RPC version, ID, and result. ```typescript import { JSONRPCMethod, JSONRPC } from "json-rpc-2.0"; const advancedMethod: JSONRPCMethod = (request, serverParams) => { return Promise.resolve({ jsonrpc: JSONRPC, id: request.id, result: "custom response", }); }; server.addMethodAdvanced("custom", advancedMethod); ``` -------------------------------- ### JSONRPCSuccessResponse Construction Examples Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Illustrates manual creation of a JSONRPCSuccessResponse and the use of a helper function 'createJSONRPCSuccessResponse' for generating success responses. ```typescript import { JSONRPCSuccessResponse, createJSONRPCSuccessResponse } from "json-rpc-2.0"; // Manual construction const response: JSONRPCSuccessResponse = { jsonrpc: "2.0", id: 1, result: { sum: 8 }, }; // Using helper const response2 = createJSONRPCSuccessResponse(1, [1, 2, 3]); ``` -------------------------------- ### JSONRPCRequest Construction Examples Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Shows how to manually construct a JSONRPCRequest object and how to use a helper function 'createJSONRPCRequest' for simpler creation. ```typescript import { JSONRPCRequest, createJSONRPCRequest } from "json-rpc-2.0"; // Manual construction const request: JSONRPCRequest = { jsonrpc: "2.0", id: 1, method: "add", params: { x: 5, y: 3 }, }; // Using helper const request2 = createJSONRPCRequest(1, "echo", { text: "hello" }); ``` -------------------------------- ### Basic HTTP Server Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server.md Set up a basic HTTP server using Express to handle JSON-RPC 2.0 requests. This involves defining methods and routing POST requests to the server's receive method. ```typescript import express from "express"; import { JSONRPCServer } from "json-rpc-2.0"; const server = new JSONRPCServer(); server.addMethod("echo", ({ text }) => text); server.addMethod("add", ({ x, y }) => x + y); const app = express(); app.use(express.json()); app.post("/json-rpc", (req, res) => { server.receive(req.body).then((response) => { if (response) { res.json(response); } else { res.sendStatus(204); } }); }); app.listen(3000); ``` -------------------------------- ### Implement UUID CreateID Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Example implementation of the CreateID type using the 'uuid' library to generate v4 UUIDs as request IDs. Ensure the 'uuid' library is installed. ```typescript import { CreateID } from "json-rpc-2.0"; import uuid from "uuid"; const uuidGenerator: CreateID = () => uuid.v4(); ``` -------------------------------- ### JSONRPCErrorResponse Construction Examples Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Shows manual construction of a JSONRPCErrorResponse and usage of a helper function 'createJSONRPCErrorResponse' for creating error responses. ```typescript import { JSONRPCErrorResponse, createJSONRPCErrorResponse } from "json-rpc-2.0"; // Manual construction const response: JSONRPCErrorResponse = { jsonrpc: "2.0", id: 1, error: { code: -32601, message: "Method not found", }, }; // Using helper const response2 = createJSONRPCErrorResponse( 1, -32602, "Invalid params", { invalidField: "email" } ); ``` -------------------------------- ### Basic JSON-RPC 2.0 Server Setup with Express Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Sets up an Express server to handle JSON-RPC 2.0 requests. It defines 'echo' and 'log' methods and processes incoming requests using `server.receive`. ```javascript const express = require("express"); const bodyParser = require("body-parser"); const { JSONRPCServer } = require("json-rpc-2.0"); const server = new JSONRPCServer(); // First parameter is a method name. // Second parameter is a method itself. // A method takes JSON-RPC params and returns a result. // It can also return a promise of the result. server.addMethod("echo", ({ text }) => text); server.addMethod("log", ({ message }) => console.log(message)); const app = express(); app.use(bodyParser.json()); app.post("/json-rpc", (req, res) => { const jsonRPCRequest = req.body; // server.receive takes a JSON-RPC request and returns a promise of a JSON-RPC response. // It can also receive an array of requests, in which case it may return an array of responses. // Alternatively, you can use server.receiveJSON, which takes JSON string as is (in this case req.body). server.receive(jsonRPCRequest).then((jsonRPCResponse) => { if (jsonRPCResponse) { res.json(jsonRPCResponse); } else { // If response is absent, it was a JSON-RPC notification method. // Respond with no content status (204). res.sendStatus(204); } }); }); app.listen(80); ``` -------------------------------- ### Typed JSON-RPC Server and Client Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Demonstrates setting up typed JSON-RPC servers and clients in TypeScript. Define your method signatures using a type alias to ensure type safety for method names, parameters, and return types. This prevents common errors like typos or incorrect argument/return types. ```typescript import { JSONRPCClient, JSONRPCServer, JSONRPCServerAndClient, TypedJSONRPCClient, TypedJSONRPCServer, TypedJSONRPCServerAndClient, } from "json-rpc-2.0"; // Use `type` instead of `interface`. In TypeScript, interface can be exnteded, // so the type checker considers the possibility of the interface being extended, // resulting in an error. // Reference: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces type Methods = { echo(params: { message: string }): string; sum(params: { x: number; y: number }): number; }; const server: TypedJSONRPCServer = new JSONRPCServer(/* ... */); const client: TypedJSONRPCClient = new JSONRPCClient(/* ... */); // Types are infered from the Methods type server.addMethod("echo", ({ message }) => message); server.addMethod("sum", ({ x, y }) => x + y); // These result in type error // server.addMethod("ech0", ({ message }) => message); // typo in method name // server.addMethod("echo", ({ messagE }) => messagE); // typo in param name // server.addMethod("echo", ({ message }) => 123); // return type must be string client .request("echo", { message: "hello" }) .then((result) => console.log(result)); client.request("sum", { x: 1, y: 2 }).then((result) => console.log(result)); // These result in type error // client.request("ech0", { message: "hello" }); // typo in method name // client.request("echo", { messagE: "hello" }); // typo in param name // client.request("echo", { message: 123 }); // message param must be string // client // .request("echo", { message: "hello" }) // .then((result: number) => console.log(result)); // return type must be string // The same rule applies to TypedJSONRPCServerAndClient type ServerAMethods = { echo(params: { message: string }): string; }; type ServerBMethods = { sum(params: { x: number; y: number }): number; }; const serverAndClientA: TypedJSONRPCServerAndClient< ServerAMethods, ServerBMethods > = new JSONRPCServerAndClient(/* ... */); const serverAndClientB: TypedJSONRPCServerAndClient< ServerBMethods, ServerAMethods > = new JSONRPCServerAndClient(/* ... */); serverAndClientA.addMethod("echo", ({ message }) => message); serverAndClientB.addMethod("sum", ({ x, y }) => x + y); serverAndClientA .request("sum", { x: 1, y: 2 }) .then((result) => console.log(result)); serverAndClientB .request("echo", { message: "hello" }) .then((result) => console.log(result)); ``` -------------------------------- ### Type-Safe JSON-RPC 2.0 Server and Client Setup Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Define methods for type safety and set up typed server and client instances. This enhances code maintainability and reduces runtime errors. ```typescript type Methods = { echo(params: { text: string }): string }; const server: TypedJSONRPCServer = new JSONRPCServer(); const client: TypedJSONRPCClient = new JSONRPCClient(/* ... */); ``` -------------------------------- ### JSONRPCError Usage Example Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Demonstrates the creation of a JSONRPCError object with a specific error code, message, and additional data payload. ```typescript import { JSONRPCError } from "json-rpc-2.0"; const error: JSONRPCError = { code: -32602, message: "Invalid parameters", data: { missingFields: ["name", "email"] }, }; ``` -------------------------------- ### JSONRPC Request with Version Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Example of constructing a JSON-RPC request object, ensuring the 'jsonrpc' field is set to the defined JSONRPC version. ```typescript import { JSONRPC } from "json-rpc-2.0"; const request = { jsonrpc: JSONRPC, id: 1, method: "echo", params: { text: "hello" }, }; ``` -------------------------------- ### JSONRPCClient Transport Functions Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Examples of providing send functions for different transport protocols when creating a JSONRPCClient. This demonstrates the protocol-agnostic nature of the library. ```typescript new JSONRPCClient((req) => fetch(...)) ``` ```typescript new JSONRPCClient((req) => webSocket.send(JSON.stringify(req))) ``` ```typescript new JSONRPCClient((req) => customTransport.send(req)) ``` -------------------------------- ### Bidirectional JSON-RPC Message Handling with WebSocket Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md This example demonstrates setting up a `JSONRPCServerAndClient` to handle messages over a WebSocket connection. It shows how to process incoming JSON-RPC payloads, send responses, and manage connection closures. ```typescript const webSocket = new WebSocket("ws://localhost:8080"); const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { webSocket.send(JSON.stringify(request)); return Promise.resolve(); }) ); webSocket.onmessage = (event) => { const payload = JSON.parse(event.data); serverAndClient.receiveAndSend(payload, {}, {}); }; webSocket.onclose = (event) => { serverAndClient.rejectAllPendingRequests( `Connection closed: ${event.reason}` ); }; ``` -------------------------------- ### Implement HTTP SendRequest Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Example implementation of the SendRequest type for sending JSON-RPC requests over HTTP using fetch. It includes custom client parameters for authentication tokens. ```typescript import { SendRequest } from "json-rpc-2.0"; interface AuthParams { token: string; } const httpSend: SendRequest = (payload, { token }) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, }, body: JSON.stringify(payload), }).then((response) => response.json()); ``` -------------------------------- ### JSONRPCID Type Usage Example Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/types.md Demonstrates the usage of the JSONRPCID type by creating an array containing various valid ID types: number, string, and null. ```typescript import { JSONRPCID } from "json-rpc-2.0"; const ids: JSONRPCID[] = [1, "request-uuid", null]; ``` -------------------------------- ### Create and Use JSONRPCServerAndClient Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Combine server and client functionality for bidirectional communication. This setup is useful for scenarios like WebSockets where both parties send and receive requests. Use `addMethod` to register server-side methods and `request` for client-side calls. ```typescript import { JSONRPCServerAndClient, JSONRPCServer, JSONRPCClient } from "json-rpc-2.0"; const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { webSocket.send(JSON.stringify(request)); }) ); webSocket.onmessage = (event) => { serverAndClient.receiveAndSend(JSON.parse(event.data), {}, {}); }; serverAndClient.addMethod("echo", ({ text }) => text); await serverAndClient.request("remoteMethod", { arg: "value" }); ``` -------------------------------- ### Handle MethodNotFound on Server Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/errors.md This example shows the server-side behavior when a client attempts to call a non-existent method, resulting in a MethodNotFound error (-32601). Notifications without an ID do not trigger this error response. ```typescript const server = new JSONRPCServer(); server.addMethod("echo", ({ text }) => text); // Method "unknown" is not registered server.receive({ jsonrpc: "2.0", id: 1, method: "unknown", params: {}, }).then((response) => { // response.error.code === -32601 // response.error.message === "Method not found" }); ``` -------------------------------- ### Build Project with npm Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Run this command to build the project using npm. ```bash npm run build ``` -------------------------------- ### Test Project with npm Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Run this command to execute the project's tests using npm. ```bash npm test ``` -------------------------------- ### JSONRPCClient Initialization and Request with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-client.md Demonstrates how to initialize the JSONRPCClient with custom parameters for authentication and how to make a request using these parameters. The client is configured to send an Authorization header with a Bearer token. ```APIDOC ## Initialize JSONRPCClient with Authentication ### Description Initializes a JSONRPCClient that includes an authentication token in the request headers. This is useful for securing API endpoints. ### Usage ```typescript interface AuthToken { token: string; } const client = new JSONRPCClient( (jsonRPCRequest, { token }) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { if (response.status === 200) { return response .json() .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); } else if (jsonRPCRequest.id !== undefined) { return Promise.reject(new Error(response.statusText)); } }) ); // Example of making a request with authentication parameters client.request("echo", { text: "Hello" }, { token: "my-token" }); ``` ### Type Parameters - `ClientParams` (default: `void`) — Type of custom parameters passed to the send function and request methods. In this example, `AuthToken` is used. ### Parameters for Client Initialization - `send` function: A function that takes the JSON RPC request and client parameters, and returns a Promise. - `clientParams`: An object containing client-specific parameters, such as authentication tokens. ``` -------------------------------- ### Simple HTTP RPC with JSON-RPC 2.0 Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/README.md Demonstrates setting up a JSON-RPC 2.0 server and client for simple HTTP communication. The client sends requests to a server endpoint and processes responses. Ensure the server is running at the specified URL. ```typescript import { JSONRPCServer, JSONRPCClient } from "json-rpc-2.0"; // Server const server = new JSONRPCServer(); server.addMethod("add", ({ x, y }) => x + y); // Client const client = new JSONRPCClient((request) => fetch("http://localhost/rpc", { method: "POST", body: JSON.stringify(request) }) .then(r => r.json()) .then(response => client.receive(response)) ); // Use const result = await client.request("add", { x: 5, y: 3 }); // => 8 ``` -------------------------------- ### Throw JSONRPCErrorException with No Data Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/errors.md A simple example of throwing a JSONRPCErrorException with only a message and an error code, without any additional custom data. ```typescript throw new JSONRPCErrorException("Resource not found", -32000); ``` -------------------------------- ### Peer-to-Peer with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Demonstrates setting up a peer-to-peer JSON-RPC connection with authentication. This includes defining context and authentication interfaces, applying a server-side authentication middleware, and handling incoming messages with peer context. ```typescript interface PeerContext { peerId: string; authenticated: boolean; } interface ClientAuth { token: string; } const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request, { token }) => { webSocket.send(JSON.stringify(request)); return Promise.resolve(); }) ); // Server-side: handle incoming requests from peer const authMiddleware = (next, request, serverParams) => { if (!serverParams.authenticated) { return Promise.resolve({ jsonrpc: "2.0", id: request.id, error: { code: -32700, message: "Peer not authenticated" }, }); } return next(request, serverParams); }; serverAndClient.applyServerMiddleware(authMiddleware); serverAndClient.addMethod("getInfo", ({ type }, { peerId }) => ({ peerId, timestamp: Date.now(), type, })); // Client-side: send requests to peer webSocket.onmessage = (event) => { const peerContext: PeerContext = { peerId: extractPeerID(event), authenticated: true, }; serverAndClient.receiveAndSend( JSON.parse(event.data), peerContext, { token: myAuthToken } ); }; ``` -------------------------------- ### Custom Error Listener to Suppress Logging Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Example of configuring an empty error listener to completely suppress any error logging from the JSONRPCServer. ```typescript const server = new JSONRPCServer({ errorListener: () => { // Silent }, }); ``` -------------------------------- ### Create and Use JSONRPCServer Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Set up a JSONRPCServer to handle incoming requests. Register methods using `addMethod` and process requests by calling the `receive` method with the request object. ```typescript import { JSONRPCServer } from "json-rpc-2.0"; const server = new JSONRPCServer(); server.addMethod("add", ({ x, y }) => x + y); const response = await server.receive({ jsonrpc: "2.0", id: 1, method: "add", params: { x: 5, y: 3 }, }); // => { jsonrpc: "2.0", id: 1, result: 8 } ``` -------------------------------- ### Typed Configuration with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Demonstrates typed JSON-RPC server and client configurations, including passing authentication tokens in client requests and enforcing authorization on server methods. ```typescript interface UserContext { userId: string; role: "admin" | "user"; token: string; } interface AuthParams { token: string; } const server = new JSONRPCServer(); const client = new JSONRPCClient((request, { token }) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", "authorization": `Bearer ${token}`, }, body: JSON.stringify(request), }).then((response) => response.json()) .then((response) => client.receive(response)) ); // Server method injection server.addMethod("getProfile", ({ userId }, { userId: currentUserId }) => { if (userId !== currentUserId) { throw new JSONRPCErrorException("Unauthorized", -32700); } return { id: currentUserId, role: "user" }; }); // Client auth usage client.request("getProfile", { userId: "123" }, { token: userToken }); ``` -------------------------------- ### Server with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server.md Illustrates how to configure the JSON-RPC server to handle authenticated requests by injecting a custom request context. ```APIDOC ## With Authentication This example demonstrates how to add authentication to your JSON-RPC server by providing a custom context to method calls. ### Request Context Definition ```typescript interface RequestContext { userId: string; userRole: string; } // Initialize server with custom context type const server = new JSONRPCServer(); // Method that uses the context server.addMethod( "getProfile", ({ userId }, { userId: currentUserId }) => { // Example authorization check if (userId !== currentUserId) { throw new JSONRPCErrorException("Unauthorized", -32700); } return { id: userId, name: "User" }; } ); // Express route to handle requests app.post("/json-rpc", (req, res) => { // Extract context from request (e.g., headers, session) const context: RequestContext = { userId: extractUserID(req), // Assume extractUserID is defined elsewhere userRole: extractUserRole(req), // Assume extractUserRole is defined elsewhere }; server.receive(req.body, context).then((response) => { if (response) { res.json(response); } else { res.sendStatus(204); } }); }); ``` ``` -------------------------------- ### Custom Error Listener for Conditional Development Logging Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Example of a custom error listener that logs detailed errors to the console during development but logs only the message in production. ```typescript const server = new JSONRPCServer({ errorListener: (message, data) => { if (process.env.NODE_ENV === "development") { console.error(`[JSON-RPC Error] ${message}`, data); } else { console.error(message); } }, }); ``` -------------------------------- ### Instantiate JSONRPCServerAndClient with WebSocket Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Demonstrates initializing JSONRPCServerAndClient with a JSONRPCServer and JSONRPCClient that sends requests over a WebSocket. Includes a custom error listener. ```typescript import { JSONRPCServerAndClient, JSONRPCServer, JSONRPCClient } from "json-rpc-2.0"; const webSocket = new WebSocket("ws://localhost:8080"); const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { webSocket.send(JSON.stringify(request)); return Promise.resolve(); }), { errorListener: (message, data) => { console.error("JSON-RPC Error:", message, data); }, } ); ``` -------------------------------- ### Handle InternalError on Server Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/errors.md This server-side example triggers an InternalError (-32603) when a method successfully processes but fails to generate a response for a request that expected one (e.g., by returning undefined). ```typescript server.addMethodAdvanced("broken", (request) => { // Returns nothing (undefined) for a request with an ID return Promise.resolve(undefined); }); server.receive({ jsonrpc: "2.0", id: 1, method: "broken", }).then((response) => { // response.error.code === -32603 // response.error.message === "Internal error" }); ``` -------------------------------- ### JSONRPCServer Constructor Options Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Illustrates how to configure the JSONRPCServer with custom options during instantiation. The `errorListener` option allows for custom error handling. ```typescript new JSONRPCServer({ errorListener: (message: string, data: unknown): void => { // Listen to error here. By default, it will use console.warn to log errors. }, }); ``` -------------------------------- ### Server-side InvalidParams Exception Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/errors.md This server implementation example shows how to throw a custom InvalidParams error (-32602) when method parameters do not meet the expected criteria. This is not automatically generated by the library. ```typescript import { JSONRPCErrorException, JSONRPCErrorCode } from "json-rpc-2.0"; server.addMethod("validateEmail", ({ email }) => { if (!isValidEmail(email)) { throw new JSONRPCErrorException( "Invalid email format", JSONRPCErrorCode.InvalidParams, { field: "email", value: email } ); } return { valid: true }; }); ``` -------------------------------- ### Custom Error Listener for External Logging Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Example of configuring a custom error listener to send errors to an external logging service and an error tracking service like Sentry. ```typescript const server = new JSONRPCServer({ errorListener: (message, data) => { logger.error(message, { context: data }); sentryClient.captureException(data); }, }); ``` -------------------------------- ### JSON-RPC Client with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Shows how to configure a JSONRPCClient to include authentication tokens in requests. Custom parameters can be passed during request initiation. ```typescript interface AuthToken { token: string; } const client = new JSONRPCClient( // It can also take a custom parameter as the second parameter. (jsonRPCRequest, { token }) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { // ... }) ); // Pass the custom params as the third argument. client.request("echo", { text: "Hello, World!" }, { token: "foo's token" }); client.notify("log", { message: "Hello, World!" }, { token: "foo's token" }); ``` -------------------------------- ### Initialize JSONRPCServer Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server.md Instantiate the JSONRPCServer with default or custom configurations. The errorListener option allows for custom error handling during method execution. ```typescript import { JSONRPCServer } from "json-rpc-2.0"; // Default configuration const server = new JSONRPCServer(); // With custom error listener const server = new JSONRPCServer({ errorListener: (message, data) => { console.error(`[JSON-RPC Error] ${message}`, data); // Send to external logging service logService.error(message, data); }, }); ``` -------------------------------- ### Basic Error Handling with Promise.reject Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Demonstrates how to reject a promise to signal an error on the server and how the client receives this error. ```APIDOC ## Basic Error Handling with Promise.reject ### Description This method demonstrates how to reject a promise to signal an error on the server. The client-side promise will be rejected with an Error object containing the same message. ### Method `server.addMethod` ### Endpoint N/A (Method invocation) ### Parameters N/A ### Request Example ```javascript server.addMethod("fail", () => Promise.reject(new Error("This is an error message.")) ); ``` ### Response #### Success Response N/A (This method is designed to fail) #### Response Example ```javascript client.request("fail").then( () => console.log("This does not get called"), (error) => console.error(error.message) // Outputs "This is an error message." ); ``` ``` -------------------------------- ### Custom JSONRPCServer Error Mapping Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Provides an example of customizing the server's error mapping logic to handle specific custom error types and map them to appropriate JSON-RPC error responses. ```typescript server.mapErrorToJSONRPCErrorResponse = (id, error) => { // Custom error mapping logic let code = 0; let message = "Unknown error"; let data; if (error instanceof CustomValidationError) { code = -32602; message = "Validation error"; data = { validationErrors: error.errors }; } else if (error instanceof CustomAuthError) { code = -32700; message = "Authentication failed"; } else if (error instanceof JSONRPCErrorException) { code = error.code; message = error.message; data = error.data; } return { jsonrpc: "2.0", id, error: { code, message, data }, }; }; ``` -------------------------------- ### JSONRPCServer Constructor Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server.md Initializes a new JSONRPCServer instance. It can be configured with an optional error listener for handling errors during method execution. ```APIDOC ## JSONRPCServer Constructor ### Description Initializes a new JSONRPCServer instance. It can be configured with an optional error listener for handling errors during method execution. ### Signature ```typescript constructor(options?: JSONRPCServerOptions) ``` ### Parameters #### Options - **options** (`JSONRPCServerOptions`) - Optional - Configuration object. - **errorListener** (`ErrorListener`) - Optional - Custom error handler function called when errors occur during method execution. Defaults to `console.warn`. ### Returns `JSONRPCServer` - An instance of the JSONRPCServer. ### Example ```typescript import { JSONRPCServer } from "json-rpc-2.0"; // Default configuration const server = new JSONRPCServer(); // With custom error listener const serverWithOptions = new JSONRPCServer({ errorListener: (message, data) => { console.error(`[JSON-RPC Error] ${message}`, data); // logService.error(message, data); }, }); ``` ``` -------------------------------- ### Create and Use JSONRPCClient Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Instantiate a JSONRPCClient to make requests to a JSON-RPC server. The client requires a callback function to handle sending requests and processing responses. Use the `request` method for standard calls. ```typescript import { JSONRPCClient } from "json-rpc-2.0"; const client = new JSONRPCClient((request) => fetch("http://localhost/json-rpc", { method: "POST", body: JSON.stringify(request), headers: { "content-type": "application/json" }, }).then((r) => r.json()).then((response) => client.receive(response)) ); await client.request("add", { x: 5, y: 3 }); // => 8 ``` -------------------------------- ### JSON-RPC 2.0 Notification Example Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/errors.md Demonstrates sending a notification without an 'id' field. The server will not send a response, even if an error occurs during processing. Errors are typically handled via an error listener. ```typescript const notification = { jsonrpc: "2.0", method: "logEvent", params: { event: "user-login" }, // No id field }; server.receive(notification).then((response) => { // response is null, even if the method throws or doesn't exist // The error is logged via errorListener if applicable }); ``` -------------------------------- ### Bidirectional WebSocket RPC with JSON-RPC 2.0 Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/README.md Illustrates bidirectional communication using JSON-RPC 2.0 over WebSockets. This setup allows both the server and client to send and receive messages. The `receiveAndSend` method handles incoming messages from the WebSocket. ```typescript const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { webSocket.send(JSON.stringify(request)); }) ); serverAndClient.addMethod("ping", () => "pong"); webSocket.onmessage = (event) => { serverAndClient.receiveAndSend(JSON.parse(event.data), {}, {}); }; ``` -------------------------------- ### JSONRPCClient Constructor Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-client.md Initializes a new JSONRPCClient instance. It requires a function to send requests and optionally accepts a custom ID generation function. ```APIDOC ## JSONRPCClient Constructor ### Description Initializes a new JSONRPCClient instance. It requires a function to send requests and optionally accepts a custom ID generation function. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **_send** (`SendRequest`): Required - Function that sends JSON-RPC requests. Must accept the payload and optional client parameters. Returns `PromiseLike` or `void`. - **createID** (`CreateID`): Optional - Custom function to generate request IDs. If not provided, uses auto-incrementing numeric IDs starting from 0. ### Request Example ```typescript import { JSONRPCClient } from "json-rpc-2.0"; // Basic HTTP client const client = new JSONRPCClient((jsonRPCRequest) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { if (response.status === 200) { return response .json() .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); } else if (jsonRPCRequest.id !== undefined) { return Promise.reject(new Error(response.statusText)); } }) ); // With custom ID generator const client = new JSONRPCClient( (jsonRPCRequest) => fetch(/* ... */), () => generateUniqueID() ); ``` ### Response #### Success Response Returns a `JSONRPCClient` instance. #### Response Example None ``` -------------------------------- ### JSONRPCClient Initialization with Custom ID Generation Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-client.md Shows how to initialize the JSONRPCClient with a custom function for generating unique request IDs, ensuring that each request has a distinct identifier. ```APIDOC ## Initialize JSONRPCClient with Custom ID Generation ### Description Configures the JSONRPCClient to use a custom function for generating unique IDs for each JSON RPC request. This is useful when the default ID generation is not suitable. ### Usage ```typescript import uuid from "uuid"; const client = new JSONRPCClient( (request) => fetch(/* ... */), () => uuid.v4() ); ``` ### Parameters for Client Initialization - `send` function: A function that handles sending the JSON RPC request. - `idGenerator`: A function that returns a unique ID for each request. In this example, `uuid.v4()` is used. ``` -------------------------------- ### Instantiate JSONRPCClient with Basic HTTP Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-client.md Create a JSONRPCClient instance for basic HTTP communication. The send function handles sending JSON-RPC requests via fetch and receiving responses. ```typescript import { JSONRPCClient } from "json-rpc-2.0"; // Basic HTTP client const client = new JSONRPCClient((jsonRPCRequest) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { if (response.status === 200) { return response .json() .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); } else if (jsonRPCRequest.id !== undefined) { return Promise.reject(new Error(response.statusText)); } }) ); ``` -------------------------------- ### Bidirectional Communication with Logging Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/configuration.md Sets up a bidirectional JSON-RPC server and client using WebSockets, with integrated logging for both sending requests and handling errors. ```typescript const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer({ errorListener: (message, data) => { logger.error("[Server]", message, data); }, }), new JSONRPCClient((request) => { logger.debug("[Client] Sending request", { method: request.method, id: request.id }); webSocket.send(JSON.stringify(request)); return Promise.resolve(); }), { errorListener: (message, data) => { logger.error("[Bidirectional]", message, data); }, } ); ``` -------------------------------- ### Server-Initiated Notifications Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Shows how to implement server-initiated notifications to a remote client. This involves adding methods for subscription management and using the `notify` method to send updates to the client when specific events occur. ```typescript serverAndClient.addMethod("subscribe", ({ topic }) => { // Register subscription server-side subscriptionManager.add(topic); // Send notifications to remote client subscriptionManager.on(topic, (data) => { serverAndClient.notify("onUpdate", { topic, data }); }); return { subscribed: true }; }); // Also handle updates the client sends to us serverAndClient.addMethod("unsubscribe", ({ topic }) => { subscriptionManager.remove(topic); return { unsubscribed: true }; }); ``` -------------------------------- ### Register Simple Method Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Use `addMethod` to register a simple function that accepts parameters and server parameters. This is suitable for straightforward method implementations. ```typescript serverAndClient.addMethod("sum", ({ x, y }) => x + y); serverAndClient.addMethod("getUserData", ({ id }, { userId }) => { return { id, name: `User ${id}` }; }); ``` -------------------------------- ### Configure JSONRPC Server Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/INDEX.md Set up a JSONRPC server with custom error handling. The error listener logs errors, and a custom mapper can format error responses. ```typescript const server = new JSONRPCServer({ errorListener: (message, data) => { // Log errors to external service logger.error(message, data); }, }); // Customize error responses server.mapErrorToJSONRPCErrorResponse = (id, error) => { return { jsonrpc: "2.0", id, error: { code: error.code || -32603, message: error.message, }, }; }; ``` -------------------------------- ### JSONRPCClient with Authentication Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-client.md Demonstrates how to configure the JSONRPCClient to include authentication tokens in request headers. This is useful for securing API endpoints. ```typescript interface AuthToken { token: string; } const client = new JSONRPCClient( (jsonRPCRequest, { token }) => fetch("http://localhost/json-rpc", { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, }, body: JSON.stringify(jsonRPCRequest), }).then((response) => { if (response.status === 200) { return response .json() .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); } else if (jsonRPCRequest.id !== undefined) { return Promise.reject(new Error(response.statusText)); } }) ); client.request("echo", { text: "Hello" }, { token: "my-token" }); ``` -------------------------------- ### JSONRPCServerAndClient Constructor Source: https://github.com/shogowada/json-rpc-2.0/blob/main/_autodocs/api-reference-server-and-client.md Initializes a new instance of JSONRPCServerAndClient, combining server and client capabilities for unified communication. It accepts server and client instances, along with optional configuration for error handling. ```APIDOC ## Constructor ```typescript constructor( server: JSONRPCServer, client: JSONRPCClient, options?: JSONRPCServerAndClientOptions ) ``` ### Parameters - `server` (JSONRPCServer) - Required - Server instance for handling incoming requests - `client` (JSONRPCClient) - Required - Client instance for sending outgoing requests - `options` (JSONRPCServerAndClientOptions) - Optional - Configuration object with optional `errorListener` - `options.errorListener` (ErrorListener) - Optional - Custom error handler for invalid messages ### Returns `JSONRPCServerAndClient` instance ### Example ```typescript import { JSONRPCServerAndClient, JSONRPCServer, JSONRPCClient } from "json-rpc-2.0"; const webSocket = new WebSocket("ws://localhost:8080"); const serverAndClient = new JSONRPCServerAndClient( new JSONRPCServer(), new JSONRPCClient((request) => { webSocket.send(JSON.stringify(request)); return Promise.resolve(); }), { errorListener: (message, data) => { console.error("JSON-RPC Error:", message, data); }, } ); ``` ``` -------------------------------- ### JSONRPCServerAndClient Constructor Options Source: https://github.com/shogowada/json-rpc-2.0/blob/main/README.md Illustrates optional configuration for the JSONRPCServerAndClient constructor, specifically for listening to error messages. ```typescript new JSONRPCServerAndClient(server, client, { errorListener: (message: string, data: unknown): void => { // Listen to error here. By default, it will use console.warn to log errors. }, }); ```