jmri-client 4.2.0-beta.2 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +3 -1
  2. package/dist/browser/jmri-client.js +88 -28
  3. package/dist/cjs/index.js +2442 -31
  4. package/dist/esm/index.js +2393 -17
  5. package/dist/types/client.d.ts +9 -1
  6. package/dist/types/index.d.ts +1 -1
  7. package/dist/types/managers/roster-manager.d.ts +9 -1
  8. package/dist/types/mocks/mock-data.d.ts +30 -6
  9. package/dist/types/mocks/mock-response-manager.d.ts +7 -2
  10. package/dist/types/types/jmri-messages.d.ts +22 -0
  11. package/docs/API.md +8 -0
  12. package/docs/BROWSER.md +4 -4
  13. package/docs/MIGRATION.md +30 -1
  14. package/docs/MOCK_MODE.md +15 -9
  15. package/package.json +17 -18
  16. package/dist/cjs/client.js +0 -366
  17. package/dist/cjs/core/connection-state-manager.js +0 -84
  18. package/dist/cjs/core/heartbeat-manager.js +0 -79
  19. package/dist/cjs/core/index.js +0 -25
  20. package/dist/cjs/core/message-queue.js +0 -59
  21. package/dist/cjs/core/reconnection-manager.js +0 -97
  22. package/dist/cjs/core/websocket-adapter.js +0 -135
  23. package/dist/cjs/core/websocket-client.js +0 -388
  24. package/dist/cjs/managers/index.js +0 -25
  25. package/dist/cjs/managers/light-manager.js +0 -111
  26. package/dist/cjs/managers/power-manager.js +0 -90
  27. package/dist/cjs/managers/roster-manager.js +0 -118
  28. package/dist/cjs/managers/system-connections-manager.js +0 -28
  29. package/dist/cjs/managers/throttle-manager.js +0 -233
  30. package/dist/cjs/managers/turnout-manager.js +0 -111
  31. package/dist/cjs/mocks/index.js +0 -12
  32. package/dist/cjs/mocks/mock-data.js +0 -237
  33. package/dist/cjs/mocks/mock-response-manager.js +0 -290
  34. package/dist/cjs/types/client-options.js +0 -66
  35. package/dist/cjs/types/events.js +0 -16
  36. package/dist/cjs/types/index.js +0 -23
  37. package/dist/cjs/types/jmri-messages.js +0 -95
  38. package/dist/cjs/types/throttle.js +0 -19
  39. package/dist/cjs/utils/exponential-backoff.js +0 -40
  40. package/dist/cjs/utils/index.js +0 -21
  41. package/dist/cjs/utils/message-id.js +0 -40
  42. package/dist/esm/client.js +0 -362
  43. package/dist/esm/core/connection-state-manager.js +0 -80
  44. package/dist/esm/core/heartbeat-manager.js +0 -75
  45. package/dist/esm/core/index.js +0 -9
  46. package/dist/esm/core/message-queue.js +0 -55
  47. package/dist/esm/core/reconnection-manager.js +0 -93
  48. package/dist/esm/core/websocket-adapter.js +0 -98
  49. package/dist/esm/core/websocket-client.js +0 -384
  50. package/dist/esm/managers/index.js +0 -9
  51. package/dist/esm/managers/light-manager.js +0 -107
  52. package/dist/esm/managers/power-manager.js +0 -86
  53. package/dist/esm/managers/roster-manager.js +0 -114
  54. package/dist/esm/managers/system-connections-manager.js +0 -24
  55. package/dist/esm/managers/throttle-manager.js +0 -229
  56. package/dist/esm/managers/turnout-manager.js +0 -107
  57. package/dist/esm/mocks/index.js +0 -6
  58. package/dist/esm/mocks/mock-data.js +0 -234
  59. package/dist/esm/mocks/mock-response-manager.js +0 -286
  60. package/dist/esm/types/client-options.js +0 -62
  61. package/dist/esm/types/events.js +0 -13
  62. package/dist/esm/types/index.js +0 -7
  63. package/dist/esm/types/jmri-messages.js +0 -89
  64. package/dist/esm/types/throttle.js +0 -15
  65. package/dist/esm/utils/exponential-backoff.js +0 -36
  66. package/dist/esm/utils/index.js +0 -5
  67. package/dist/esm/utils/message-id.js +0 -36
@@ -1,75 +0,0 @@
1
- /**
2
- * Heartbeat (ping/pong) management
3
- */
4
- import { EventEmitter } from 'eventemitter3';
5
- /**
6
- * Manages WebSocket heartbeat via ping/pong
7
- */
8
- export class HeartbeatManager extends EventEmitter {
9
- constructor(options) {
10
- super();
11
- this.isRunning = false;
12
- this.options = options;
13
- }
14
- /**
15
- * Start heartbeat monitoring
16
- * @param sendPing - Callback to send ping message
17
- */
18
- start(sendPing) {
19
- if (!this.options.enabled || this.isRunning) {
20
- return;
21
- }
22
- this.isRunning = true;
23
- // Send ping at regular intervals
24
- this.pingInterval = setInterval(() => {
25
- sendPing();
26
- this.emit('pingSent');
27
- // Start pong timeout
28
- this.pongTimeout = setTimeout(() => {
29
- this.emit('timeout');
30
- }, this.options.timeout);
31
- }, this.options.interval);
32
- }
33
- /**
34
- * Stop heartbeat monitoring
35
- */
36
- stop() {
37
- this.isRunning = false;
38
- if (this.pingInterval) {
39
- clearInterval(this.pingInterval);
40
- this.pingInterval = undefined;
41
- }
42
- if (this.pongTimeout) {
43
- clearTimeout(this.pongTimeout);
44
- this.pongTimeout = undefined;
45
- }
46
- }
47
- /**
48
- * Handle pong received from server
49
- */
50
- receivedPong() {
51
- // Clear pong timeout
52
- if (this.pongTimeout) {
53
- clearTimeout(this.pongTimeout);
54
- this.pongTimeout = undefined;
55
- }
56
- this.emit('pongReceived');
57
- }
58
- /**
59
- * Check if heartbeat is running
60
- */
61
- running() {
62
- return this.isRunning;
63
- }
64
- /**
65
- * Update heartbeat options
66
- */
67
- updateOptions(options) {
68
- const wasRunning = this.isRunning;
69
- if (wasRunning) {
70
- this.stop();
71
- }
72
- this.options = { ...this.options, ...options };
73
- // Note: Caller must call start() again if needed
74
- }
75
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Core infrastructure exports
3
- */
4
- export * from './websocket-client.js';
5
- export * from './websocket-adapter.js';
6
- export * from './connection-state-manager.js';
7
- export * from './reconnection-manager.js';
8
- export * from './heartbeat-manager.js';
9
- export * from './message-queue.js';
@@ -1,55 +0,0 @@
1
- /**
2
- * Message queue for offline message handling
3
- */
4
- /**
5
- * Queue for storing messages when disconnected
6
- * Messages are sent when connection is restored
7
- */
8
- export class MessageQueue {
9
- constructor(maxSize = 100) {
10
- this.queue = [];
11
- this.maxSize = maxSize;
12
- }
13
- /**
14
- * Add message to queue
15
- * If queue is full, oldest message is removed
16
- */
17
- enqueue(message) {
18
- if (this.queue.length >= this.maxSize) {
19
- this.queue.shift(); // Remove oldest
20
- }
21
- this.queue.push(message);
22
- }
23
- /**
24
- * Get all queued messages and clear queue
25
- */
26
- flush() {
27
- const messages = [...this.queue];
28
- this.queue = [];
29
- return messages;
30
- }
31
- /**
32
- * Clear all queued messages without returning them
33
- */
34
- clear() {
35
- this.queue = [];
36
- }
37
- /**
38
- * Get number of queued messages
39
- */
40
- size() {
41
- return this.queue.length;
42
- }
43
- /**
44
- * Check if queue is empty
45
- */
46
- isEmpty() {
47
- return this.queue.length === 0;
48
- }
49
- /**
50
- * Check if queue is full
51
- */
52
- isFull() {
53
- return this.queue.length >= this.maxSize;
54
- }
55
- }
@@ -1,93 +0,0 @@
1
- /**
2
- * Automatic reconnection management with exponential backoff
3
- */
4
- import { EventEmitter } from 'eventemitter3';
5
- import { calculateBackoffDelay, shouldReconnect } from '../utils/exponential-backoff.js';
6
- /**
7
- * Manages automatic reconnection with exponential backoff
8
- */
9
- export class ReconnectionManager extends EventEmitter {
10
- constructor(options) {
11
- super();
12
- this.currentAttempt = 0;
13
- this.isReconnecting = false;
14
- this.options = options;
15
- }
16
- /**
17
- * Start reconnection process
18
- * @param reconnect - Callback to attempt reconnection
19
- */
20
- start(reconnect) {
21
- if (!this.options.enabled || this.isReconnecting) {
22
- return;
23
- }
24
- this.isReconnecting = true;
25
- this.currentAttempt = 0;
26
- this.scheduleNextAttempt(reconnect);
27
- }
28
- /**
29
- * Schedule next reconnection attempt
30
- */
31
- scheduleNextAttempt(reconnect) {
32
- this.currentAttempt++;
33
- // Check if should continue trying
34
- if (!shouldReconnect(this.currentAttempt, this.options.maxAttempts)) {
35
- this.emit('maxAttemptsReached', this.currentAttempt - 1);
36
- this.stop();
37
- return;
38
- }
39
- // Calculate delay with backoff
40
- const delay = calculateBackoffDelay(this.currentAttempt, this.options);
41
- this.emit('attemptScheduled', this.currentAttempt, delay);
42
- // Schedule attempt
43
- this.reconnectTimeout = setTimeout(async () => {
44
- this.emit('attempting', this.currentAttempt);
45
- try {
46
- await reconnect();
47
- // Success - stop reconnection process
48
- this.stop();
49
- this.emit('success', this.currentAttempt);
50
- }
51
- catch (error) {
52
- // Failure - schedule next attempt
53
- this.emit('failed', this.currentAttempt, error);
54
- this.scheduleNextAttempt(reconnect);
55
- }
56
- }, delay);
57
- }
58
- /**
59
- * Stop reconnection process
60
- */
61
- stop() {
62
- this.isReconnecting = false;
63
- if (this.reconnectTimeout) {
64
- clearTimeout(this.reconnectTimeout);
65
- this.reconnectTimeout = undefined;
66
- }
67
- }
68
- /**
69
- * Reset attempt counter
70
- */
71
- reset() {
72
- this.stop();
73
- this.currentAttempt = 0;
74
- }
75
- /**
76
- * Check if currently reconnecting
77
- */
78
- reconnecting() {
79
- return this.isReconnecting;
80
- }
81
- /**
82
- * Get current attempt number
83
- */
84
- getAttempt() {
85
- return this.currentAttempt;
86
- }
87
- /**
88
- * Update reconnection options
89
- */
90
- updateOptions(options) {
91
- this.options = { ...this.options, ...options };
92
- }
93
- }
@@ -1,98 +0,0 @@
1
- /**
2
- * WebSocket Adapter
3
- * Provides a unified interface for WebSocket connections in both Node.js and browser environments
4
- */
5
- import { EventEmitter } from 'eventemitter3';
6
- /**
7
- * WebSocket ready states
8
- */
9
- export var ReadyState;
10
- (function (ReadyState) {
11
- ReadyState[ReadyState["CONNECTING"] = 0] = "CONNECTING";
12
- ReadyState[ReadyState["OPEN"] = 1] = "OPEN";
13
- ReadyState[ReadyState["CLOSING"] = 2] = "CLOSING";
14
- ReadyState[ReadyState["CLOSED"] = 3] = "CLOSED";
15
- })(ReadyState || (ReadyState = {}));
16
- /**
17
- * Create a WebSocket adapter for the current environment
18
- */
19
- export async function createWebSocketAdapter(url, protocols) {
20
- // Detect environment
21
- const isBrowser = typeof window !== 'undefined' && typeof window.WebSocket !== 'undefined';
22
- if (isBrowser) {
23
- return new BrowserWebSocketAdapter(url, protocols);
24
- }
25
- else {
26
- return await NodeWebSocketAdapter.create(url, protocols);
27
- }
28
- }
29
- /**
30
- * Browser WebSocket adapter
31
- * Wraps native browser WebSocket with EventEmitter interface
32
- */
33
- class BrowserWebSocketAdapter extends EventEmitter {
34
- constructor(url, protocols) {
35
- super();
36
- this.ws = new WebSocket(url, protocols);
37
- this.ws.onopen = () => {
38
- this.emit('open');
39
- };
40
- this.ws.onmessage = (event) => {
41
- this.emit('message', event.data);
42
- };
43
- this.ws.onerror = () => {
44
- this.emit('error', new Error('WebSocket error'));
45
- };
46
- this.ws.onclose = (event) => {
47
- this.emit('close', event.code, event.reason);
48
- };
49
- }
50
- send(data) {
51
- this.ws.send(data);
52
- }
53
- close(code, reason) {
54
- this.ws.close(code, reason);
55
- }
56
- get readyState() {
57
- return this.ws.readyState;
58
- }
59
- }
60
- /**
61
- * Node.js WebSocket adapter
62
- * Wraps ws package with consistent interface
63
- */
64
- class NodeWebSocketAdapter extends EventEmitter {
65
- constructor(ws) {
66
- super();
67
- this.ws = ws;
68
- this.ws.on('open', () => {
69
- this.emit('open');
70
- });
71
- this.ws.on('message', (data) => {
72
- // Convert Buffer to string if needed
73
- const message = typeof data === 'string' ? data : data.toString();
74
- this.emit('message', message);
75
- });
76
- this.ws.on('error', (error) => {
77
- this.emit('error', error);
78
- });
79
- this.ws.on('close', (code, reason) => {
80
- this.emit('close', code, reason);
81
- });
82
- }
83
- static async create(url, protocols) {
84
- // Use dynamic import for ESM compatibility
85
- const { default: WebSocket } = await import('ws');
86
- const ws = new WebSocket(url, protocols);
87
- return new NodeWebSocketAdapter(ws);
88
- }
89
- send(data) {
90
- this.ws.send(data);
91
- }
92
- close(code, reason) {
93
- this.ws.close(code, reason);
94
- }
95
- get readyState() {
96
- return this.ws.readyState;
97
- }
98
- }