solver-sdk 2.8.0 → 3.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 (197) hide show
  1. package/README.md +200 -368
  2. package/dist/cjs/api/chat-api/index.js +23 -49
  3. package/dist/cjs/api/chat-api/index.js.map +1 -1
  4. package/dist/cjs/api/chat-api/interfaces.js +1 -0
  5. package/dist/cjs/api/chat-api/interfaces.js.map +1 -1
  6. package/dist/cjs/api/context-api.js +6 -1
  7. package/dist/cjs/api/context-api.js.map +1 -1
  8. package/dist/cjs/api/models-api.js +43 -60
  9. package/dist/cjs/api/models-api.js.map +1 -1
  10. package/dist/cjs/api/projects-api.js +63 -293
  11. package/dist/cjs/api/projects-api.js.map +1 -1
  12. package/dist/cjs/api/search-api.js +131 -8
  13. package/dist/cjs/api/search-api.js.map +1 -1
  14. package/dist/cjs/code-solver-sdk.js +68 -322
  15. package/dist/cjs/code-solver-sdk.js.map +1 -1
  16. package/dist/cjs/index.js +3 -19
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/utils/logger.js +4 -4
  19. package/dist/cjs/utils/logger.js.map +1 -1
  20. package/dist/esm/api/chat-api/index.js +22 -48
  21. package/dist/esm/api/chat-api/index.js.map +1 -1
  22. package/dist/esm/api/chat-api/interfaces.js +1 -0
  23. package/dist/esm/api/chat-api/interfaces.js.map +1 -1
  24. package/dist/esm/api/context-api.js +6 -1
  25. package/dist/esm/api/context-api.js.map +1 -1
  26. package/dist/esm/api/models-api.js +43 -60
  27. package/dist/esm/api/models-api.js.map +1 -1
  28. package/dist/esm/api/projects-api.js +63 -293
  29. package/dist/esm/api/projects-api.js.map +1 -1
  30. package/dist/esm/api/search-api.js +131 -8
  31. package/dist/esm/api/search-api.js.map +1 -1
  32. package/dist/esm/code-solver-sdk.js +68 -322
  33. package/dist/esm/code-solver-sdk.js.map +1 -1
  34. package/dist/esm/index.js +2 -18
  35. package/dist/esm/index.js.map +1 -1
  36. package/dist/esm/utils/logger.js +3 -3
  37. package/dist/esm/utils/logger.js.map +1 -1
  38. package/dist/types/api/chat-api/index.d.ts +1 -13
  39. package/dist/types/api/chat-api/index.d.ts.map +1 -1
  40. package/dist/types/api/chat-api/interfaces.d.ts +6 -54
  41. package/dist/types/api/chat-api/interfaces.d.ts.map +1 -1
  42. package/dist/types/api/chat-api/models.d.ts +3 -26
  43. package/dist/types/api/chat-api/models.d.ts.map +1 -1
  44. package/dist/types/api/context-api.d.ts.map +1 -1
  45. package/dist/types/api/models-api.d.ts +31 -62
  46. package/dist/types/api/models-api.d.ts.map +1 -1
  47. package/dist/types/api/projects-api.d.ts +47 -126
  48. package/dist/types/api/projects-api.d.ts.map +1 -1
  49. package/dist/types/api/search-api.d.ts +147 -6
  50. package/dist/types/api/search-api.d.ts.map +1 -1
  51. package/dist/types/code-solver-sdk.d.ts +36 -86
  52. package/dist/types/code-solver-sdk.d.ts.map +1 -1
  53. package/dist/types/index.d.ts +1 -14
  54. package/dist/types/index.d.ts.map +1 -1
  55. package/dist/types/interfaces/sdk-options.d.ts +18 -66
  56. package/dist/types/interfaces/sdk-options.d.ts.map +1 -1
  57. package/dist/types/utils/logger.d.ts +3 -3
  58. package/dist/types/utils/logger.d.ts.map +1 -1
  59. package/docs/README.md +53 -37
  60. package/docs/VSCODE_INTEGRATION.md +208 -371
  61. package/docs/indexing/INDEXING.md +658 -335
  62. package/package.json +26 -23
  63. package/dist/cjs/api/agents-api.js +0 -94
  64. package/dist/cjs/api/agents-api.js.map +0 -1
  65. package/dist/cjs/api/chat-api/websocket-helpers.js +0 -211
  66. package/dist/cjs/api/chat-api/websocket-helpers.js.map +0 -1
  67. package/dist/cjs/api/dependencies-api.js +0 -286
  68. package/dist/cjs/api/dependencies-api.js.map +0 -1
  69. package/dist/cjs/constants/websocket-events.constants.js +0 -170
  70. package/dist/cjs/constants/websocket-events.constants.js.map +0 -1
  71. package/dist/cjs/constants/websocket-namespaces.constants.js +0 -22
  72. package/dist/cjs/constants/websocket-namespaces.constants.js.map +0 -1
  73. package/dist/cjs/interfaces/websocket/callbacks.interfaces.js +0 -3
  74. package/dist/cjs/interfaces/websocket/callbacks.interfaces.js.map +0 -1
  75. package/dist/cjs/interfaces/websocket/client-options.interfaces.js +0 -3
  76. package/dist/cjs/interfaces/websocket/client-options.interfaces.js.map +0 -1
  77. package/dist/cjs/interfaces/websocket/events.interfaces.js +0 -3
  78. package/dist/cjs/interfaces/websocket/events.interfaces.js.map +0 -1
  79. package/dist/cjs/interfaces/websocket/vscode-command.interfaces.js +0 -42
  80. package/dist/cjs/interfaces/websocket/vscode-command.interfaces.js.map +0 -1
  81. package/dist/cjs/simple-indexing-client.js +0 -138
  82. package/dist/cjs/simple-indexing-client.js.map +0 -1
  83. package/dist/cjs/utils/code-solver-websocket-client.js +0 -497
  84. package/dist/cjs/utils/code-solver-websocket-client.js.map +0 -1
  85. package/dist/cjs/utils/connection-state-manager.js +0 -133
  86. package/dist/cjs/utils/connection-state-manager.js.map +0 -1
  87. package/dist/cjs/utils/indexing-websocket-client.js +0 -107
  88. package/dist/cjs/utils/indexing-websocket-client.js.map +0 -1
  89. package/dist/cjs/utils/session-manager.js +0 -114
  90. package/dist/cjs/utils/session-manager.js.map +0 -1
  91. package/dist/cjs/utils/simple-connection-monitor.js +0 -52
  92. package/dist/cjs/utils/simple-connection-monitor.js.map +0 -1
  93. package/dist/cjs/utils/websocket-client.js +0 -638
  94. package/dist/cjs/utils/websocket-client.js.map +0 -1
  95. package/dist/cjs/ws/base-ws-client.js +0 -280
  96. package/dist/cjs/ws/base-ws-client.js.map +0 -1
  97. package/dist/cjs/ws/dependencies-ws-client.js +0 -11
  98. package/dist/cjs/ws/dependencies-ws-client.js.map +0 -1
  99. package/dist/cjs/ws/file-editing-ws-client.js +0 -162
  100. package/dist/cjs/ws/file-editing-ws-client.js.map +0 -1
  101. package/dist/cjs/ws/filesystem-ws-client.js +0 -305
  102. package/dist/cjs/ws/filesystem-ws-client.js.map +0 -1
  103. package/dist/cjs/ws/indexing-ws-client.js +0 -275
  104. package/dist/cjs/ws/indexing-ws-client.js.map +0 -1
  105. package/dist/cjs/ws/notifications-ws-client.js +0 -12
  106. package/dist/cjs/ws/notifications-ws-client.js.map +0 -1
  107. package/dist/esm/api/agents-api.js +0 -90
  108. package/dist/esm/api/agents-api.js.map +0 -1
  109. package/dist/esm/api/chat-api/websocket-helpers.js +0 -205
  110. package/dist/esm/api/chat-api/websocket-helpers.js.map +0 -1
  111. package/dist/esm/api/dependencies-api.js +0 -282
  112. package/dist/esm/api/dependencies-api.js.map +0 -1
  113. package/dist/esm/constants/websocket-events.constants.js +0 -167
  114. package/dist/esm/constants/websocket-events.constants.js.map +0 -1
  115. package/dist/esm/constants/websocket-namespaces.constants.js +0 -19
  116. package/dist/esm/constants/websocket-namespaces.constants.js.map +0 -1
  117. package/dist/esm/interfaces/websocket/callbacks.interfaces.js +0 -2
  118. package/dist/esm/interfaces/websocket/callbacks.interfaces.js.map +0 -1
  119. package/dist/esm/interfaces/websocket/client-options.interfaces.js +0 -2
  120. package/dist/esm/interfaces/websocket/client-options.interfaces.js.map +0 -1
  121. package/dist/esm/interfaces/websocket/events.interfaces.js +0 -2
  122. package/dist/esm/interfaces/websocket/events.interfaces.js.map +0 -1
  123. package/dist/esm/interfaces/websocket/vscode-command.interfaces.js +0 -39
  124. package/dist/esm/interfaces/websocket/vscode-command.interfaces.js.map +0 -1
  125. package/dist/esm/simple-indexing-client.js +0 -134
  126. package/dist/esm/simple-indexing-client.js.map +0 -1
  127. package/dist/esm/utils/code-solver-websocket-client.js +0 -492
  128. package/dist/esm/utils/code-solver-websocket-client.js.map +0 -1
  129. package/dist/esm/utils/connection-state-manager.js +0 -129
  130. package/dist/esm/utils/connection-state-manager.js.map +0 -1
  131. package/dist/esm/utils/indexing-websocket-client.js +0 -103
  132. package/dist/esm/utils/indexing-websocket-client.js.map +0 -1
  133. package/dist/esm/utils/session-manager.js +0 -109
  134. package/dist/esm/utils/session-manager.js.map +0 -1
  135. package/dist/esm/utils/simple-connection-monitor.js +0 -48
  136. package/dist/esm/utils/simple-connection-monitor.js.map +0 -1
  137. package/dist/esm/utils/websocket-client.js +0 -634
  138. package/dist/esm/utils/websocket-client.js.map +0 -1
  139. package/dist/esm/ws/base-ws-client.js +0 -276
  140. package/dist/esm/ws/base-ws-client.js.map +0 -1
  141. package/dist/esm/ws/dependencies-ws-client.js +0 -7
  142. package/dist/esm/ws/dependencies-ws-client.js.map +0 -1
  143. package/dist/esm/ws/file-editing-ws-client.js +0 -158
  144. package/dist/esm/ws/file-editing-ws-client.js.map +0 -1
  145. package/dist/esm/ws/filesystem-ws-client.js +0 -301
  146. package/dist/esm/ws/filesystem-ws-client.js.map +0 -1
  147. package/dist/esm/ws/indexing-ws-client.js +0 -271
  148. package/dist/esm/ws/indexing-ws-client.js.map +0 -1
  149. package/dist/esm/ws/notifications-ws-client.js +0 -8
  150. package/dist/esm/ws/notifications-ws-client.js.map +0 -1
  151. package/dist/types/api/agents-api.d.ts +0 -141
  152. package/dist/types/api/agents-api.d.ts.map +0 -1
  153. package/dist/types/api/chat-api/websocket-helpers.d.ts +0 -40
  154. package/dist/types/api/chat-api/websocket-helpers.d.ts.map +0 -1
  155. package/dist/types/api/dependencies-api.d.ts +0 -109
  156. package/dist/types/api/dependencies-api.d.ts.map +0 -1
  157. package/dist/types/constants/websocket-events.constants.d.ts +0 -144
  158. package/dist/types/constants/websocket-events.constants.d.ts.map +0 -1
  159. package/dist/types/constants/websocket-namespaces.constants.d.ts +0 -17
  160. package/dist/types/constants/websocket-namespaces.constants.d.ts.map +0 -1
  161. package/dist/types/interfaces/websocket/callbacks.interfaces.d.ts +0 -30
  162. package/dist/types/interfaces/websocket/callbacks.interfaces.d.ts.map +0 -1
  163. package/dist/types/interfaces/websocket/client-options.interfaces.d.ts +0 -51
  164. package/dist/types/interfaces/websocket/client-options.interfaces.d.ts.map +0 -1
  165. package/dist/types/interfaces/websocket/events.interfaces.d.ts +0 -165
  166. package/dist/types/interfaces/websocket/events.interfaces.d.ts.map +0 -1
  167. package/dist/types/interfaces/websocket/vscode-command.interfaces.d.ts +0 -56
  168. package/dist/types/interfaces/websocket/vscode-command.interfaces.d.ts.map +0 -1
  169. package/dist/types/simple-indexing-client.d.ts +0 -66
  170. package/dist/types/simple-indexing-client.d.ts.map +0 -1
  171. package/dist/types/utils/code-solver-websocket-client.d.ts +0 -144
  172. package/dist/types/utils/code-solver-websocket-client.d.ts.map +0 -1
  173. package/dist/types/utils/connection-state-manager.d.ts +0 -94
  174. package/dist/types/utils/connection-state-manager.d.ts.map +0 -1
  175. package/dist/types/utils/indexing-websocket-client.d.ts +0 -123
  176. package/dist/types/utils/indexing-websocket-client.d.ts.map +0 -1
  177. package/dist/types/utils/session-manager.d.ts +0 -98
  178. package/dist/types/utils/session-manager.d.ts.map +0 -1
  179. package/dist/types/utils/simple-connection-monitor.d.ts +0 -26
  180. package/dist/types/utils/simple-connection-monitor.d.ts.map +0 -1
  181. package/dist/types/utils/websocket-client.d.ts +0 -233
  182. package/dist/types/utils/websocket-client.d.ts.map +0 -1
  183. package/dist/types/ws/base-ws-client.d.ts +0 -119
  184. package/dist/types/ws/base-ws-client.d.ts.map +0 -1
  185. package/dist/types/ws/dependencies-ws-client.d.ts +0 -6
  186. package/dist/types/ws/dependencies-ws-client.d.ts.map +0 -1
  187. package/dist/types/ws/file-editing-ws-client.d.ts +0 -85
  188. package/dist/types/ws/file-editing-ws-client.d.ts.map +0 -1
  189. package/dist/types/ws/filesystem-ws-client.d.ts +0 -201
  190. package/dist/types/ws/filesystem-ws-client.d.ts.map +0 -1
  191. package/dist/types/ws/indexing-ws-client.d.ts +0 -94
  192. package/dist/types/ws/indexing-ws-client.d.ts.map +0 -1
  193. package/dist/types/ws/notifications-ws-client.d.ts +0 -5
  194. package/dist/types/ws/notifications-ws-client.d.ts.map +0 -1
  195. package/docs/ARCHITECTURE.md +0 -268
  196. package/docs/QUICK_START.md +0 -126
  197. package/docs/WEBSOCKET.md +0 -472
@@ -1,634 +0,0 @@
1
- // Импортируем Socket.IO клиент
2
- import { io } from 'socket.io-client';
3
- /**
4
- * Базовый класс для WebSocket клиентов, реализованный на базе Socket.IO
5
- */
6
- export class WebSocketClient {
7
- /**
8
- * Создает новый WebSocket клиент
9
- * @param {string} url URL для подключения
10
- * @param {WebSocketClientOptions} [options] Опции клиента
11
- */
12
- constructor(url, options = {}) {
13
- /** Экземпляр Socket.IO */
14
- this.socket = null;
15
- /** Счетчик попыток переподключения */
16
- this.retryCount = 0;
17
- /** Флаг, указывающий, что соединение было закрыто намеренно */
18
- this.intentionallyClosed = false;
19
- /** Таймер переподключения */
20
- this.reconnectTimer = null;
21
- /** Таймер таймаута соединения */
22
- this.connectionTimeoutTimer = null;
23
- /** Обработчики событий */
24
- this.eventHandlers = {};
25
- /** Очередь сообщений для отправки после подключения */
26
- this.messageQueue = [];
27
- /** Состояние соединения */
28
- this.connected = false;
29
- /** Аутентифицировано ли соединение */
30
- this.authenticated = false;
31
- /** ID сокета */
32
- this.socketId = null;
33
- /** Хранилище ожидающих callback-функций */
34
- this._pendingCallbacks = new Map();
35
- /** Таймер проверки состояния соединения */
36
- this.healthCheckTimer = null;
37
- /** Время последнего полученного pong */
38
- this.lastPongTimestamp = 0;
39
- /** Интервал проверки здоровья соединения */
40
- this.healthCheckInterval = 10000;
41
- /**
42
- * Тип для хранения отложенных обработчиков событий
43
- * @private
44
- */
45
- this._pendingCallbackHandlers = new Map();
46
- this.url = url;
47
- this.options = {
48
- headers: options.headers || {},
49
- connectionTimeout: options.connectionTimeout || 30000,
50
- protocols: options.protocols || [],
51
- maxRetries: options.maxRetries || 5,
52
- retryDelay: options.retryDelay || 1000,
53
- maxRetryDelay: options.maxRetryDelay || 30000,
54
- autoReconnect: options.autoReconnect !== undefined ? options.autoReconnect : true,
55
- rejectUnauthorized: options.rejectUnauthorized !== undefined ? options.rejectUnauthorized : true,
56
- apiKey: options.apiKey || '',
57
- namespace: options.namespace || '',
58
- logger: options.logger,
59
- pingInterval: options.pingInterval || 25000,
60
- pingTimeout: options.pingTimeout || 60000,
61
- debug: options.debug || false
62
- };
63
- // Определяем среду выполнения
64
- this.isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
65
- // Инициализируем пространство имен
66
- this.namespace = this.options.namespace || '';
67
- // Если namespace не начинается с /, добавляем его
68
- if (this.namespace && !this.namespace.startsWith('/')) {
69
- this.namespace = '/' + this.namespace;
70
- }
71
- // Инициализируем логгер
72
- this.logger = this.options.logger || ((level, message, data) => {
73
- if (level === 'error') {
74
- console.error(`[WebSocketClient] ${message}`, data);
75
- }
76
- else if (level === 'warn') {
77
- console.warn(`[WebSocketClient] ${message}`, data);
78
- }
79
- else if (level === 'info') {
80
- console.info(`[WebSocketClient] ${message}`, data);
81
- }
82
- else if (level === 'debug' && process.env.NODE_ENV === 'development') {
83
- console.debug(`[WebSocketClient] ${message}`, data);
84
- }
85
- });
86
- // Логирование конфигурации при создании клиента
87
- this.logger('info', 'Создан WebSocket клиент', {
88
- url: this.url,
89
- namespace: this.namespace,
90
- hasApiKey: !!this.options.apiKey,
91
- apiKeyLength: this.options.apiKey ? this.options.apiKey.length : 0,
92
- connectionTimeout: this.options.connectionTimeout,
93
- autoReconnect: this.options.autoReconnect,
94
- maxRetries: this.options.maxRetries
95
- });
96
- }
97
- /**
98
- * Получает WebSocket URL из HTTP URL
99
- * @returns {string} WebSocket URL
100
- * @private
101
- */
102
- getWebSocketURL() {
103
- let wsUrl = this.url;
104
- // Замена протокола
105
- if (wsUrl.startsWith('http://')) {
106
- wsUrl = wsUrl.replace('http://', 'ws://');
107
- }
108
- else if (wsUrl.startsWith('https://')) {
109
- wsUrl = wsUrl.replace('https://', 'wss://');
110
- }
111
- else if (!wsUrl.startsWith('ws://') && !wsUrl.startsWith('wss://')) {
112
- // Если URL не содержит протокол, добавляем ws://
113
- wsUrl = 'ws://' + wsUrl;
114
- }
115
- // Удаляем слеш в конце URL если он есть
116
- if (wsUrl.endsWith('/')) {
117
- wsUrl = wsUrl.slice(0, -1);
118
- }
119
- return wsUrl;
120
- }
121
- /**
122
- * Подключается к WebSocket серверу используя Socket.IO клиент
123
- * @returns {Promise<void>}
124
- */
125
- connect() {
126
- // Если соединение уже установлено, возвращаем Promise.resolve
127
- if (this.isConnected()) {
128
- this.logger('debug', 'Соединение уже установлено, пропускаем повторное подключение');
129
- return Promise.resolve();
130
- }
131
- // Сбрасываем таймер reconnect
132
- if (this.reconnectTimer) {
133
- clearTimeout(this.reconnectTimer);
134
- this.reconnectTimer = null;
135
- }
136
- return new Promise((resolve, reject) => {
137
- try {
138
- // Получаем WebSocket URL из http/https URL
139
- const wsUrl = this.getWebSocketURL();
140
- const namespaceStr = this.options.namespace || '';
141
- this.logger('debug', `Подключение к ${wsUrl}${namespaceStr}`);
142
- // Настройки для Socket.IO клиента
143
- const socketOptions = {
144
- path: '/socket.io', // Устанавливаем путь без слеша в конце
145
- transports: ['websocket', 'polling'], // Поддерживаем оба транспорта
146
- reconnection: this.options.autoReconnect, // Автоматическое переподключение
147
- reconnectionAttempts: this.options.maxRetries, // Количество попыток
148
- reconnectionDelay: this.options.retryDelay, // Задержка между попытками
149
- timeout: this.options.connectionTimeout, // Таймаут соединения
150
- forceNew: true, // Создавать новое соединение
151
- extraHeaders: this.options.headers, // HTTP заголовки
152
- rejectUnauthorized: this.options.rejectUnauthorized, // Проверка сертификатов
153
- pingTimeout: this.options.pingTimeout, // Явно устанавливаем таймаут для ping
154
- pingInterval: this.options.pingInterval, // Явно устанавливаем интервал ping
155
- debug: this.options.debug
156
- };
157
- // Если указан API ключ, добавляем его в query и auth
158
- if (this.options.apiKey) {
159
- socketOptions.auth = { token: this.options.apiKey };
160
- socketOptions.query = { token: this.options.apiKey };
161
- }
162
- // Создаем Socket.IO клиент с namespace
163
- this.socket = io(wsUrl + namespaceStr, socketOptions);
164
- // Устанавливаем таймаут соединения
165
- this.connectionTimeoutTimer = setTimeout(() => {
166
- if (this.socket && !this.socket.connected) {
167
- const error = new Error('Таймаут подключения WebSocket');
168
- this.logger('error', 'Превышен таймаут подключения', { timeout: this.options.connectionTimeout });
169
- reject(error);
170
- this.close();
171
- }
172
- }, this.options.connectionTimeout);
173
- // Обработчик успешного подключения
174
- this.socket.on('connect', () => {
175
- clearTimeout(this.connectionTimeoutTimer);
176
- this.retryCount = 0;
177
- this.connected = true;
178
- this.socketId = this.socket?.id || null;
179
- this.logger('info', 'WebSocket соединение установлено', { socketId: this.socketId });
180
- // Отладка Socket.IO handshake
181
- const engine = this.socket ? this.socket.io?.engine : null;
182
- if (engine) {
183
- this.logger('debug', 'Socket.IO engine настройки:', {
184
- pingInterval: engine.pingInterval,
185
- pingTimeout: engine.pingTimeout,
186
- transport: engine.transport?.name
187
- });
188
- // Отслеживаем ping-pong обмен
189
- engine.on('ping', () => {
190
- this.logger('debug', 'Socket.IO engine отправил ping');
191
- // Явно пытаемся стимулировать ответ pong от сервера
192
- if (this.socket && this.socket.connected) {
193
- // Отправляем простое эхо-событие, чтобы сервер отреагировал
194
- this.socket.emit('_ping_check', { timestamp: Date.now() });
195
- }
196
- });
197
- engine.on('pong', () => {
198
- this.logger('debug', 'Socket.IO engine получил pong');
199
- // Сбрасываем флаг неактивности
200
- this.lastPongTimestamp = Date.now();
201
- });
202
- // Ловим ошибки транспорта
203
- if (engine.transport) {
204
- engine.transport.on('error', (err) => {
205
- this.logger('error', `Socket.IO transport ошибка: ${err.message}`, err);
206
- });
207
- // При смене транспорта
208
- engine.on('upgrade', (transport) => {
209
- this.logger('info', `Socket.IO transport обновлен до ${transport.name}`);
210
- });
211
- // При отключении по таймауту
212
- engine.on('close', (reason) => {
213
- this.logger('warn', `Socket.IO engine закрыт по причине: ${reason}`);
214
- if (reason === 'ping timeout') {
215
- this.logger('error', 'Соединение потеряно из-за таймаута ping-pong обмена!');
216
- // Запускаем процесс переподключения, если это необходимо
217
- if (this.options.autoReconnect && !this.intentionallyClosed) {
218
- this.reconnect();
219
- }
220
- }
221
- });
222
- }
223
- }
224
- // Отслеживаем серверные события ping/pong
225
- if (this.socket) {
226
- this.socket.on('_ping', (data, callback) => {
227
- this.logger('debug', 'Получен _ping от сервера');
228
- if (typeof callback === 'function') {
229
- callback({ pong: true, clientTime: Date.now() });
230
- }
231
- });
232
- }
233
- // Устанавливаем поллинг для проверки состояния соединения
234
- this.setupConnectionHealthCheck();
235
- // Отправляем сообщения из очереди
236
- while (this.messageQueue.length > 0) {
237
- const message = this.messageQueue.shift();
238
- if (message && this.socket && this.socket.connected) {
239
- if (typeof message === 'object' && message.event) {
240
- this.socket.emit(message.event, message.data);
241
- }
242
- else {
243
- // Поддержка старого формата сообщений
244
- this.socket.send(message);
245
- }
246
- }
247
- }
248
- resolve();
249
- this.dispatchEvent('open', {});
250
- });
251
- // Обработчик ошибок соединения
252
- this.socket.on('connect_error', (error) => {
253
- clearTimeout(this.connectionTimeoutTimer);
254
- this.logger('error', 'Ошибка соединения WebSocket', {
255
- message: error.message,
256
- name: error.name,
257
- stack: error.stack
258
- });
259
- this.dispatchEvent('error', error);
260
- if (!this.connected) {
261
- reject(new Error('Ошибка подключения WebSocket'));
262
- }
263
- });
264
- // Обработчик закрытия соединения
265
- this.socket.on('disconnect', (reason) => {
266
- clearTimeout(this.connectionTimeoutTimer);
267
- this.connected = false;
268
- this.logger('info', `WebSocket соединение закрыто: ${reason}`);
269
- // Формируем объект события для совместимости с WebSocket API
270
- const closeEvent = {
271
- code: this.getCloseCodeFromReason(reason),
272
- reason: reason
273
- };
274
- this.dispatchEvent('close', closeEvent);
275
- // Если соединение было закрыто намеренно, не пытаемся переподключиться
276
- if (this.intentionallyClosed) {
277
- return;
278
- }
279
- });
280
- // Обработчик всех сообщений, используем 'message' для совместимости
281
- this.socket.onAny((eventName, ...args) => {
282
- // Отправляем в обработчик события по имени события
283
- this.dispatchEvent(eventName, args.length === 1 ? args[0] : args);
284
- // Также отправляем событие message для совместимости
285
- this.dispatchEvent('message', {
286
- event: eventName,
287
- data: args.length === 1 ? args[0] : args
288
- });
289
- });
290
- }
291
- catch (error) {
292
- clearTimeout(this.connectionTimeoutTimer);
293
- this.logger('error', 'Ошибка при создании Socket.IO клиента', error);
294
- reject(error);
295
- }
296
- });
297
- }
298
- /**
299
- * Получает код закрытия WebSocket из строки причины Socket.IO
300
- * @param {string} reason Причина закрытия Socket.IO
301
- * @returns {number} Код закрытия WebSocket
302
- * @private
303
- */
304
- getCloseCodeFromReason(reason) {
305
- switch (reason) {
306
- case 'io server disconnect':
307
- return 1000; // Нормальное закрытие соединения сервером
308
- case 'io client disconnect':
309
- return 1000; // Нормальное закрытие соединения клиентом
310
- case 'ping timeout':
311
- return 1001; // Выход из соединения по таймауту
312
- case 'transport close':
313
- return 1006; // Аномальное закрытие соединения
314
- case 'transport error':
315
- return 1002; // Протокольная ошибка
316
- default:
317
- return 1000; // По умолчанию - нормальное закрытие
318
- }
319
- }
320
- /**
321
- * Настраивает проверку состояния соединения для обнаружения "зависших" подключений
322
- * @private
323
- */
324
- setupConnectionHealthCheck() {
325
- // Очищаем предыдущий таймер, если он был
326
- if (this.healthCheckTimer) {
327
- clearInterval(this.healthCheckTimer);
328
- this.healthCheckTimer = null;
329
- }
330
- // Устанавливаем начальное время pong
331
- this.lastPongTimestamp = Date.now();
332
- // Создаем новый таймер для регулярной проверки
333
- this.healthCheckTimer = setInterval(() => {
334
- if (!this.socket || !this.connected)
335
- return;
336
- const now = Date.now();
337
- const lastPongAge = now - this.lastPongTimestamp;
338
- // Если прошло больше 2*pingInterval мс с последнего pong, возможно соединение зависло
339
- if (lastPongAge > 2 * (this.options.pingInterval || 25000)) {
340
- this.logger('warn', `Возможно зависшее соединение: ${lastPongAge}ms с последнего pong`);
341
- // Отправляем тестовое сообщение для проверки соединения
342
- const socket = this.socket; // Сохраняем ссылку на сокет в переменную
343
- if (socket && socket.connected) {
344
- socket.emit('_health_check', { timestamp: now }, (response) => {
345
- if (response && response.success) {
346
- this.logger('debug', 'Соединение активно, получен ответ на _health_check');
347
- this.lastPongTimestamp = Date.now();
348
- }
349
- });
350
- }
351
- }
352
- }, this.healthCheckInterval);
353
- }
354
- /**
355
- * Останавливает проверку состояния соединения
356
- * @private
357
- */
358
- stopConnectionHealthCheck() {
359
- if (this.healthCheckTimer) {
360
- clearInterval(this.healthCheckTimer);
361
- this.healthCheckTimer = null;
362
- }
363
- }
364
- /**
365
- * Закрывает соединение WebSocket
366
- * @param {number} code Код закрытия
367
- * @param {string} reason Причина закрытия
368
- */
369
- close(code = 1000, reason = 'Closed by client') {
370
- this.intentionallyClosed = true;
371
- // Останавливаем проверку здоровья соединения
372
- this.stopConnectionHealthCheck();
373
- // Очищаем таймеры
374
- if (this.reconnectTimer) {
375
- clearTimeout(this.reconnectTimer);
376
- this.reconnectTimer = null;
377
- }
378
- if (this.connectionTimeoutTimer) {
379
- clearTimeout(this.connectionTimeoutTimer);
380
- this.connectionTimeoutTimer = null;
381
- }
382
- // Закрываем соединение
383
- if (this.socket) {
384
- this.logger('info', 'Закрытие WebSocket соединения', { code, reason });
385
- if (this.socket.connected) {
386
- this.socket.disconnect();
387
- }
388
- this.connected = false;
389
- this.socket = null;
390
- }
391
- }
392
- /**
393
- * Отправляет сообщение в WebSocket
394
- * @param {any} data Данные для отправки
395
- * @returns {boolean} Успешно ли отправлено сообщение
396
- */
397
- send(data) {
398
- try {
399
- // Если соединение еще не установлено, добавляем сообщение в очередь
400
- if (!this.socket || !this.socket.connected) {
401
- this.messageQueue.push(data);
402
- return true;
403
- }
404
- // Обработка разных типов сообщений для совместимости
405
- if (typeof data === 'object') {
406
- if (data.event) {
407
- // Формат { event: 'event_name', data: {} }
408
- this.socket.emit(data.event, data.data);
409
- }
410
- else if (data.type && data.type === '2' && data.data && Array.isArray(data.data)) {
411
- // Socket.IO тип пакета '2' - событие с данными
412
- // Формат { type: '2', nsp: '/namespace', data: ['event_name', {}] }
413
- const eventName = data.data[0];
414
- const eventData = data.data.length > 1 ? data.data[1] : null;
415
- this.socket.emit(eventName, eventData);
416
- }
417
- else {
418
- // Обычные объекты отправляем через 'message'
419
- this.socket.emit('message', data);
420
- }
421
- }
422
- else {
423
- // Строки, бинарные данные и т.д.
424
- this.socket.send(data);
425
- }
426
- return true;
427
- }
428
- catch (error) {
429
- this.logger('error', 'Ошибка при отправке сообщения', error);
430
- return false;
431
- }
432
- }
433
- /**
434
- * Отправляет событие с данными и ожидает ответа с помощью Promise
435
- * @param {string} event Название события
436
- * @param {any} data Данные события
437
- * @param {number} [timeout=5000] Таймаут ожидания ответа в мс
438
- * @returns {Promise<any>} Promise с ответом
439
- */
440
- emitWithAck(event, data, timeout = 5000) {
441
- return new Promise((resolve, reject) => {
442
- if (!this.socket || !this.socket.connected) {
443
- reject(new Error('WebSocket не подключен'));
444
- return;
445
- }
446
- try {
447
- // Используем встроенный механизм acknowledgements в Socket.IO
448
- this.socket.timeout(timeout).emit(event, data, (err, response) => {
449
- if (err) {
450
- reject(err);
451
- }
452
- else {
453
- resolve(response);
454
- }
455
- });
456
- }
457
- catch (error) {
458
- reject(error);
459
- }
460
- });
461
- }
462
- /**
463
- * Добавляет обработчик события
464
- * @param {string} eventType Тип события
465
- * @param {WebSocketEventHandler} handler Обработчик события
466
- */
467
- on(eventType, handler) {
468
- if (!this.eventHandlers[eventType]) {
469
- this.eventHandlers[eventType] = [];
470
- }
471
- this.eventHandlers[eventType].push(handler);
472
- // Если соединение уже установлено, добавляем обработчик для Socket.IO
473
- if (this.socket && this.socket.connected && eventType !== 'open' && eventType !== 'close') {
474
- // Не добавляем обработчики для 'open' и 'close', так как они обрабатываются
475
- // через 'connect' и 'disconnect' в методе connect()
476
- this.socket.on(eventType, handler);
477
- }
478
- }
479
- /**
480
- * Удаляет обработчик события
481
- * @param {string} eventType Тип события
482
- * @param {WebSocketEventHandler} [handler] Обработчик события (если не указан, удаляются все обработчики)
483
- */
484
- off(eventType, handler) {
485
- if (!this.eventHandlers[eventType]) {
486
- return;
487
- }
488
- if (handler) {
489
- // Удаляем конкретный обработчик
490
- const index = this.eventHandlers[eventType].indexOf(handler);
491
- if (index !== -1) {
492
- this.eventHandlers[eventType].splice(index, 1);
493
- }
494
- // Также удаляем обработчик из Socket.IO, если соединение установлено
495
- if (this.socket && this.socket.connected) {
496
- this.socket.off(eventType, handler);
497
- }
498
- }
499
- else {
500
- // Удаляем все обработчики для данного типа события
501
- delete this.eventHandlers[eventType];
502
- // Также удаляем все обработчики из Socket.IO, если соединение установлено
503
- if (this.socket && this.socket.connected) {
504
- this.socket.off(eventType);
505
- }
506
- }
507
- }
508
- /**
509
- * Отправляет событие в обработчики
510
- * @param {string} eventType Тип события
511
- * @param {any} data Данные события
512
- * @private
513
- */
514
- dispatchEvent(eventType, data) {
515
- if (!this.eventHandlers[eventType]) {
516
- return;
517
- }
518
- for (const handler of this.eventHandlers[eventType]) {
519
- try {
520
- handler(data);
521
- }
522
- catch (error) {
523
- this.logger('error', `Ошибка в обработчике события '${eventType}'`, error);
524
- }
525
- }
526
- }
527
- /**
528
- * Возвращает текущий статус соединения
529
- * @returns {boolean} Подключен ли клиент
530
- */
531
- isConnected() {
532
- return this.socket !== null && this.socket.connected;
533
- }
534
- /**
535
- * Выполняет принудительное переподключение
536
- * @returns {Promise<void>} Promise без результата
537
- */
538
- async reconnect() {
539
- // Если соединение уже установлено, сначала закрываем его
540
- if (this.socket && this.socket.connected) {
541
- this.close();
542
- }
543
- // Сбрасываем флаг намеренного закрытия для возможности переподключения
544
- this.intentionallyClosed = false;
545
- // Устанавливаем новое соединение
546
- return this.connect();
547
- }
548
- /**
549
- * Отправляет событие (алиас для более удобного использования)
550
- * @param {string} eventName Название события
551
- * @param {any} data Данные события
552
- * @returns {boolean} Успешно ли отправлено событие
553
- */
554
- emit(eventName, data) {
555
- return this.send({ event: eventName, data });
556
- }
557
- /**
558
- * Возвращает ID сокета, если соединение установлено
559
- * @returns {string|null} ID сокета или null, если соединение не установлено
560
- */
561
- getSocketId() {
562
- return this.socket?.id || null;
563
- }
564
- /**
565
- * Устанавливает функцию логирования
566
- * @param {Function} loggerFn Функция для логирования
567
- */
568
- setLogger(loggerFn) {
569
- this.logger = loggerFn;
570
- }
571
- /**
572
- * Регистрирует обработчик события, который будет вызван один раз и удален
573
- * @param {string} event Название события
574
- * @param {WebSocketEventHandler} handler Обработчик события
575
- * @returns {void}
576
- */
577
- once(event, handler) {
578
- // Если есть нативная реализация в Socket.IO, используем её
579
- if (this.socket && this.socket.connected) {
580
- this.socket.once(event, handler);
581
- return;
582
- }
583
- // Создаем обертку, которая удалит обработчик после первого вызова
584
- const wrapperHandler = (data) => {
585
- // Удаляем обработчик
586
- this.off(event, wrapperHandler);
587
- // Вызываем оригинальный обработчик
588
- handler(data);
589
- };
590
- // Регистрируем обертку
591
- this.on(event, wrapperHandler);
592
- }
593
- /**
594
- * Отправляет событие Socket.IO через WebSocket соединение
595
- * @param {string} event Имя события
596
- * @param {any} data Данные события
597
- * @param {(response: any) => void} [callback] Функция обратного вызова для получения ответа
598
- * @param {string} [namespace=''] Namespace для Socket.IO
599
- * @returns {boolean} Успешно ли отправлено сообщение
600
- */
601
- sendSocketIOEvent(event, data, callback, namespace = '') {
602
- // Если нет соединения, сразу возвращаем false
603
- if (!this.socket || !this.socket.connected) {
604
- this.logger('error', 'Нельзя отправить событие: WebSocket не подключен');
605
- return false;
606
- }
607
- try {
608
- // Проверяем, нужно ли использовать другой namespace
609
- let targetSocket = this.socket;
610
- // Если указан другой namespace, используем его
611
- if (namespace && namespace !== this.namespace) {
612
- const nsSocket = io(this.url + namespace, {
613
- forceNew: false,
614
- auth: { token: this.options.apiKey }
615
- });
616
- targetSocket = nsSocket;
617
- }
618
- // Отправляем событие с callback, если он указан
619
- if (callback) {
620
- targetSocket.emit(event, data, callback);
621
- }
622
- else {
623
- targetSocket.emit(event, data);
624
- }
625
- this.logger('debug', `Отправлено Socket.IO событие ${event}`, { hasData: !!data, namespace });
626
- return true;
627
- }
628
- catch (error) {
629
- this.logger('error', `Ошибка при отправке Socket.IO события ${event}`, error);
630
- return false;
631
- }
632
- }
633
- }
634
- //# sourceMappingURL=websocket-client.js.map