Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,21 @@ jobs:
- name: Run tests
run: npm test

- name: Check package contents
run: npm pack --dry-run
package:
runs-on: ubuntu-latest
needs: test

steps:
- uses: actions/checkout@v4

- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Test packed package
run: npm run package-test
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,87 @@ This package is the framework-agnostic Node.js core for the RPC Toolkit ecosyste
npm install rpc-node-toolkit
```

Requirements:

- Node.js 18+

## Compatibility

`rpc-node-toolkit` is tested with Node.js 18, 20, and 22. Its CommonJS
runtime supports both CommonJS and Node.js ESM consumers. See
[Compatibility](docs/COMPATIBILITY.md) for the runtime, module, and packaged
consumer matrices.

## TypeScript

The package supports TypeScript ESM/NodeNext and CommonJS consumers. Both
forms are tested with `strict: true`, `skipLibCheck: false`, and
`esModuleInterop: false` against the tarball produced by `npm pack`.

Install the declarations used by these examples:

```bash
npm install --save-dev typescript @types/node
```

ESM/NodeNext (`package.json` contains `"type": "module"`):

```typescript
import RpcEndpoint, {
RpcEndpoint as NamedRpcEndpoint,
RpcClient,
type RpcEndpointOptions,
} from 'rpc-node-toolkit';
import {
RpcSafeClient,
RpcSafeEndpoint,
} from 'rpc-node-toolkit/safe';

const options: RpcEndpointOptions = { safeEnabled: false };
const rpc = new RpcEndpoint({}, options);
const namedRpc = new NamedRpcEndpoint({}, options);
const client = new RpcClient('http://localhost:3000/api');
const safeRpc = new RpcSafeEndpoint({});
const safeClient = new RpcSafeClient('http://localhost:3000/api');
```

Use these compiler options for the ESM example:

```json
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"skipLibCheck": false,
"esModuleInterop": false,
"types": ["node"],
"ignoreDeprecations": "6.0"
}
}
```

`ignoreDeprecations` only acknowledges TypeScript 6's deprecation notice for
the explicitly tested `esModuleInterop: false` setting.

CommonJS TypeScript (`.cts` with NodeNext or Node16 resolution):

```typescript
import RpcEndpoint = require('rpc-node-toolkit');
import Safe = require('rpc-node-toolkit/safe');

const options: RpcEndpoint.RpcEndpointOptions = { safeEnabled: false };
const rpc = new RpcEndpoint({}, options);
const namedRpc = new RpcEndpoint.RpcEndpoint({}, options);
const client = new RpcEndpoint.RpcClient('http://localhost:3000/api');
const safeRpc = new Safe.RpcSafeEndpoint({});
const safeClient = new Safe.RpcSafeClient('http://localhost:3000/api');
```

The root CommonJS import remains the constructable `RpcEndpoint` export while
also exposing its named API. The `/safe` subpath exposes the safe classes and
the root utilities it re-exports at runtime.

## Current Scope

- Framework-independent `RpcEndpoint`
Expand Down Expand Up @@ -131,10 +212,16 @@ npm run example:safe
```bash
npm install
npm test
npm run typecheck
npm run package-test
```

The package test suite covers the core endpoint, HTTP handler, schema validation, batch requests, notifications, and Safe Mode behavior. The ecosystem compatibility matrix also covers `rpc-node-toolkit` as an HTTP Safe Mode server.

`npm run package-test` validates TypeScript and Node.js consumers against the
tarball produced by `npm pack`, including the package export map and the files
that would be published.

## Related Projects

- [rpc-express-toolkit](https://github.com/n-car/rpc-express-toolkit)
Expand Down
69 changes: 69 additions & 0 deletions docs/COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Compatibility

`rpc-node-toolkit` is a framework-agnostic Node.js library for JSON-RPC 2.0
servers and clients.

## Runtime Matrix

| Runtime | Status |
| --- | --- |
| Node.js 18.x | Supported and CI tested |
| Node.js 20.x | Supported and CI tested |
| Node.js 22.x | Supported and CI tested |

The package requires Node.js 18 or newer. The GitHub Actions matrix runs the
runtime test suite across Node.js 18, 20, and 22.

## Module And TypeScript Compatibility

The published package remains CommonJS at runtime and supports both CommonJS
and Node.js ESM consumers. Its TypeScript declarations model the constructable
CommonJS root export and the named properties exposed by the root and `/safe`
entrypoints.

| Consumer | Module setup | Verified imports | Validation |
| --- | --- | --- | --- |
| TypeScript ESM | `"type": "module"` with `module` and `moduleResolution` set to `NodeNext` | Root default and named imports, public root types, and named `/safe` imports | TypeScript 6, `strict: true`, `skipLibCheck: false`, `esModuleInterop: false` |
| TypeScript CommonJS | `.cts` with NodeNext resolution | `import = require()` for the root and `/safe`, including namespace properties | TypeScript 6, `strict: true`, `skipLibCheck: false`, `esModuleInterop: false` |
| Node.js ESM | `.mjs` | Root default and named imports plus named `/safe` imports | Runtime smoke test |
| Node.js CommonJS | `.cjs` | `require()` for the root and `/safe`, including root default identity | Runtime smoke test |

The TypeScript ESM consumer covers `RpcEndpoint` as both the default and a
named import, `RpcClient`, `RpcEndpointOptions`, `RpcSafeEndpoint`, and
`RpcSafeClient`. The CommonJS consumer covers the constructable root export,
`RpcEndpoint.RpcEndpoint`, `RpcEndpoint.RpcClient`,
`Safe.RpcSafeEndpoint`, and `Safe.RpcSafeClient`.

TypeScript applications should install `@types/node` because the public server
API references types from `node:http`.

The TypeScript 6 fixtures set `ignoreDeprecations: "6.0"` solely to
acknowledge the compiler's deprecation notice for the deliberately explicit
`esModuleInterop: false` test setting.

### Packaged Consumer Validation

`npm run package-test` builds a tarball with `npm pack`, installs that tarball
into isolated consumer fixtures, and runs the full module and TypeScript matrix
above. This verifies the published `exports` map, included files, declaration
resolution, module extensions, and runtime format instead of importing the
repository sources directly.

The same validation checks the packed artifact with `publint --strict` and
`@arethetypeswrong/cli` for both the root and `/safe` entrypoints.

Package validation runs in a dedicated Node.js 20 CI job and as part of
`prepublishOnly`, so declaration or packaging regressions block publication.

## Compatibility Coverage

The runtime tests cover:

- core endpoint calls;
- plain `node:http` handling;
- method schema validation;
- batch requests and notifications;
- Safe Mode serialization and HTTP behavior.

The isolated packaged consumers separately cover module resolution, runtime
exports, and TypeScript declaration compatibility.
Loading
Loading