@lspeasy/core 1.0.1

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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +550 -0
  3. package/dist/index.d.ts +44 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +32 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/jsonrpc/framing.d.ts +32 -0
  8. package/dist/jsonrpc/framing.d.ts.map +1 -0
  9. package/dist/jsonrpc/framing.js +96 -0
  10. package/dist/jsonrpc/framing.js.map +1 -0
  11. package/dist/jsonrpc/messages.d.ts +64 -0
  12. package/dist/jsonrpc/messages.d.ts.map +1 -0
  13. package/dist/jsonrpc/messages.js +23 -0
  14. package/dist/jsonrpc/messages.js.map +1 -0
  15. package/dist/jsonrpc/reader.d.ts +44 -0
  16. package/dist/jsonrpc/reader.d.ts.map +1 -0
  17. package/dist/jsonrpc/reader.js +107 -0
  18. package/dist/jsonrpc/reader.js.map +1 -0
  19. package/dist/jsonrpc/schemas.d.ts +103 -0
  20. package/dist/jsonrpc/schemas.d.ts.map +1 -0
  21. package/dist/jsonrpc/schemas.js +66 -0
  22. package/dist/jsonrpc/schemas.js.map +1 -0
  23. package/dist/jsonrpc/writer.d.ts +43 -0
  24. package/dist/jsonrpc/writer.d.ts.map +1 -0
  25. package/dist/jsonrpc/writer.js +110 -0
  26. package/dist/jsonrpc/writer.js.map +1 -0
  27. package/dist/middleware/compose.d.ts +3 -0
  28. package/dist/middleware/compose.d.ts.map +1 -0
  29. package/dist/middleware/compose.js +16 -0
  30. package/dist/middleware/compose.js.map +1 -0
  31. package/dist/middleware/index.d.ts +6 -0
  32. package/dist/middleware/index.d.ts.map +1 -0
  33. package/dist/middleware/index.js +5 -0
  34. package/dist/middleware/index.js.map +1 -0
  35. package/dist/middleware/pipeline.d.ts +5 -0
  36. package/dist/middleware/pipeline.d.ts.map +1 -0
  37. package/dist/middleware/pipeline.js +54 -0
  38. package/dist/middleware/pipeline.js.map +1 -0
  39. package/dist/middleware/scoped.d.ts +9 -0
  40. package/dist/middleware/scoped.d.ts.map +1 -0
  41. package/dist/middleware/scoped.js +20 -0
  42. package/dist/middleware/scoped.js.map +1 -0
  43. package/dist/middleware/typed.d.ts +3 -0
  44. package/dist/middleware/typed.d.ts.map +1 -0
  45. package/dist/middleware/typed.js +18 -0
  46. package/dist/middleware/typed.js.map +1 -0
  47. package/dist/middleware/types.d.ts +45 -0
  48. package/dist/middleware/types.d.ts.map +1 -0
  49. package/dist/middleware/types.js +2 -0
  50. package/dist/middleware/types.js.map +1 -0
  51. package/dist/protocol/capabilities.d.ts +93 -0
  52. package/dist/protocol/capabilities.d.ts.map +1 -0
  53. package/dist/protocol/capabilities.js +143 -0
  54. package/dist/protocol/capabilities.js.map +1 -0
  55. package/dist/protocol/capability-methods.d.ts +270 -0
  56. package/dist/protocol/capability-methods.d.ts.map +1 -0
  57. package/dist/protocol/capability-methods.js +14 -0
  58. package/dist/protocol/capability-methods.js.map +1 -0
  59. package/dist/protocol/enums.d.ts +336 -0
  60. package/dist/protocol/enums.d.ts.map +1 -0
  61. package/dist/protocol/enums.js +417 -0
  62. package/dist/protocol/enums.js.map +1 -0
  63. package/dist/protocol/infer.d.ts +112 -0
  64. package/dist/protocol/infer.d.ts.map +1 -0
  65. package/dist/protocol/infer.js +58 -0
  66. package/dist/protocol/infer.js.map +1 -0
  67. package/dist/protocol/namespaces.d.ts +1432 -0
  68. package/dist/protocol/namespaces.d.ts.map +1 -0
  69. package/dist/protocol/namespaces.js +570 -0
  70. package/dist/protocol/namespaces.js.map +1 -0
  71. package/dist/protocol/partial.d.ts +29 -0
  72. package/dist/protocol/partial.d.ts.map +1 -0
  73. package/dist/protocol/partial.js +24 -0
  74. package/dist/protocol/partial.js.map +1 -0
  75. package/dist/protocol/progress.d.ts +32 -0
  76. package/dist/protocol/progress.d.ts.map +1 -0
  77. package/dist/protocol/progress.js +60 -0
  78. package/dist/protocol/progress.js.map +1 -0
  79. package/dist/protocol/schemas.d.ts +534 -0
  80. package/dist/protocol/schemas.d.ts.map +1 -0
  81. package/dist/protocol/schemas.js +271 -0
  82. package/dist/protocol/schemas.js.map +1 -0
  83. package/dist/protocol/types.d.ts +19 -0
  84. package/dist/protocol/types.d.ts.map +1 -0
  85. package/dist/protocol/types.js +8 -0
  86. package/dist/protocol/types.js.map +1 -0
  87. package/dist/protocol/watching.d.ts +29 -0
  88. package/dist/protocol/watching.d.ts.map +1 -0
  89. package/dist/protocol/watching.js +36 -0
  90. package/dist/protocol/watching.js.map +1 -0
  91. package/dist/protocol/workspace.d.ts +24 -0
  92. package/dist/protocol/workspace.d.ts.map +1 -0
  93. package/dist/protocol/workspace.js +26 -0
  94. package/dist/protocol/workspace.js.map +1 -0
  95. package/dist/transport/events.d.ts +27 -0
  96. package/dist/transport/events.d.ts.map +1 -0
  97. package/dist/transport/events.js +34 -0
  98. package/dist/transport/events.js.map +1 -0
  99. package/dist/transport/stdio.d.ts +55 -0
  100. package/dist/transport/stdio.d.ts.map +1 -0
  101. package/dist/transport/stdio.js +147 -0
  102. package/dist/transport/stdio.js.map +1 -0
  103. package/dist/transport/transport.d.ts +38 -0
  104. package/dist/transport/transport.d.ts.map +1 -0
  105. package/dist/transport/transport.js +5 -0
  106. package/dist/transport/transport.js.map +1 -0
  107. package/dist/transport/websocket.d.ts +142 -0
  108. package/dist/transport/websocket.d.ts.map +1 -0
  109. package/dist/transport/websocket.js +324 -0
  110. package/dist/transport/websocket.js.map +1 -0
  111. package/dist/utils/cancellation.d.ts +47 -0
  112. package/dist/utils/cancellation.d.ts.map +1 -0
  113. package/dist/utils/cancellation.js +77 -0
  114. package/dist/utils/cancellation.js.map +1 -0
  115. package/dist/utils/disposable-event-emitter.d.ts +26 -0
  116. package/dist/utils/disposable-event-emitter.d.ts.map +1 -0
  117. package/dist/utils/disposable-event-emitter.js +62 -0
  118. package/dist/utils/disposable-event-emitter.js.map +1 -0
  119. package/dist/utils/disposable.d.ts +34 -0
  120. package/dist/utils/disposable.d.ts.map +1 -0
  121. package/dist/utils/disposable.js +55 -0
  122. package/dist/utils/disposable.js.map +1 -0
  123. package/dist/utils/document.d.ts +20 -0
  124. package/dist/utils/document.d.ts.map +1 -0
  125. package/dist/utils/document.js +54 -0
  126. package/dist/utils/document.js.map +1 -0
  127. package/dist/utils/errors.d.ts +69 -0
  128. package/dist/utils/errors.d.ts.map +1 -0
  129. package/dist/utils/errors.js +104 -0
  130. package/dist/utils/errors.js.map +1 -0
  131. package/dist/utils/handler-registry.d.ts +35 -0
  132. package/dist/utils/handler-registry.d.ts.map +1 -0
  133. package/dist/utils/handler-registry.js +68 -0
  134. package/dist/utils/handler-registry.js.map +1 -0
  135. package/dist/utils/index.d.ts +5 -0
  136. package/dist/utils/index.d.ts.map +1 -0
  137. package/dist/utils/index.js +4 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/internal.d.ts +3 -0
  140. package/dist/utils/internal.d.ts.map +1 -0
  141. package/dist/utils/internal.js +3 -0
  142. package/dist/utils/internal.js.map +1 -0
  143. package/dist/utils/logger.d.ts +47 -0
  144. package/dist/utils/logger.d.ts.map +1 -0
  145. package/dist/utils/logger.js +61 -0
  146. package/dist/utils/logger.js.map +1 -0
  147. package/dist/utils/pending-request-tracker.d.ts +36 -0
  148. package/dist/utils/pending-request-tracker.d.ts.map +1 -0
  149. package/dist/utils/pending-request-tracker.js +93 -0
  150. package/dist/utils/pending-request-tracker.js.map +1 -0
  151. package/dist/utils/transport-attachment.d.ts +34 -0
  152. package/dist/utils/transport-attachment.d.ts.map +1 -0
  153. package/dist/utils/transport-attachment.js +48 -0
  154. package/dist/utils/transport-attachment.js.map +1 -0
  155. package/package.json +87 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * StdioTransport - Transport implementation using stdin/stdout
3
+ */
4
+ import { MessageReader } from '../jsonrpc/reader.js';
5
+ import { MessageWriter } from '../jsonrpc/writer.js';
6
+ /**
7
+ * Transport implementation using stdin/stdout streams
8
+ */
9
+ export class StdioTransport {
10
+ reader;
11
+ writer;
12
+ connected;
13
+ messageHandlers;
14
+ errorHandlers;
15
+ closeHandlers;
16
+ constructor(options = {}) {
17
+ const input = options.input ?? process.stdin;
18
+ const output = options.output ?? process.stdout;
19
+ this.reader = new MessageReader(input);
20
+ this.writer = new MessageWriter(output);
21
+ this.connected = true;
22
+ this.messageHandlers = new Set();
23
+ this.errorHandlers = new Set();
24
+ this.closeHandlers = new Set();
25
+ // Set up reader event handlers
26
+ this.reader.on('message', (message) => {
27
+ this.messageHandlers.forEach((handler) => {
28
+ try {
29
+ handler(message);
30
+ }
31
+ catch (error) {
32
+ console.error('Error in message handler:', error);
33
+ }
34
+ });
35
+ });
36
+ this.reader.on('error', (error) => {
37
+ this.errorHandlers.forEach((handler) => {
38
+ try {
39
+ handler(error);
40
+ }
41
+ catch (err) {
42
+ console.error('Error in error handler:', err);
43
+ }
44
+ });
45
+ });
46
+ this.reader.on('close', () => {
47
+ this.handleClose();
48
+ });
49
+ // Set up writer event handlers
50
+ this.writer.on('error', (error) => {
51
+ this.errorHandlers.forEach((handler) => {
52
+ try {
53
+ handler(error);
54
+ }
55
+ catch (err) {
56
+ console.error('Error in error handler:', err);
57
+ }
58
+ });
59
+ });
60
+ this.writer.on('close', () => {
61
+ this.handleClose();
62
+ });
63
+ }
64
+ /**
65
+ * Send a message
66
+ */
67
+ async send(message) {
68
+ if (!this.connected) {
69
+ throw new Error('Transport is not connected');
70
+ }
71
+ await this.writer.write(message);
72
+ }
73
+ /**
74
+ * Subscribe to incoming messages
75
+ */
76
+ onMessage(handler) {
77
+ this.messageHandlers.add(handler);
78
+ return {
79
+ dispose: () => {
80
+ this.messageHandlers.delete(handler);
81
+ }
82
+ };
83
+ }
84
+ /**
85
+ * Subscribe to errors
86
+ */
87
+ onError(handler) {
88
+ this.errorHandlers.add(handler);
89
+ return {
90
+ dispose: () => {
91
+ this.errorHandlers.delete(handler);
92
+ }
93
+ };
94
+ }
95
+ /**
96
+ * Subscribe to close events
97
+ */
98
+ onClose(handler) {
99
+ this.closeHandlers.add(handler);
100
+ return {
101
+ dispose: () => {
102
+ this.closeHandlers.delete(handler);
103
+ }
104
+ };
105
+ }
106
+ /**
107
+ * Close the transport
108
+ */
109
+ async close() {
110
+ if (!this.connected) {
111
+ return;
112
+ }
113
+ this.reader.close();
114
+ this.writer.close();
115
+ // Don't close stdin/stdout as they're shared resources
116
+ // Just clean up our handlers
117
+ this.handleClose();
118
+ }
119
+ /**
120
+ * Check if transport is connected
121
+ */
122
+ isConnected() {
123
+ return this.connected;
124
+ }
125
+ /**
126
+ * Handle connection close
127
+ */
128
+ handleClose() {
129
+ if (!this.connected) {
130
+ return;
131
+ }
132
+ this.connected = false;
133
+ this.closeHandlers.forEach((handler) => {
134
+ try {
135
+ handler();
136
+ }
137
+ catch (error) {
138
+ console.error('Error in close handler:', error);
139
+ }
140
+ });
141
+ // Clear all handlers
142
+ this.messageHandlers.clear();
143
+ this.errorHandlers.clear();
144
+ this.closeHandlers.clear();
145
+ }
146
+ }
147
+ //# sourceMappingURL=stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transport/stdio.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Transport interface for pluggable communication layers
3
+ */
4
+ import type { Message } from '../jsonrpc/messages.js';
5
+ import type { Disposable } from '../utils/disposable.js';
6
+ /**
7
+ * Transport interface for sending/receiving JSON-RPC messages
8
+ */
9
+ export interface Transport {
10
+ /**
11
+ * Send a message to the remote peer
12
+ */
13
+ send(message: Message): Promise<void>;
14
+ /**
15
+ * Subscribe to incoming messages
16
+ * @returns Disposable to unsubscribe
17
+ */
18
+ onMessage(handler: (message: Message) => void): Disposable;
19
+ /**
20
+ * Subscribe to transport errors
21
+ * @returns Disposable to unsubscribe
22
+ */
23
+ onError(handler: (error: Error) => void): Disposable;
24
+ /**
25
+ * Subscribe to connection close
26
+ * @returns Disposable to unsubscribe
27
+ */
28
+ onClose(handler: () => void): Disposable;
29
+ /**
30
+ * Close the transport connection
31
+ */
32
+ close(): Promise<void>;
33
+ /**
34
+ * Check if transport is connected
35
+ */
36
+ isConnected(): boolean;
37
+ }
38
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC;IAE3D;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;IAErD;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,UAAU,CAAC;IAEzC;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;CACxB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Transport interface for pluggable communication layers
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * WebSocket Transport implementation for LSP
3
+ */
4
+ import type { Transport } from './transport.js';
5
+ import type { Message } from '../jsonrpc/messages.js';
6
+ import type { Disposable } from '../utils/disposable.js';
7
+ type CloseLikeEvent = {
8
+ type: 'close';
9
+ };
10
+ type ErrorLikeEvent = {
11
+ error?: unknown;
12
+ };
13
+ type MessageLikeEvent = {
14
+ data: unknown;
15
+ };
16
+ type WebSocketLike = {
17
+ readonly readyState: number;
18
+ send(data: string, callback?: (error?: Error) => void): void;
19
+ close(): void;
20
+ on?(event: 'open', handler: () => void): void;
21
+ on?(event: 'message', handler: (data: Buffer | string) => void): void;
22
+ on?(event: 'error', handler: (error: Error) => void): void;
23
+ on?(event: 'close', handler: () => void): void;
24
+ once?(event: 'close', handler: () => void): void;
25
+ addEventListener?(event: 'open', handler: () => void): void;
26
+ addEventListener?(event: 'message', handler: (event: MessageLikeEvent) => void): void;
27
+ addEventListener?(event: 'error', handler: (event: ErrorLikeEvent) => void): void;
28
+ addEventListener?(event: 'close', handler: (event: CloseLikeEvent) => void): void;
29
+ };
30
+ export interface WebSocketTransportOptions {
31
+ /**
32
+ * WebSocket URL for client mode (e.g., 'ws://localhost:3000')
33
+ */
34
+ url?: string;
35
+ /**
36
+ * Existing WebSocket instance for server mode
37
+ */
38
+ socket?: WebSocketLike;
39
+ /**
40
+ * Enable automatic reconnection (client mode only)
41
+ */
42
+ enableReconnect?: boolean;
43
+ /**
44
+ * Maximum number of reconnection attempts
45
+ * @default 5
46
+ */
47
+ maxReconnectAttempts?: number;
48
+ /**
49
+ * Initial delay between reconnection attempts in milliseconds
50
+ * @default 1000
51
+ */
52
+ reconnectDelay?: number;
53
+ /**
54
+ * Maximum delay between reconnection attempts in milliseconds
55
+ * @default 30000
56
+ */
57
+ maxReconnectDelay?: number;
58
+ /**
59
+ * Multiplier for exponential backoff
60
+ * @default 2
61
+ */
62
+ reconnectBackoffMultiplier?: number;
63
+ }
64
+ export declare function createWebSocketClient(url: string): WebSocketLike;
65
+ /**
66
+ * WebSocket-based transport for LSP communication
67
+ *
68
+ * Supports both client and server modes:
69
+ * - Client mode: Connects to a WebSocket server URL
70
+ * - Server mode: Wraps an existing WebSocket connection
71
+ */
72
+ export declare class WebSocketTransport implements Transport {
73
+ private socket;
74
+ private connected;
75
+ private messageHandlers;
76
+ private errorHandlers;
77
+ private closeHandlers;
78
+ private readonly mode;
79
+ private readonly url;
80
+ private readonly enableReconnect;
81
+ private readonly maxReconnectAttempts;
82
+ private readonly reconnectDelay;
83
+ private readonly maxReconnectDelay;
84
+ private readonly reconnectBackoffMultiplier;
85
+ private reconnectAttempts;
86
+ private reconnectTimer;
87
+ private intentionallyClosed;
88
+ constructor(options: WebSocketTransportOptions);
89
+ /**
90
+ * Setup event handlers for the WebSocket
91
+ */
92
+ private setupSocket;
93
+ private handleOpen;
94
+ private handleMessageData;
95
+ private handleClose;
96
+ /**
97
+ * Schedule a reconnection attempt with exponential backoff
98
+ */
99
+ private scheduleReconnect;
100
+ /**
101
+ * Attempt to reconnect to the server
102
+ */
103
+ private attemptReconnect;
104
+ /**
105
+ * Notify all error handlers
106
+ */
107
+ private notifyError;
108
+ /**
109
+ * Send a message through the WebSocket
110
+ */
111
+ send(message: Message): Promise<void>;
112
+ /**
113
+ * Register a handler for incoming messages
114
+ */
115
+ onMessage(handler: (message: Message) => void): Disposable;
116
+ /**
117
+ * Register a handler for transport errors
118
+ */
119
+ onError(handler: (error: Error) => void): Disposable;
120
+ /**
121
+ * Register a handler for transport closure
122
+ */
123
+ onClose(handler: () => void): Disposable;
124
+ /**
125
+ * Close the WebSocket connection
126
+ */
127
+ close(): Promise<void>;
128
+ /**
129
+ * Check if the transport is currently connected
130
+ */
131
+ isConnected(): boolean;
132
+ /**
133
+ * Get the current reconnection attempt count
134
+ */
135
+ getReconnectAttempts(): number;
136
+ /**
137
+ * Check if reconnection is enabled
138
+ */
139
+ isReconnectEnabled(): boolean;
140
+ }
141
+ export {};
142
+ //# sourceMappingURL=websocket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/transport/websocket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,324 @@
1
+ /**
2
+ * WebSocket Transport implementation for LSP
3
+ */
4
+ import { createRequire } from 'node:module';
5
+ const READY_STATE_CONNECTING = 0;
6
+ const READY_STATE_OPEN = 1;
7
+ function hasEventEmitterAPI(socket) {
8
+ return typeof socket.on === 'function';
9
+ }
10
+ function getNativeWebSocketCtor() {
11
+ if (typeof globalThis.WebSocket === 'undefined') {
12
+ return undefined;
13
+ }
14
+ const ctor = globalThis.WebSocket;
15
+ return (url) => new ctor(url);
16
+ }
17
+ function getWsWebSocketCtor() {
18
+ try {
19
+ const require = createRequire(import.meta.url);
20
+ const moduleValue = require('ws');
21
+ if (typeof moduleValue === 'function') {
22
+ return (url) => new moduleValue(url);
23
+ }
24
+ if (moduleValue.WebSocket) {
25
+ return (url) => new moduleValue.WebSocket(url);
26
+ }
27
+ return undefined;
28
+ }
29
+ catch {
30
+ return undefined;
31
+ }
32
+ }
33
+ export function createWebSocketClient(url) {
34
+ const nativeCtor = getNativeWebSocketCtor();
35
+ if (nativeCtor) {
36
+ return nativeCtor(url);
37
+ }
38
+ const wsCtor = getWsWebSocketCtor();
39
+ if (wsCtor) {
40
+ return wsCtor(url);
41
+ }
42
+ throw new Error('WebSocket client unavailable. Use Node.js >= 22.4 for native globalThis.WebSocket, or install "ws" as an optional peer dependency.');
43
+ }
44
+ function parseIncomingMessage(data) {
45
+ if (typeof data === 'string') {
46
+ return JSON.parse(data);
47
+ }
48
+ if (data instanceof Uint8Array) {
49
+ return JSON.parse(Buffer.from(data).toString('utf8'));
50
+ }
51
+ if (data instanceof ArrayBuffer) {
52
+ return JSON.parse(Buffer.from(data).toString('utf8'));
53
+ }
54
+ if (typeof Buffer !== 'undefined' && Buffer.isBuffer(data)) {
55
+ return JSON.parse(data.toString('utf8'));
56
+ }
57
+ throw new Error('Unsupported WebSocket message payload type');
58
+ }
59
+ /**
60
+ * WebSocket-based transport for LSP communication
61
+ *
62
+ * Supports both client and server modes:
63
+ * - Client mode: Connects to a WebSocket server URL
64
+ * - Server mode: Wraps an existing WebSocket connection
65
+ */
66
+ export class WebSocketTransport {
67
+ socket;
68
+ connected = false;
69
+ messageHandlers = new Set();
70
+ errorHandlers = new Set();
71
+ closeHandlers = new Set();
72
+ // Reconnection state
73
+ mode;
74
+ url;
75
+ enableReconnect;
76
+ maxReconnectAttempts;
77
+ reconnectDelay;
78
+ maxReconnectDelay;
79
+ reconnectBackoffMultiplier;
80
+ reconnectAttempts = 0;
81
+ reconnectTimer;
82
+ intentionallyClosed = false;
83
+ constructor(options) {
84
+ if (!options.url && !options.socket) {
85
+ throw new Error('Either url or socket must be provided');
86
+ }
87
+ if (options.url && options.socket) {
88
+ throw new Error('Cannot provide both url and socket');
89
+ }
90
+ this.mode = options.socket ? 'server' : 'client';
91
+ this.url = options.url;
92
+ this.enableReconnect = options.enableReconnect ?? false;
93
+ this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;
94
+ this.reconnectDelay = options.reconnectDelay ?? 1000;
95
+ this.maxReconnectDelay = options.maxReconnectDelay ?? 30000;
96
+ this.reconnectBackoffMultiplier = options.reconnectBackoffMultiplier ?? 2;
97
+ if (options.socket) {
98
+ this.socket = options.socket;
99
+ }
100
+ else {
101
+ this.socket = createWebSocketClient(this.url);
102
+ }
103
+ this.setupSocket();
104
+ }
105
+ /**
106
+ * Setup event handlers for the WebSocket
107
+ */
108
+ setupSocket() {
109
+ if (hasEventEmitterAPI(this.socket)) {
110
+ this.socket.on('open', () => this.handleOpen());
111
+ this.socket.on('message', (data) => this.handleMessageData(data));
112
+ this.socket.on('error', (error) => this.notifyError(error));
113
+ this.socket.on('close', () => this.handleClose());
114
+ return;
115
+ }
116
+ this.socket.addEventListener?.('open', () => this.handleOpen());
117
+ this.socket.addEventListener?.('message', (event) => {
118
+ this.handleMessageData(event.data);
119
+ });
120
+ this.socket.addEventListener?.('error', (event) => {
121
+ const error = event.error instanceof Error ? event.error : new Error('WebSocket error');
122
+ this.notifyError(error);
123
+ });
124
+ this.socket.addEventListener?.('close', () => this.handleClose());
125
+ }
126
+ handleOpen() {
127
+ this.connected = true;
128
+ this.reconnectAttempts = 0;
129
+ if (this.reconnectTimer) {
130
+ clearTimeout(this.reconnectTimer);
131
+ this.reconnectTimer = undefined;
132
+ }
133
+ }
134
+ handleMessageData(data) {
135
+ try {
136
+ const message = parseIncomingMessage(data);
137
+ for (const handler of this.messageHandlers) {
138
+ try {
139
+ handler(message);
140
+ }
141
+ catch {
142
+ // Ignore message-handler failures to avoid breaking the transport loop.
143
+ }
144
+ }
145
+ }
146
+ catch (error) {
147
+ const err = error instanceof Error ? error : new Error(String(error));
148
+ this.notifyError(new Error(`Failed to parse message: ${err.message}`));
149
+ }
150
+ }
151
+ handleClose() {
152
+ const wasConnected = this.connected;
153
+ this.connected = false;
154
+ for (const handler of this.closeHandlers) {
155
+ try {
156
+ handler();
157
+ }
158
+ catch {
159
+ // Ignore close-handler failures.
160
+ }
161
+ }
162
+ if (this.mode === 'client' &&
163
+ this.enableReconnect &&
164
+ !this.intentionallyClosed &&
165
+ wasConnected &&
166
+ this.reconnectAttempts < this.maxReconnectAttempts) {
167
+ this.scheduleReconnect();
168
+ }
169
+ }
170
+ /**
171
+ * Schedule a reconnection attempt with exponential backoff
172
+ */
173
+ scheduleReconnect() {
174
+ if (this.reconnectTimer) {
175
+ return;
176
+ }
177
+ this.reconnectAttempts++;
178
+ const baseDelay = this.reconnectDelay * Math.pow(this.reconnectBackoffMultiplier, this.reconnectAttempts - 1);
179
+ const delay = Math.min(baseDelay, this.maxReconnectDelay);
180
+ this.reconnectTimer = setTimeout(() => {
181
+ this.reconnectTimer = undefined;
182
+ this.attemptReconnect();
183
+ }, delay);
184
+ }
185
+ /**
186
+ * Attempt to reconnect to the server
187
+ */
188
+ attemptReconnect() {
189
+ if (this.intentionallyClosed || !this.url) {
190
+ return;
191
+ }
192
+ try {
193
+ this.socket = createWebSocketClient(this.url);
194
+ this.setupSocket();
195
+ }
196
+ catch (error) {
197
+ const err = error instanceof Error ? error : new Error(String(error));
198
+ this.notifyError(new Error(`Reconnection attempt ${this.reconnectAttempts} failed: ${err.message}`));
199
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
200
+ this.scheduleReconnect();
201
+ }
202
+ }
203
+ }
204
+ /**
205
+ * Notify all error handlers
206
+ */
207
+ notifyError(error) {
208
+ for (const handler of this.errorHandlers) {
209
+ try {
210
+ handler(error);
211
+ }
212
+ catch {
213
+ // Ignore error-handler failures.
214
+ }
215
+ }
216
+ }
217
+ /**
218
+ * Send a message through the WebSocket
219
+ */
220
+ async send(message) {
221
+ if (!this.connected || this.socket.readyState !== READY_STATE_OPEN) {
222
+ throw new Error('WebSocket is not connected');
223
+ }
224
+ return new Promise((resolve, reject) => {
225
+ const data = JSON.stringify(message);
226
+ if (hasEventEmitterAPI(this.socket)) {
227
+ this.socket.send(data, (error) => {
228
+ if (error) {
229
+ reject(new Error(`Failed to send message: ${error.message}`));
230
+ return;
231
+ }
232
+ resolve();
233
+ });
234
+ return;
235
+ }
236
+ try {
237
+ this.socket.send(data);
238
+ resolve();
239
+ }
240
+ catch (error) {
241
+ const err = error instanceof Error ? error : new Error(String(error));
242
+ reject(new Error(`Failed to send message: ${err.message}`));
243
+ }
244
+ });
245
+ }
246
+ /**
247
+ * Register a handler for incoming messages
248
+ */
249
+ onMessage(handler) {
250
+ this.messageHandlers.add(handler);
251
+ return {
252
+ dispose: () => {
253
+ this.messageHandlers.delete(handler);
254
+ }
255
+ };
256
+ }
257
+ /**
258
+ * Register a handler for transport errors
259
+ */
260
+ onError(handler) {
261
+ this.errorHandlers.add(handler);
262
+ return {
263
+ dispose: () => {
264
+ this.errorHandlers.delete(handler);
265
+ }
266
+ };
267
+ }
268
+ /**
269
+ * Register a handler for transport closure
270
+ */
271
+ onClose(handler) {
272
+ this.closeHandlers.add(handler);
273
+ return {
274
+ dispose: () => {
275
+ this.closeHandlers.delete(handler);
276
+ }
277
+ };
278
+ }
279
+ /**
280
+ * Close the WebSocket connection
281
+ */
282
+ async close() {
283
+ this.intentionallyClosed = true;
284
+ if (this.reconnectTimer) {
285
+ clearTimeout(this.reconnectTimer);
286
+ this.reconnectTimer = undefined;
287
+ }
288
+ if (this.socket.readyState === READY_STATE_OPEN ||
289
+ this.socket.readyState === READY_STATE_CONNECTING) {
290
+ return new Promise((resolve) => {
291
+ const cleanup = () => {
292
+ resolve();
293
+ };
294
+ if (hasEventEmitterAPI(this.socket) && this.socket.once) {
295
+ this.socket.once('close', cleanup);
296
+ }
297
+ else {
298
+ this.socket.addEventListener?.('close', cleanup);
299
+ }
300
+ setTimeout(cleanup, 5000);
301
+ this.socket.close();
302
+ });
303
+ }
304
+ }
305
+ /**
306
+ * Check if the transport is currently connected
307
+ */
308
+ isConnected() {
309
+ return this.connected && this.socket.readyState === READY_STATE_OPEN;
310
+ }
311
+ /**
312
+ * Get the current reconnection attempt count
313
+ */
314
+ getReconnectAttempts() {
315
+ return this.reconnectAttempts;
316
+ }
317
+ /**
318
+ * Check if reconnection is enabled
319
+ */
320
+ isReconnectEnabled() {
321
+ return this.enableReconnect;
322
+ }
323
+ }
324
+ //# sourceMappingURL=websocket.js.map