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