Skip to content

n-car/rpc-express-toolkit

Repository files navigation

RPC Express Toolkit

CI Coverage Status License npm version npm downloads node

Enterprise-ready JSON-RPC 2.0 toolkit for Express.js with simplified APIs, middleware, schema validation, batch support, and optional safe type disambiguation.

Quick Start

Installation

npm install rpc-express-toolkit
# or
yarn add rpc-express-toolkit

Requirements:

  • Node.js 18+ (uses globalThis.fetch)

Server

const express = require('express');
const { RpcEndpoint } = require('rpc-express-toolkit');

const app = express();
app.use(express.json()); // required

const context = { database: db, config };

const rpc = new RpcEndpoint(app, context);
rpc.addMethod('add', (req, ctx, params) => params.a + params.b);

app.listen(3000);

Client

const { RpcClient } = require('rpc-express-toolkit');
const client = new RpcClient('http://localhost:3000/api');
const sum = await client.call('add', { a: 1, b: 2 });

Safe Type Disambiguation (optional)

Safe type disambiguation is disabled by default for maximum JSON-RPC 2.0 compatibility. The library can show warnings when BigInt or Date values are serialized in standard mode. Enable safe serialization with safeEnabled: true to add safe prefixes (S: for strings, D: for dates), or suppress warnings with warnOnUnsafe: false. See README_ADVANCED.md#safe-serialization for details.

Minimal API

  • new RpcEndpoint(router, context, options?): create and attach a JSON-RPC endpoint.
  • rpc.addMethod(name, handlerOrConfig): register a method (function or { handler, schema }).
  • new RpcClient(baseUrl, headers?, options?): client for making calls.
  • client.call(method, params?): single call.
  • client.batch([...]): batch.
  • client.notify(method, params?): notification.

Safe Import (opt-in)

npm (proxy) safe preset

When you control both client and server and want safer type round-trips, import the safe preset. It enables safe serialization by default (and strict mode on the server):

// Server (safe preset)
const express = require('express');
const { createSafeEndpoint } = require('rpc-express-toolkit/safe');

const app = express();
app.use(express.json());

const rpc = createSafeEndpoint(app, {}, { endpoint: '/api' /* strictMode: true by default */ });

// Client (safe preset)
const { createSafeClient } = require('rpc-express-toolkit/safe');
const client = createSafeClient('http://localhost:3000/api');

This keeps JSON-RPC 2.0 compliance as default for the main entrypoint, while offering a convenient safe-mode import for projects that prefer explicit type disambiguation.

Alternative: npm proxy package

If you prefer a dedicated package name, you can install the thin proxy rpc-express-toolkit-safe which simply re-exports the safe preset:

npm install rpc-express-toolkit-safe
// Server
const express = require('express');
const { createSafeEndpoint } = require('rpc-express-toolkit-safe');
const app = express();
app.use(express.json());
const rpc = createSafeEndpoint(app, {}, { endpoint: '/api' });

// Client
const { createSafeClient } = require('rpc-express-toolkit-safe');
const client = createSafeClient('http://localhost:3000/api');

Introspection Methods

Enable introspection to expose metadata about registered methods via reserved __rpc.* methods:

const rpc = new RpcEndpoint(app, context, {
  enableIntrospection: true  // Enable __rpc.* methods
});

// Register methods with public schemas
rpc.addMethod('add', async (req, ctx, params) => {
  return params.a + params.b;
}, {
  schema: {
    type: 'object',
    properties: {
      a: { type: 'number' },
      b: { type: 'number' }
    },
    required: ['a', 'b']
  },
  exposeSchema: true,        // Make schema publicly queryable
  description: 'Add two numbers'
});

// Available introspection methods:
// __rpc.listMethods() → ["add", "multiply", ...]
// __rpc.describe({method: "add"}) → {name, schema, description}
// __rpc.describeAll() → [{name, schema, description}, ...]
// __rpc.version() → {toolkit, version, expressVersion, nodeVersion}
// __rpc.capabilities() → {safeMode, batch, introspection, ...}

// Client usage
const methods = await client.call('__rpc.listMethods');
const addInfo = await client.call('__rpc.describe', { method: 'add' });

Note: The introspection prefix is configurable via introspectionPrefix option (default: __rpc). User methods starting with this prefix are rejected to prevent conflicts.

Full Details

For advanced configuration, middleware, structured logging, safe serialization, error handling, and more, see README_ADVANCED.md.

🔗 Related Projects

Contributing

git clone https://github.com/n-car/rpc-express-toolkit.git
npm install
npm test
npm run lint

License

MIT. See LICENSE.