npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@emkodev/json-rpc

v1.0.2

Published

JSON-RPC 2.0 specification compliant TypeScript implementation with full type safety

Readme

JSON-RPC 2.0 TypeScript Implementation

JSR JSR Score JSON-RPC 2.0 License: MIT TypeScript Zero Dependencies

A specification-compliant JSON-RPC 2.0 implementation for TypeScript/Deno with full type safety and zero dependencies.

Features

  • JSON-RPC 2.0 Spec Compliant - Follows the specification
  • 🔒 Type Safe - Full TypeScript support with strict typing
  • 🚀 Zero Dependencies - Pure TypeScript implementation
  • 🧪 Thoroughly Tested - Comprehensive test suite
  • 📦 Multiple Transports - HTTP, WebSocket, and custom transport support
  • High Performance - Efficient message handling and validation
  • 🔄 Batch Support - Full batch request/response handling
  • 📢 Notifications - Complete notification support
  • 🛡️ Error Handling - Proper JSON-RPC error codes and handling
  • ⚙️ Configurable - Flexible server and client options

Why Choose This Implementation?

  • Zero Dependencies - No external packages to manage or audit
  • TypeScript Native - Written from the ground up in TypeScript
  • Multiple Transports - Built-in HTTP and WebSocket support
  • Spec Compliant - Follows JSON-RPC 2.0 specification
  • Batch Support - Full batch request and response handling

Installation

# Deno
deno add @emkodev/json-rpc

# Node.js
npx jsr add @emkodev/json-rpc

Quick Start

Server

import { JsonRpcServer } from "@emkodev/json-rpc";

const server = new JsonRpcServer();

// Register methods
server.method("add", (params: [number, number]) => {
  return params[0] + params[1];
});

server.method("greet", (params: { name: string }) => {
  return `Hello, ${params.name}!`;
});

// Register notifications
server.notification("log", (params: { message: string }) => {
  console.log(params.message);
});

// Handle requests
const request = JSON.stringify({
  jsonrpc: "2.0",
  method: "add",
  params: [2, 3],
  id: 1,
});

const response = await server.handle(request);
console.log(response); // {"jsonrpc":"2.0","result":5,"id":1}

Client

import { HttpTransport, JsonRpcClient } from "@emkodev/json-rpc";

// HTTP transport
const transport = new HttpTransport("http://localhost:8080/rpc");
const client = new JsonRpcClient(transport);

// Method calls
const result = await client.call<number>("add", [2, 3]);
console.log(result); // 5

// Notifications
await client.notify("log", { message: "Hello World" });

// Batch requests
const responses = await client.batch([
  { type: "call", method: "add", params: [1, 2], id: 1 },
  { type: "call", method: "multiply", params: [3, 4], id: 2 },
  { type: "notify", method: "log", params: ["batch test"] },
]);

API Reference

JsonRpcServer

const server = new JsonRpcServer({
  allowNotifications: true,  // Enable notifications (default: true)
  allowBatch: true,          // Enable batch requests (default: true)
  maxBatchSize: 100,         // Maximum batch size (default: 100)
  timeout: 30000             // Request timeout in ms (default: 30000)
});

// Register method handler
server.method<TParams, TResult>(name: string, handler: JsonRpcMethodHandler<TParams, TResult>);

// Register notification handler
server.notification<TParams>(name: string, handler: JsonRpcNotificationHandler<TParams>);

// Handle JSON-RPC message
await server.handle(jsonString: string, context?: JsonRpcContext): Promise<string | null>;

// Process parsed message
await server.process(message: unknown, context?: JsonRpcContext): Promise<JsonRpcResponse | JsonRpcBatchResponse | null>;

JsonRpcClient

const client = new JsonRpcClient(transport, {
  timeout: 30000,    // Request timeout in ms
  retries: 3,        // Number of retries
  retryDelay: 1000,  // Delay between retries
  headers: {}        // Custom headers
});

// Call method
await client.call<TResult, TParams>(method: string, params?: TParams, id?: JsonRpcId): Promise<TResult>;

// Send notification
await client.notify<TParams>(method: string, params?: TParams): Promise<void>;

// Batch requests
await client.batch(requests: BatchRequestItem[]): Promise<JsonRpcResponse[]>;

// Close connection
await client.close(): Promise<void>;

Transports

HTTP Transport

import { HttpTransport } from "@emkodev/json-rpc";

const transport = new HttpTransport("http://localhost:8080/rpc", {
  "Authorization": "Bearer token",
  "Content-Type": "application/json",
});

WebSocket Transport

import { WebSocketTransport } from "@emkodev/json-rpc";

const transport = new WebSocketTransport("ws://localhost:8080/rpc");

Custom Transport

import { JsonRpcTransport } from "@emkodev/json-rpc";

class CustomTransport implements JsonRpcTransport {
  async send(message: string): Promise<string> {
    // Your transport implementation
    return response;
  }

  async close?(): Promise<void> {
    // Optional cleanup
  }
}

Error Handling

The library provides proper JSON-RPC 2.0 error handling:

import { JsonRpcErrorCode, JsonRpcServerError } from "@emkodev/json-rpc";

server.method("divide", (params: [number, number]) => {
  if (params[1] === 0) {
    throw JsonRpcServerError.invalidParams("Division by zero");
  }
  return params[0] / params[1];
});

// Client error handling
try {
  await client.call("divide", [10, 0]);
} catch (error) {
  if (error instanceof JsonRpcClientError) {
    console.log(error.error.code); // -32602
    console.log(error.error.message); // "Invalid params"
  }
}

Standard Error Codes

  • -32700 Parse error
  • -32600 Invalid Request
  • -32601 Method not found
  • -32602 Invalid params
  • -32603 Internal error
  • -32000 to -32099 Server error range

Batch Processing

// Server automatically handles batch requests
const batchRequest = [
  { jsonrpc: "2.0", method: "add", params: [1, 2], id: 1 },
  { jsonrpc: "2.0", method: "subtract", params: [5, 3], id: 2 },
  { jsonrpc: "2.0", method: "notify", params: ["test"] }, // notification
];

const responses = await server.handle(JSON.stringify(batchRequest));
// Returns array of responses (no response for notifications)

// Client batch requests
const responses = await client.batch([
  { type: "call", method: "add", params: [1, 2], id: 1 },
  { type: "call", method: "subtract", params: [5, 3], id: 2 },
  { type: "notify", method: "log", params: ["test"] },
]);

Type Safety

Full TypeScript support with generic type parameters:

interface User {
  id: number;
  name: string;
  email: string;
}

// Typed method handler
server.method<{ id: number }, User>("getUser", async (params) => {
  // params is typed as { id: number }
  return await findUser(params.id); // return type is User
});

// Typed client call
const user = await client.call<User, { id: number }>("getUser", { id: 123 });
// user is typed as User

Testing

Run the test suite:

# Run all tests
deno task test

# Run specific test suites
deno task test:types
deno task test:server
deno task test:client
deno task test:integration

# Watch mode
deno task test:watch

# Coverage report
deno task test:coverage
deno task coverage

Development

# Format code
deno task fmt

# Lint code
deno task lint

# Type check
deno task check

Specification Compliance

This implementation follows the JSON-RPC 2.0 Specification:

  • ✅ Request/Response/Notification formats
  • ✅ Batch processing
  • ✅ Error handling with standard codes
  • ✅ Reserved method names ("rpc." prefix)
  • ✅ ID validation (string, number, null)
  • ✅ Parameter passing (positional arrays or named objects)
  • ✅ Version validation ("2.0" exactly)

License

MIT License - see LICENSE file for details.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Project Status

Version 1.0.0 - Stable Release

Spec Compliant - Follows JSON-RPC 2.0 specification requirements ✅ TypeScript Native - Written from the ground up in TypeScript ✅ Zero Dependencies - No external dependencies to manage ✅ Comprehensive Tests - Extensive test suite with passing tests ✅ Type Safe - Full TypeScript support with strict mode

Changelog

v1.0.0

  • Stable release
  • JSON-RPC 2.0 specification compliance
  • Full TypeScript support with strict mode
  • HTTP and WebSocket transports
  • Comprehensive test suite
  • Zero dependencies