v4.x: Node.js 18+ v5.0: Node.js 22+
Node 18 reached end-of-life in April 2025 and Node 20 in April 2026. v5.0 requires Node 22 (Active LTS, EOL April 2027) or later.
node --version # Should be >= 22.0.0There are no API-level breaking changes between v4.x and v5.0. All existing code targeting v4.x will work without modification.
- Node.js 22+ required (drops EOL Node 18 and 20)
- Built with TypeScript 6
- esbuild-based build pipeline — faster, smaller outputs, no more dual
tsccompilation
Version 3.0 is a complete rewrite switching from HTTP/axios to WebSocket-based communication. This enables real-time updates and full throttle control.
v2.x:
const client = new JmriClient('http', 'jmri.local', 12080);v3.x:
const client = new JmriClient({
host: 'jmri.local',
port: 12080
});Changes:
- Constructor now takes an options object
- No
protocolparameter (always uses WebSocket) - Added
autoConnectoption (default: true) - Added reconnection and heartbeat configuration
v2.x:
const response = await client.getPower();
console.log(response.data); // axios response objectv3.x:
const powerState = await client.getPower();
console.log(powerState); // Direct value (PowerState enum)Changes:
- Methods return data directly instead of axios response objects
- No more
.dataproperty on responses - Power state is now a
PowerStateenum (UNKNOWN=0, ON=2, OFF=4)
v2.x:
await client.setPower(true); // boolean
await client.setPower(false);v3.x:
await client.setPower(PowerState.ON); // enum
await client.setPower(PowerState.OFF);
// Or use convenience methods:
await client.powerOn();
await client.powerOff();v3.x introduces an event-driven pattern for real-time updates:
client.on('connected', () => console.log('Connected!'));
client.on('disconnected', (reason) => console.log('Disconnected:', reason));
client.on('power:changed', (state) => console.log('Power:', state));
client.on('throttle:updated', (id, data) => console.log('Throttle:', id));v2.x had commented-out throttle methods. v3.x has full throttle support:
// Acquire throttle
const throttleId = await client.acquireThrottle({ address: 3 });
// Control speed (0.0 to 1.0)
await client.setThrottleSpeed(throttleId, 0.5);
// Control direction
await client.setThrottleDirection(throttleId, true); // forward
// Control functions F0-F28
await client.setThrottleFunction(throttleId, 'F0', true);
// Release when done
await client.releaseThrottle(throttleId);v2.x: Node.js 14+ v3.x: Node.js 18+
axios- Replaced with native WebSocketxml2json- No longer needed (JSON protocol only)
const client = new JmriClient({
host: 'jmri.local',
reconnection: {
enabled: true,
maxAttempts: 0, // infinite
initialDelay: 1000,
maxDelay: 30000,
multiplier: 1.5,
jitter: true
}
});
client.on('reconnecting', (attempt, delay) => {
console.log(`Reconnecting attempt ${attempt} in ${delay}ms`);
});const client = new JmriClient({
host: 'jmri.local',
heartbeat: {
enabled: true,
interval: 30000,
timeout: 5000
}
});Messages sent while disconnected are queued and automatically flushed when reconnected.
Ensure you're running Node.js 18 or higher:
node --version # Should be >= 18.0.0npm install jmri-client@3.0.0If using TypeScript, import types:
import { JmriClient, PowerState } from 'jmri-client';Replace positional arguments with options object:
// Before
const client = new JmriClient('http', 'jmri.local', 12080);
// After
const client = new JmriClient({
host: 'jmri.local',
port: 12080
});Replace boolean with enum:
// Before
await client.setPower(true);
// After
await client.powerOn();
// or
await client.setPower(PowerState.ON);Remove .data access:
// Before
const response = await client.getPower();
const state = response.data.state;
// After
const state = await client.getPower();Take advantage of real-time updates:
client.on('connected', () => {
console.log('Connected to JMRI');
});
client.on('power:changed', (state) => {
const stateStr = state === PowerState.ON ? 'ON' :
state === PowerState.OFF ? 'OFF' : 'UNKNOWN';
console.log('Power changed:', stateStr);
});Before (v2.x):
const { JmriClient } = require('jmri-client');
const client = new JmriClient('http', 'jmri.local', 12080);
async function main() {
const powerResponse = await client.getPower();
console.log(powerResponse.data);
await client.setPower(true);
console.log('Power turned on');
}
main();After (v3.x):
import { JmriClient, PowerState } from 'jmri-client';
const client = new JmriClient({
host: 'jmri.local',
port: 12080
});
client.on('connected', async () => {
const powerState = await client.getPower();
console.log('Current power:', powerState);
await client.powerOn();
console.log('Power turned on');
});
client.on('error', (error) => {
console.error('Error:', error);
});