@theia/core 1.43.1 → 1.45.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 (320) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +10 -3
  3. package/i18n/nls.de.json +10 -3
  4. package/i18n/nls.es.json +10 -3
  5. package/i18n/nls.fr.json +10 -3
  6. package/i18n/nls.hu.json +10 -3
  7. package/i18n/nls.it.json +10 -3
  8. package/i18n/nls.ja.json +10 -3
  9. package/i18n/nls.json +10 -3
  10. package/i18n/nls.pl.json +10 -3
  11. package/i18n/nls.pt-br.json +10 -3
  12. package/i18n/nls.pt-pt.json +10 -3
  13. package/i18n/nls.ru.json +10 -3
  14. package/i18n/nls.zh-cn.json +10 -3
  15. package/lib/browser/common-frontend-contribution.d.ts +10 -0
  16. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  17. package/lib/browser/common-frontend-contribution.js +68 -10
  18. package/lib/browser/common-frontend-contribution.js.map +1 -1
  19. package/lib/browser/connection-status-service.d.ts +2 -2
  20. package/lib/browser/connection-status-service.d.ts.map +1 -1
  21. package/lib/browser/connection-status-service.js +3 -3
  22. package/lib/browser/connection-status-service.js.map +1 -1
  23. package/lib/browser/connection-status-service.spec.js +6 -6
  24. package/lib/browser/connection-status-service.spec.js.map +1 -1
  25. package/lib/browser/core-preferences.d.ts.map +1 -1
  26. package/lib/browser/core-preferences.js +16 -0
  27. package/lib/browser/core-preferences.js.map +1 -1
  28. package/lib/browser/dialogs.d.ts +0 -1
  29. package/lib/browser/dialogs.d.ts.map +1 -1
  30. package/lib/browser/dialogs.js +1 -34
  31. package/lib/browser/dialogs.js.map +1 -1
  32. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  33. package/lib/browser/frontend-application-module.js +4 -0
  34. package/lib/browser/frontend-application-module.js.map +1 -1
  35. package/lib/browser/icon-theme-contribution.d.ts +1 -0
  36. package/lib/browser/icon-theme-contribution.d.ts.map +1 -1
  37. package/lib/browser/icon-theme-contribution.js +1 -0
  38. package/lib/browser/icon-theme-contribution.js.map +1 -1
  39. package/lib/browser/icon-theme-service.d.ts +1 -0
  40. package/lib/browser/icon-theme-service.d.ts.map +1 -1
  41. package/lib/browser/icon-theme-service.js.map +1 -1
  42. package/lib/browser/language-icon-provider.d.ts +15 -0
  43. package/lib/browser/language-icon-provider.d.ts.map +1 -0
  44. package/lib/browser/language-icon-provider.js +74 -0
  45. package/lib/browser/language-icon-provider.js.map +1 -0
  46. package/lib/browser/language-service.d.ts +22 -0
  47. package/lib/browser/language-service.d.ts.map +1 -1
  48. package/lib/browser/language-service.js +28 -0
  49. package/lib/browser/language-service.js.map +1 -1
  50. package/lib/browser/messaging/connection-source.d.ts +9 -0
  51. package/lib/browser/messaging/connection-source.d.ts.map +1 -0
  52. package/lib/browser/messaging/connection-source.js +20 -0
  53. package/lib/browser/messaging/connection-source.js.map +1 -0
  54. package/lib/browser/messaging/frontend-id-provider.d.ts +13 -0
  55. package/lib/browser/messaging/frontend-id-provider.d.ts.map +1 -0
  56. package/lib/browser/messaging/frontend-id-provider.js +40 -0
  57. package/lib/browser/messaging/frontend-id-provider.js.map +1 -0
  58. package/lib/browser/messaging/messaging-frontend-module.d.ts.map +1 -1
  59. package/lib/browser/messaging/messaging-frontend-module.js +18 -1
  60. package/lib/browser/messaging/messaging-frontend-module.js.map +1 -1
  61. package/lib/browser/messaging/service-connection-provider.d.ts +48 -0
  62. package/lib/browser/messaging/service-connection-provider.d.ts.map +1 -0
  63. package/lib/browser/messaging/service-connection-provider.js +115 -0
  64. package/lib/browser/messaging/service-connection-provider.js.map +1 -0
  65. package/lib/browser/messaging/ws-connection-provider.d.ts +7 -38
  66. package/lib/browser/messaging/ws-connection-provider.d.ts.map +1 -1
  67. package/lib/browser/messaging/ws-connection-provider.js +17 -121
  68. package/lib/browser/messaging/ws-connection-provider.js.map +1 -1
  69. package/lib/browser/messaging/ws-connection-source.d.ts +41 -0
  70. package/lib/browser/messaging/ws-connection-source.d.ts.map +1 -0
  71. package/lib/browser/messaging/ws-connection-source.js +210 -0
  72. package/lib/browser/messaging/ws-connection-source.js.map +1 -0
  73. package/lib/browser/preload/i18n-preload-contribution.js +1 -1
  74. package/lib/browser/preload/i18n-preload-contribution.js.map +1 -1
  75. package/lib/browser/shell/application-shell.js +1 -1
  76. package/lib/browser/shell/application-shell.js.map +1 -1
  77. package/lib/browser/tree/tree-compression/compressed-tree-widget.d.ts +1 -0
  78. package/lib/browser/tree/tree-compression/compressed-tree-widget.d.ts.map +1 -1
  79. package/lib/browser/tree/tree-compression/compressed-tree-widget.js +5 -0
  80. package/lib/browser/tree/tree-compression/compressed-tree-widget.js.map +1 -1
  81. package/lib/browser/tree/tree-widget.d.ts +6 -0
  82. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  83. package/lib/browser/tree/tree-widget.js +21 -11
  84. package/lib/browser/tree/tree-widget.js.map +1 -1
  85. package/lib/browser/user-working-directory-provider.d.ts +8 -1
  86. package/lib/browser/user-working-directory-provider.d.ts.map +1 -1
  87. package/lib/browser/user-working-directory-provider.js +22 -1
  88. package/lib/browser/user-working-directory-provider.js.map +1 -1
  89. package/lib/browser/window/default-secondary-window-service.d.ts +3 -0
  90. package/lib/browser/window/default-secondary-window-service.d.ts.map +1 -1
  91. package/lib/browser/window/default-secondary-window-service.js +55 -1
  92. package/lib/browser/window/default-secondary-window-service.js.map +1 -1
  93. package/lib/common/contribution-filter/contribution-filter.d.ts +9 -0
  94. package/lib/common/contribution-filter/contribution-filter.d.ts.map +1 -1
  95. package/lib/common/event.js +1 -1
  96. package/lib/common/event.js.map +1 -1
  97. package/lib/common/message-rpc/channel.d.ts.map +1 -1
  98. package/lib/common/message-rpc/channel.js +7 -1
  99. package/lib/common/message-rpc/channel.js.map +1 -1
  100. package/lib/common/message-rpc/message-buffer.d.ts +2 -0
  101. package/lib/common/message-rpc/message-buffer.d.ts.map +1 -1
  102. package/lib/common/message-rpc/message-buffer.js +4 -0
  103. package/lib/common/message-rpc/message-buffer.js.map +1 -1
  104. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts +1 -0
  105. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts.map +1 -1
  106. package/lib/common/message-rpc/uint8-array-message-buffer.js +6 -0
  107. package/lib/common/message-rpc/uint8-array-message-buffer.js.map +1 -1
  108. package/lib/common/messaging/connection-management.d.ts +25 -0
  109. package/lib/common/messaging/connection-management.d.ts.map +1 -0
  110. package/lib/common/messaging/connection-management.js +38 -0
  111. package/lib/common/messaging/connection-management.js.map +1 -0
  112. package/lib/common/messaging/handler.d.ts +1 -0
  113. package/lib/common/messaging/handler.d.ts.map +1 -1
  114. package/lib/common/messaging/handler.js +2 -1
  115. package/lib/common/messaging/handler.js.map +1 -1
  116. package/lib/common/messaging/socket-write-buffer.d.ts +11 -0
  117. package/lib/common/messaging/socket-write-buffer.d.ts.map +1 -0
  118. package/lib/common/messaging/socket-write-buffer.js +50 -0
  119. package/lib/common/messaging/socket-write-buffer.js.map +1 -0
  120. package/lib/common/messaging/web-socket-channel.d.ts +7 -35
  121. package/lib/common/messaging/web-socket-channel.d.ts.map +1 -1
  122. package/lib/common/messaging/web-socket-channel.js +20 -9
  123. package/lib/common/messaging/web-socket-channel.js.map +1 -1
  124. package/lib/common/nls.js +12 -1
  125. package/lib/common/nls.js.map +1 -1
  126. package/lib/electron-browser/messaging/electron-frontend-id-provider.d.ts +5 -0
  127. package/lib/electron-browser/messaging/electron-frontend-id-provider.d.ts.map +1 -0
  128. package/lib/{electron-node/token/electron-token-messaging-contribution.js → electron-browser/messaging/electron-frontend-id-provider.js} +9 -28
  129. package/lib/electron-browser/messaging/electron-frontend-id-provider.js.map +1 -0
  130. package/lib/electron-browser/messaging/electron-ipc-connection-source.d.ts +24 -0
  131. package/lib/electron-browser/messaging/electron-ipc-connection-source.d.ts.map +1 -0
  132. package/lib/electron-browser/messaging/{electron-ipc-connection-provider.js → electron-ipc-connection-source.js} +19 -19
  133. package/lib/electron-browser/messaging/electron-ipc-connection-source.js.map +1 -0
  134. package/lib/electron-browser/messaging/electron-local-ws-connection-source.d.ts +7 -0
  135. package/lib/electron-browser/messaging/electron-local-ws-connection-source.d.ts.map +1 -0
  136. package/lib/electron-browser/messaging/{electron-local-ws-connection-provider.js → electron-local-ws-connection-source.js} +7 -7
  137. package/lib/electron-browser/messaging/electron-local-ws-connection-source.js.map +1 -0
  138. package/lib/electron-browser/messaging/electron-messaging-frontend-module.d.ts.map +1 -1
  139. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js +45 -13
  140. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js.map +1 -1
  141. package/lib/electron-browser/messaging/electron-ws-connection-source.d.ts +12 -0
  142. package/lib/electron-browser/messaging/electron-ws-connection-source.d.ts.map +1 -0
  143. package/lib/electron-browser/messaging/{electron-ws-connection-provider.js → electron-ws-connection-source.js} +14 -21
  144. package/lib/electron-browser/messaging/electron-ws-connection-source.js.map +1 -0
  145. package/lib/electron-browser/preload.d.ts.map +1 -1
  146. package/lib/electron-browser/preload.js +11 -0
  147. package/lib/electron-browser/preload.js.map +1 -1
  148. package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -1
  149. package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
  150. package/lib/electron-browser/window/electron-window-module.js +2 -2
  151. package/lib/electron-browser/window/electron-window-module.js.map +1 -1
  152. package/lib/electron-browser/window/electron-window-preferences.js +1 -1
  153. package/lib/electron-browser/window/electron-window-preferences.js.map +1 -1
  154. package/lib/electron-browser/window/electron-window-service.d.ts +4 -0
  155. package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
  156. package/lib/electron-browser/window/electron-window-service.js +13 -0
  157. package/lib/electron-browser/window/electron-window-service.js.map +1 -1
  158. package/lib/electron-common/electron-api.d.ts +7 -0
  159. package/lib/electron-common/electron-api.d.ts.map +1 -1
  160. package/lib/electron-common/electron-api.js +3 -1
  161. package/lib/electron-common/electron-api.js.map +1 -1
  162. package/lib/electron-main/electron-api-main.d.ts +1 -0
  163. package/lib/electron-main/electron-api-main.d.ts.map +1 -1
  164. package/lib/electron-main/electron-api-main.js +15 -0
  165. package/lib/electron-main/electron-api-main.js.map +1 -1
  166. package/lib/electron-main/electron-main-application-module.js +5 -5
  167. package/lib/electron-main/electron-main-application-module.js.map +1 -1
  168. package/lib/electron-main/electron-main-application.d.ts +9 -13
  169. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  170. package/lib/electron-main/electron-main-application.js +60 -28
  171. package/lib/electron-main/electron-main-application.js.map +1 -1
  172. package/lib/electron-main/messaging/electron-connection-handler.d.ts.map +1 -0
  173. package/lib/electron-main/messaging/electron-connection-handler.js.map +1 -0
  174. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +13 -22
  175. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
  176. package/lib/electron-main/messaging/electron-messaging-contribution.js +39 -39
  177. package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
  178. package/lib/electron-main/messaging/electron-messaging-service.d.ts.map +1 -1
  179. package/lib/electron-main/messaging/electron-messaging-service.js.map +1 -1
  180. package/lib/electron-main/theia-electron-window.d.ts +2 -2
  181. package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
  182. package/lib/electron-main/theia-electron-window.js +3 -2
  183. package/lib/electron-main/theia-electron-window.js.map +1 -1
  184. package/lib/node/backend-application.d.ts +2 -0
  185. package/lib/node/backend-application.d.ts.map +1 -1
  186. package/lib/node/backend-application.js +11 -9
  187. package/lib/node/backend-application.js.map +1 -1
  188. package/lib/node/cli.d.ts +1 -1
  189. package/lib/node/cli.d.ts.map +1 -1
  190. package/lib/node/cli.js +9 -5
  191. package/lib/node/cli.js.map +1 -1
  192. package/lib/node/cli.spec.js +3 -3
  193. package/lib/node/cli.spec.js.map +1 -1
  194. package/lib/node/env-variables/env-variables-server.d.ts +3 -0
  195. package/lib/node/env-variables/env-variables-server.d.ts.map +1 -1
  196. package/lib/node/env-variables/env-variables-server.js +25 -1
  197. package/lib/node/env-variables/env-variables-server.js.map +1 -1
  198. package/lib/node/i18n/localization-server.d.ts +1 -1
  199. package/lib/node/i18n/localization-server.d.ts.map +1 -1
  200. package/lib/node/messaging/default-messaging-service.d.ts +29 -0
  201. package/lib/node/messaging/default-messaging-service.d.ts.map +1 -0
  202. package/lib/node/messaging/default-messaging-service.js +140 -0
  203. package/lib/node/messaging/default-messaging-service.js.map +1 -0
  204. package/lib/node/messaging/frontend-connection-service.d.ts +7 -0
  205. package/lib/node/messaging/frontend-connection-service.d.ts.map +1 -0
  206. package/lib/node/messaging/frontend-connection-service.js +19 -0
  207. package/lib/node/messaging/frontend-connection-service.js.map +1 -0
  208. package/lib/node/messaging/ipc-protocol.js +1 -1
  209. package/lib/node/messaging/ipc-protocol.js.map +1 -1
  210. package/lib/node/messaging/messaging-backend-module.d.ts.map +1 -1
  211. package/lib/node/messaging/messaging-backend-module.js +23 -9
  212. package/lib/node/messaging/messaging-backend-module.js.map +1 -1
  213. package/lib/node/messaging/messaging-service.d.ts +2 -3
  214. package/lib/node/messaging/messaging-service.d.ts.map +1 -1
  215. package/lib/node/messaging/test/test-web-socket-channel.d.ts +3 -3
  216. package/lib/node/messaging/test/test-web-socket-channel.d.ts.map +1 -1
  217. package/lib/node/messaging/test/test-web-socket-channel.js +38 -24
  218. package/lib/node/messaging/test/test-web-socket-channel.js.map +1 -1
  219. package/lib/node/messaging/websocket-endpoint.d.ts +21 -0
  220. package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -0
  221. package/lib/node/messaging/websocket-endpoint.js +89 -0
  222. package/lib/node/messaging/websocket-endpoint.js.map +1 -0
  223. package/lib/node/messaging/websocket-frontend-connection-service.d.ts +30 -0
  224. package/lib/node/messaging/websocket-frontend-connection-service.d.ts.map +1 -0
  225. package/lib/node/messaging/websocket-frontend-connection-service.js +173 -0
  226. package/lib/node/messaging/websocket-frontend-connection-service.js.map +1 -0
  227. package/package.json +6 -6
  228. package/src/browser/common-frontend-contribution.ts +70 -9
  229. package/src/browser/connection-status-service.spec.ts +6 -6
  230. package/src/browser/connection-status-service.ts +2 -2
  231. package/src/browser/core-preferences.ts +16 -0
  232. package/src/browser/dialogs.ts +0 -34
  233. package/src/browser/frontend-application-module.ts +4 -0
  234. package/src/browser/icon-theme-contribution.ts +1 -0
  235. package/src/browser/icon-theme-service.ts +1 -0
  236. package/src/browser/language-icon-provider.ts +55 -0
  237. package/src/browser/language-service.ts +34 -0
  238. package/src/browser/messaging/connection-source.ts +26 -0
  239. package/src/browser/messaging/frontend-id-provider.ts +37 -0
  240. package/src/browser/messaging/messaging-frontend-module.ts +20 -2
  241. package/src/browser/messaging/service-connection-provider.ts +126 -0
  242. package/src/browser/messaging/ws-connection-provider.ts +16 -141
  243. package/src/browser/messaging/ws-connection-source.ts +210 -0
  244. package/src/browser/preload/i18n-preload-contribution.ts +1 -1
  245. package/src/browser/shell/application-shell.ts +1 -1
  246. package/src/browser/style/index.css +1 -0
  247. package/src/browser/style/os.css +87 -0
  248. package/src/browser/tree/tree-compression/compressed-tree-widget.tsx +27 -7
  249. package/src/browser/tree/tree-widget.tsx +21 -10
  250. package/src/browser/user-working-directory-provider.ts +32 -3
  251. package/src/browser/window/default-secondary-window-service.ts +54 -1
  252. package/src/common/contribution-filter/contribution-filter.ts +9 -0
  253. package/src/common/event.ts +1 -1
  254. package/src/common/i18n/nls.metadata.json +7695 -7220
  255. package/src/common/message-rpc/channel.ts +5 -1
  256. package/src/common/message-rpc/message-buffer.ts +6 -0
  257. package/src/common/message-rpc/uint8-array-message-buffer.ts +7 -0
  258. package/src/common/messaging/connection-management.ts +43 -0
  259. package/src/common/messaging/handler.ts +2 -0
  260. package/src/common/messaging/socket-write-buffer.ts +52 -0
  261. package/src/common/messaging/web-socket-channel.ts +28 -45
  262. package/src/common/nls.ts +12 -1
  263. package/src/electron-browser/messaging/electron-frontend-id-provider.ts +25 -0
  264. package/src/electron-browser/messaging/{electron-ipc-connection-provider.ts → electron-ipc-connection-source.ts} +17 -13
  265. package/src/electron-browser/messaging/{electron-local-ws-connection-provider.ts → electron-local-ws-connection-source.ts} +2 -2
  266. package/src/electron-browser/messaging/electron-messaging-frontend-module.ts +49 -12
  267. package/src/electron-browser/messaging/{electron-ws-connection-provider.ts → electron-ws-connection-source.ts} +6 -17
  268. package/src/electron-browser/preload.ts +16 -1
  269. package/src/electron-browser/window/electron-secondary-window-service.ts +1 -1
  270. package/src/electron-browser/window/electron-window-module.ts +1 -1
  271. package/src/electron-browser/window/electron-window-preferences.ts +1 -1
  272. package/src/electron-browser/window/electron-window-service.ts +11 -0
  273. package/src/electron-common/electron-api.ts +8 -0
  274. package/src/electron-main/electron-api-main.ts +20 -1
  275. package/src/electron-main/electron-main-application-module.ts +5 -5
  276. package/src/electron-main/electron-main-application.ts +72 -44
  277. package/src/electron-main/messaging/electron-messaging-contribution.ts +45 -43
  278. package/src/electron-main/messaging/electron-messaging-service.ts +1 -0
  279. package/src/electron-main/theia-electron-window.ts +4 -3
  280. package/src/node/backend-application.ts +14 -11
  281. package/src/node/cli.spec.ts +3 -3
  282. package/src/node/cli.ts +9 -5
  283. package/src/node/env-variables/env-variables-server.ts +21 -1
  284. package/src/node/i18n/localization-server.ts +1 -1
  285. package/src/node/messaging/default-messaging-service.ts +129 -0
  286. package/src/node/messaging/frontend-connection-service.ts +24 -0
  287. package/src/node/messaging/ipc-protocol.ts +1 -1
  288. package/src/node/messaging/messaging-backend-module.ts +25 -10
  289. package/src/node/messaging/messaging-service.ts +3 -3
  290. package/src/node/messaging/test/test-web-socket-channel.ts +32 -27
  291. package/src/node/messaging/websocket-endpoint.ts +79 -0
  292. package/src/node/messaging/websocket-frontend-connection-service.ts +171 -0
  293. package/lib/common/messaging/abstract-connection-provider.d.ts +0 -45
  294. package/lib/common/messaging/abstract-connection-provider.d.ts.map +0 -1
  295. package/lib/common/messaging/abstract-connection-provider.js +0 -93
  296. package/lib/common/messaging/abstract-connection-provider.js.map +0 -1
  297. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts +0 -19
  298. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts.map +0 -1
  299. package/lib/electron-browser/messaging/electron-ipc-connection-provider.js.map +0 -1
  300. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.d.ts +0 -7
  301. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.d.ts.map +0 -1
  302. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.js.map +0 -1
  303. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts +0 -17
  304. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts.map +0 -1
  305. package/lib/electron-browser/messaging/electron-ws-connection-provider.js.map +0 -1
  306. package/lib/electron-common/messaging/electron-connection-handler.d.ts.map +0 -1
  307. package/lib/electron-common/messaging/electron-connection-handler.js.map +0 -1
  308. package/lib/electron-node/token/electron-token-messaging-contribution.d.ts +0 -16
  309. package/lib/electron-node/token/electron-token-messaging-contribution.d.ts.map +0 -1
  310. package/lib/electron-node/token/electron-token-messaging-contribution.js.map +0 -1
  311. package/lib/node/messaging/messaging-contribution.d.ts +0 -44
  312. package/lib/node/messaging/messaging-contribution.d.ts.map +0 -1
  313. package/lib/node/messaging/messaging-contribution.js +0 -210
  314. package/lib/node/messaging/messaging-contribution.js.map +0 -1
  315. package/src/common/messaging/abstract-connection-provider.ts +0 -115
  316. package/src/electron-node/token/electron-token-messaging-contribution.ts +0 -41
  317. package/src/node/messaging/messaging-contribution.ts +0 -197
  318. /package/lib/{electron-common → electron-main}/messaging/electron-connection-handler.d.ts +0 -0
  319. /package/lib/{electron-common → electron-main}/messaging/electron-connection-handler.js +0 -0
  320. /package/src/{electron-common → electron-main}/messaging/electron-connection-handler.ts +0 -0
@@ -18,6 +18,7 @@ import { join } from 'path';
18
18
  import { homedir } from 'os';
19
19
  import { injectable } from 'inversify';
20
20
  import * as drivelist from 'drivelist';
21
+ import { pathExists, mkdir } from 'fs-extra';
21
22
  import { EnvVariable, EnvVariablesServer } from '../../common/env-variables';
22
23
  import { isWindows } from '../../common/os';
23
24
  import { FileUri } from '../file-uri';
@@ -28,6 +29,7 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
28
29
  protected readonly envs: { [key: string]: EnvVariable } = {};
29
30
  protected readonly homeDirUri = FileUri.create(homedir()).toString();
30
31
  protected readonly configDirUri: Promise<string>;
32
+ protected readonly pathExistenceCache: { [key: string]: boolean } = {};
31
33
 
32
34
  constructor() {
33
35
  this.configDirUri = this.createConfigDirUri();
@@ -43,7 +45,25 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
43
45
  }
44
46
 
45
47
  protected async createConfigDirUri(): Promise<string> {
46
- return FileUri.create(process.env.THEIA_CONFIG_DIR || join(homedir(), '.theia')).toString();
48
+ let dataFolderPath: string = '';
49
+ if (process.env.THEIA_APP_PROJECT_PATH) {
50
+ dataFolderPath = join(process.env.THEIA_APP_PROJECT_PATH, 'data');
51
+ }
52
+ const userDataPath = join(dataFolderPath, 'user-data');
53
+ const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath);
54
+ if (dataFolderExists) {
55
+ const userDataExists = this.pathExistenceCache[userDataPath] ??= await pathExists(userDataPath);
56
+ if (userDataExists) {
57
+ process.env.THEIA_CONFIG_DIR = userDataPath;
58
+ } else {
59
+ await mkdir(userDataPath);
60
+ process.env.THEIA_CONFIG_DIR = userDataPath;
61
+ this.pathExistenceCache[userDataPath] = true;
62
+ }
63
+ } else {
64
+ process.env.THEIA_CONFIG_DIR = join(homedir(), '.theia');
65
+ }
66
+ return FileUri.create(process.env.THEIA_CONFIG_DIR).toString();
47
67
  }
48
68
 
49
69
  async getExecPath(): Promise<string> {
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { inject, injectable } from 'inversify';
18
- import { Localization } from 'src/common/i18n/localization';
18
+ import { Localization } from '../../common/i18n/localization';
19
19
  import { LocalizationServer } from '../../common/i18n/localization-server';
20
20
  import { nls } from '../../common/nls';
21
21
  import { Deferred } from '../../common/promise-util';
@@ -0,0 +1,129 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2018 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { injectable, inject, named, interfaces, Container } from 'inversify';
18
+ import { ContributionProvider, ConnectionHandler, bindContributionProvider, servicesPath } from '../../common';
19
+ import { MessagingService } from './messaging-service';
20
+ import { ConnectionContainerModule } from './connection-container-module';
21
+ import Route = require('route-parser');
22
+ import { Channel, ChannelMultiplexer } from '../../common/message-rpc/channel';
23
+ import { FrontendConnectionService } from './frontend-connection-service';
24
+ import { BackendApplicationContribution } from '../backend-application';
25
+
26
+ export const MessagingContainer = Symbol('MessagingContainer');
27
+ export const MainChannel = Symbol('MainChannel');
28
+
29
+ @injectable()
30
+ export class DefaultMessagingService implements MessagingService, BackendApplicationContribution {
31
+ @inject(MessagingContainer)
32
+ protected readonly container: interfaces.Container;
33
+
34
+ @inject(FrontendConnectionService)
35
+ protected readonly frontendConnectionService: FrontendConnectionService;
36
+
37
+ @inject(ContributionProvider) @named(ConnectionContainerModule)
38
+ protected readonly connectionModules: ContributionProvider<interfaces.ContainerModule>;
39
+
40
+ @inject(ContributionProvider) @named(MessagingService.Contribution)
41
+ protected readonly contributions: ContributionProvider<MessagingService.Contribution>;
42
+
43
+ protected readonly channelHandlers = new ConnectionHandlers<Channel>();
44
+
45
+ initialize(): void {
46
+ this.registerConnectionHandler(servicesPath, (_, socket) => this.handleConnection(socket));
47
+ for (const contribution of this.contributions.getContributions()) {
48
+ contribution.configure(this);
49
+ }
50
+ }
51
+
52
+ registerConnectionHandler(path: string, callback: (params: MessagingService.PathParams, mainChannel: Channel) => void): void {
53
+ this.frontendConnectionService.registerConnectionHandler(path, callback);
54
+ }
55
+
56
+ registerChannelHandler(spec: string, callback: (params: MessagingService.PathParams, channel: Channel) => void): void {
57
+ this.channelHandlers.push(spec, (params, channel) => callback(params, channel));
58
+ }
59
+
60
+ protected handleConnection(channel: Channel): void {
61
+ const multiplexer = new ChannelMultiplexer(channel);
62
+ const channelHandlers = this.getConnectionChannelHandlers(channel);
63
+ multiplexer.onDidOpenChannel(event => {
64
+ if (channelHandlers.route(event.id, event.channel)) {
65
+ console.debug(`Opening channel for service path '${event.id}'.`);
66
+ event.channel.onClose(() => console.info(`Closing channel on service path '${event.id}'.`));
67
+ }
68
+ });
69
+ }
70
+
71
+ protected createMainChannelContainer(socket: Channel): Container {
72
+ const connectionContainer: Container = this.container.createChild() as Container;
73
+ connectionContainer.bind(MainChannel).toConstantValue(socket);
74
+ return connectionContainer;
75
+ }
76
+
77
+ protected getConnectionChannelHandlers(socket: Channel): ConnectionHandlers<Channel> {
78
+ const connectionContainer = this.createMainChannelContainer(socket);
79
+ bindContributionProvider(connectionContainer, ConnectionHandler);
80
+ connectionContainer.load(...this.connectionModules.getContributions());
81
+ const connectionChannelHandlers = new ConnectionHandlers<Channel>(this.channelHandlers);
82
+ const connectionHandlers = connectionContainer.getNamed<ContributionProvider<ConnectionHandler>>(ContributionProvider, ConnectionHandler);
83
+ for (const connectionHandler of connectionHandlers.getContributions(true)) {
84
+ connectionChannelHandlers.push(connectionHandler.path, (_, channel) => {
85
+ connectionHandler.onConnection(channel);
86
+ });
87
+ }
88
+ return connectionChannelHandlers;
89
+ }
90
+
91
+ }
92
+
93
+ export class ConnectionHandlers<T> {
94
+ protected readonly handlers: ((path: string, connection: T) => string | false)[] = [];
95
+
96
+ constructor(
97
+ protected readonly parent?: ConnectionHandlers<T>
98
+ ) { }
99
+
100
+ push(spec: string, callback: (params: MessagingService.PathParams, connection: T) => void): void {
101
+ const route = new Route(spec);
102
+ const handler = (path: string, channel: T): string | false => {
103
+ const params = route.match(path);
104
+ if (!params) {
105
+ return false;
106
+ }
107
+ callback(params, channel);
108
+ return route.reverse(params);
109
+ };
110
+ this.handlers.push(handler);
111
+ }
112
+
113
+ route(path: string, connection: T): string | false {
114
+ for (const handler of this.handlers) {
115
+ try {
116
+ const result = handler(path, connection);
117
+ if (result) {
118
+ return result;
119
+ }
120
+ } catch (e) {
121
+ console.error(e);
122
+ }
123
+ }
124
+ if (this.parent) {
125
+ return this.parent.route(path, connection);
126
+ }
127
+ return false;
128
+ }
129
+ }
@@ -0,0 +1,24 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+
16
+ import { Channel } from '../../common/message-rpc/';
17
+ import { MessagingService } from './messaging-service';
18
+
19
+ export const FrontendConnectionService = Symbol('FrontendConnectionService');
20
+
21
+ export interface FrontendConnectionService {
22
+ registerConnectionHandler(path: string, callback: (params: MessagingService.PathParams, mainChannel: Channel) => void): void;
23
+ }
24
+
@@ -51,7 +51,7 @@ export function checkParentAlive(): void {
51
51
  } catch {
52
52
  process.exit();
53
53
  }
54
- }, 5000);
54
+ }, 5000).unref(); // we don't want this timeout to keep the process alive
55
55
  }
56
56
  }
57
57
  }
@@ -15,23 +15,38 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { ContainerModule } from 'inversify';
18
- import { bindContributionProvider } from '../../common';
19
- import { BackendApplicationContribution } from '../backend-application';
20
- import { MessagingContribution, MessagingContainer } from './messaging-contribution';
18
+ import { ConnectionHandler, RpcConnectionHandler, bindContributionProvider } from '../../common';
19
+ // import { BackendApplicationContribution } from '../backend-application';
20
+ import { DefaultMessagingService, MessagingContainer } from './default-messaging-service';
21
21
  import { ConnectionContainerModule } from './connection-container-module';
22
22
  import { MessagingService } from './messaging-service';
23
23
  import { MessagingListener, MessagingListenerContribution } from './messaging-listeners';
24
+ import { FrontendConnectionService } from './frontend-connection-service';
25
+ import { BackendApplicationContribution } from '../backend-application';
26
+ import { connectionCloseServicePath } from '../../common/messaging/connection-management';
27
+ import { WebsocketFrontendConnectionService } from './websocket-frontend-connection-service';
28
+ import { WebsocketEndpoint } from './websocket-endpoint';
24
29
 
25
30
  export const messagingBackendModule = new ContainerModule(bind => {
26
31
  bindContributionProvider(bind, ConnectionContainerModule);
27
32
  bindContributionProvider(bind, MessagingService.Contribution);
28
- bind(MessagingService.Identifier).to(MessagingContribution).inSingletonScope();
29
- bind(MessagingContribution).toDynamicValue(({ container }) => {
30
- const child = container.createChild();
31
- child.bind(MessagingContainer).toConstantValue(container);
32
- return child.get(MessagingService.Identifier);
33
- }).inSingletonScope();
34
- bind(BackendApplicationContribution).toService(MessagingContribution);
33
+ bind(DefaultMessagingService).toSelf().inSingletonScope();
34
+ bind(MessagingService.Identifier).toService(DefaultMessagingService);
35
+ bind(BackendApplicationContribution).toService(DefaultMessagingService);
36
+ bind(MessagingContainer).toDynamicValue(({ container }) => container).inSingletonScope();
37
+ bind(WebsocketEndpoint).toSelf().inSingletonScope();
38
+ bind(BackendApplicationContribution).toService(WebsocketEndpoint);
39
+ bind(WebsocketFrontendConnectionService).toSelf().inSingletonScope();
40
+ bind(FrontendConnectionService).toService(WebsocketFrontendConnectionService);
35
41
  bind(MessagingListener).toSelf().inSingletonScope();
36
42
  bindContributionProvider(bind, MessagingListenerContribution);
43
+
44
+ bind(ConnectionHandler).toDynamicValue(context => {
45
+ const connectionService = context.container.get<WebsocketFrontendConnectionService>(FrontendConnectionService);
46
+ return new RpcConnectionHandler<object>(connectionCloseServicePath, () => ({
47
+ markForClose: (channelId: string) => {
48
+ connectionService.markForClose(channelId);
49
+ }
50
+ }));
51
+ }).inSingletonScope();
37
52
  });
@@ -14,7 +14,6 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { Socket } from 'socket.io';
18
17
  import { Channel } from '../../common/message-rpc/channel';
19
18
 
20
19
  export interface MessagingService {
@@ -22,7 +21,7 @@ export interface MessagingService {
22
21
  * Accept a web socket channel on the given path.
23
22
  * A path supports the route syntax: https://github.com/rcs/route-parser#what-can-i-use-in-my-routes.
24
23
  */
25
- wsChannel(path: string, callback: (params: MessagingService.PathParams, channel: Channel) => void): void;
24
+ registerChannelHandler(path: string, handler: (params: MessagingService.PathParams, channel: Channel) => void): void;
26
25
  /**
27
26
  * Accept a web socket connection on the given path.
28
27
  * A path supports the route syntax: https://github.com/rcs/route-parser#what-can-i-use-in-my-routes.
@@ -31,8 +30,9 @@ export interface MessagingService {
31
30
  * Prefer using web socket channels over establishing new web socket connection. Clients can handle only limited amount of web sockets
32
31
  * and excessive amount can cause performance degradation. All web socket channels share a single web socket connection.
33
32
  */
34
- ws(path: string, callback: (params: MessagingService.PathParams, socket: Socket) => void): void;
33
+ registerConnectionHandler(path: string, callback: (params: MessagingService.PathParams, mainChannel: Channel) => void): void;
35
34
  }
35
+
36
36
  export namespace MessagingService {
37
37
  /** Inversify container identifier for the `MessagingService` component. */
38
38
  export const Identifier = Symbol('MessagingService');
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @theia/runtime-import-check */
1
2
  // *****************************************************************************
2
3
  // Copyright (C) 2018 TypeFox and others.
3
4
  //
@@ -17,40 +18,44 @@
17
18
  import * as http from 'http';
18
19
  import * as https from 'https';
19
20
  import { AddressInfo } from 'net';
20
- import { io, Socket } from 'socket.io-client';
21
- import { Channel, ChannelMultiplexer } from '../../../common/message-rpc/channel';
22
- import { IWebSocket, WebSocketChannel } from '../../../common/messaging/web-socket-channel';
21
+ import { servicesPath } from '../../../common';
22
+ import { WebSocketConnectionSource } from '../../../browser/messaging/ws-connection-source';
23
+ import { Container, inject } from 'inversify';
24
+ import { RemoteConnectionProvider, ServiceConnectionProvider } from '../../../browser/messaging/service-connection-provider';
25
+ import { messagingFrontendModule } from '../../../browser/messaging/messaging-frontend-module';
26
+ import { Socket, io } from 'socket.io-client';
27
+
28
+ const websocketUrl = Symbol('testWebsocketUrl');
29
+ class TestWebsocketConnectionSource extends WebSocketConnectionSource {
30
+ @inject(websocketUrl)
31
+ readonly websocketUrl: string;
32
+
33
+ protected override createWebSocketUrl(path: string): string {
34
+ return this.websocketUrl;
35
+ }
36
+
37
+ protected override createWebSocket(url: string): Socket {
38
+ return io(url);
39
+ }
40
+ }
23
41
 
24
42
  export class TestWebSocketChannelSetup {
25
- public readonly multiplexer: ChannelMultiplexer;
26
- public readonly channel: Channel;
43
+ public readonly connectionProvider: ServiceConnectionProvider;
27
44
 
28
45
  constructor({ server, path }: {
29
46
  server: http.Server | https.Server,
30
47
  path: string
31
48
  }) {
32
- const socket = io(`ws://localhost:${(server.address() as AddressInfo).port}${WebSocketChannel.wsPath}`);
33
- this.channel = new WebSocketChannel(toIWebSocket(socket));
34
- this.multiplexer = new ChannelMultiplexer(this.channel);
35
- socket.on('connect', () => {
36
- this.multiplexer.open(path);
37
- });
38
- socket.connect();
49
+ const address = (server.address() as AddressInfo);
50
+ const url = `ws://${address.address}:${address.port}${servicesPath}`;
51
+ this.connectionProvider = this.createConnectionProvider(url);
39
52
  }
40
- }
41
53
 
42
- function toIWebSocket(socket: Socket): IWebSocket {
43
- return {
44
- close: () => {
45
- socket.removeAllListeners('disconnect');
46
- socket.removeAllListeners('error');
47
- socket.removeAllListeners('message');
48
- socket.close();
49
- },
50
- isConnected: () => socket.connected,
51
- onClose: cb => socket.on('disconnect', reason => cb(reason)),
52
- onError: cb => socket.on('error', reason => cb(reason)),
53
- onMessage: cb => socket.on('message', data => cb(data)),
54
- send: message => socket.emit('message', message)
55
- };
54
+ protected createConnectionProvider(socketUrl: string): ServiceConnectionProvider {
55
+ const container = new Container();
56
+ container.bind(websocketUrl).toConstantValue(socketUrl);
57
+ container.load(messagingFrontendModule);
58
+ container.rebind(WebSocketConnectionSource).to(TestWebsocketConnectionSource);
59
+ return container.get(RemoteConnectionProvider);
60
+ }
56
61
  }
@@ -0,0 +1,79 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+
16
+ import { MessagingService } from './messaging-service';
17
+ import * as http from 'http';
18
+ import * as https from 'https';
19
+ import { inject, injectable } from 'inversify';
20
+ import { Server, Socket } from 'socket.io';
21
+ import { WsRequestValidator } from '../ws-request-validators';
22
+ import { MessagingListener } from './messaging-listeners';
23
+ import { ConnectionHandlers } from './default-messaging-service';
24
+ import { BackendApplicationContribution } from '../backend-application';
25
+
26
+ @injectable()
27
+ export class WebsocketEndpoint implements BackendApplicationContribution {
28
+ @inject(WsRequestValidator)
29
+ protected readonly wsRequestValidator: WsRequestValidator;
30
+
31
+ @inject(MessagingListener)
32
+ protected readonly messagingListener: MessagingListener;
33
+
34
+ protected checkAliveTimeout = 30000; // 30 seconds
35
+ protected maxHttpBufferSize = 1e8; // 100 MB
36
+
37
+ protected readonly wsHandlers = new ConnectionHandlers<Socket>();
38
+
39
+ registerConnectionHandler(spec: string, callback: (params: MessagingService.PathParams, socket: Socket) => void): void {
40
+ this.wsHandlers.push(spec, callback);
41
+ }
42
+
43
+ onStart(server: http.Server | https.Server): void {
44
+ const socketServer = new Server(server, {
45
+ pingInterval: this.checkAliveTimeout,
46
+ pingTimeout: this.checkAliveTimeout * 2,
47
+ maxHttpBufferSize: this.maxHttpBufferSize
48
+ });
49
+ // Accept every namespace by using /.*/
50
+ socketServer.of(/.*/).on('connection', async socket => {
51
+ const request = socket.request;
52
+ // Socket.io strips the `origin` header of the incoming request
53
+ // We provide a `fix-origin` header in the `WebSocketConnectionProvider`
54
+ request.headers.origin = request.headers['fix-origin'] as string;
55
+ if (await this.allowConnect(socket.request)) {
56
+ await this.handleConnection(socket);
57
+ this.messagingListener.onDidWebSocketUpgrade(socket.request, socket);
58
+ } else {
59
+ socket.disconnect(true);
60
+ }
61
+ });
62
+ }
63
+
64
+ protected async allowConnect(request: http.IncomingMessage): Promise<boolean> {
65
+ try {
66
+ return this.wsRequestValidator.allowWsUpgrade(request);
67
+ } catch (e) {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ protected async handleConnection(socket: Socket): Promise<void> {
73
+ const pathname = socket.nsp.name;
74
+ if (pathname && !this.wsHandlers.route(pathname, socket)) {
75
+ console.error('Cannot find a ws handler for the path: ' + pathname);
76
+ }
77
+ }
78
+ }
79
+
@@ -0,0 +1,171 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+
16
+ import { Channel, WriteBuffer } from '../../common/message-rpc';
17
+ import { MessagingService } from './messaging-service';
18
+ import { inject, injectable } from 'inversify';
19
+ import { Socket } from 'socket.io';
20
+ import { ConnectionHandlers } from './default-messaging-service';
21
+ import { SocketWriteBuffer } from '../../common/messaging/socket-write-buffer';
22
+ import { FrontendConnectionService } from './frontend-connection-service';
23
+ import { AbstractChannel } from '../../common/message-rpc/channel';
24
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '../../common/message-rpc/uint8-array-message-buffer';
25
+ import { BackendApplicationConfigProvider } from '../backend-application-config-provider';
26
+ import { WebsocketEndpoint } from './websocket-endpoint';
27
+ import { ConnectionManagementMessages } from '../../common/messaging/connection-management';
28
+ import { Disposable, DisposableCollection } from '../../common';
29
+
30
+ @injectable()
31
+ export class WebsocketFrontendConnectionService implements FrontendConnectionService {
32
+
33
+ @inject(WebsocketEndpoint)
34
+ protected readonly websocketServer: WebsocketEndpoint;
35
+
36
+ protected readonly wsHandlers = new ConnectionHandlers();
37
+ protected readonly connectionsByFrontend = new Map<string, ReconnectableSocketChannel>();
38
+ protected readonly closeTimeouts = new Map<string, NodeJS.Timeout>();
39
+ protected readonly channelsMarkedForClose = new Set<string>();
40
+
41
+ registerConnectionHandler(spec: string, callback: (params: MessagingService.PathParams, channel: Channel) => void): void {
42
+ this.websocketServer.registerConnectionHandler(spec, (params, socket) => this.handleConnection(socket, channel => callback(params, channel)));
43
+ }
44
+
45
+ protected async handleConnection(socket: Socket, channelCreatedHandler: (channel: Channel) => void): Promise<void> {
46
+ // eslint-disable-next-line prefer-const
47
+ let reconnectListener: (frontEndId: string) => void;
48
+ const initialConnectListener = (frontEndId: string) => {
49
+ socket.off(ConnectionManagementMessages.INITIAL_CONNECT, initialConnectListener);
50
+ socket.off(ConnectionManagementMessages.RECONNECT, reconnectListener);
51
+ if (this.connectionsByFrontend.has(frontEndId)) {
52
+ this.closeConnection(frontEndId, 'reconnecting same front end');
53
+ }
54
+ channelCreatedHandler(this.createConnection(socket, frontEndId));
55
+ socket.emit(ConnectionManagementMessages.INITIAL_CONNECT);
56
+ };
57
+
58
+ reconnectListener = (frontEndId: string) => {
59
+ socket.off(ConnectionManagementMessages.INITIAL_CONNECT, initialConnectListener);
60
+ socket.off(ConnectionManagementMessages.RECONNECT, reconnectListener);
61
+ const channel = this.connectionsByFrontend.get(frontEndId);
62
+ if (channel) {
63
+ console.info(`Reconnecting to front end ${frontEndId}`);
64
+ socket.emit(ConnectionManagementMessages.RECONNECT, true);
65
+ channel.connect(socket);
66
+ const pendingTimeout = this.closeTimeouts.get(frontEndId);
67
+ clearTimeout(pendingTimeout);
68
+ this.closeTimeouts.delete(frontEndId);
69
+ } else {
70
+ console.info(`Reconnecting failed for ${frontEndId}`);
71
+ socket.emit(ConnectionManagementMessages.RECONNECT, false);
72
+ }
73
+ };
74
+ socket.on(ConnectionManagementMessages.INITIAL_CONNECT, initialConnectListener);
75
+ socket.on(ConnectionManagementMessages.RECONNECT, reconnectListener);
76
+ }
77
+
78
+ protected closeConnection(frontEndId: string, reason: string): void {
79
+ console.info(`closing connection for ${frontEndId}`);
80
+ const connection = this.connectionsByFrontend.get(frontEndId)!; // not called when no connection is present
81
+
82
+ this.connectionsByFrontend.delete(frontEndId);
83
+
84
+ const pendingTimeout = this.closeTimeouts.get(frontEndId);
85
+ clearTimeout(pendingTimeout);
86
+ this.closeTimeouts.delete(frontEndId);
87
+
88
+ connection.onCloseEmitter.fire({ reason });
89
+ connection.close();
90
+ }
91
+
92
+ protected createConnection(socket: Socket, frontEndId: string): Channel {
93
+ console.info(`creating connection for ${frontEndId}`);
94
+ const channel = new ReconnectableSocketChannel();
95
+ channel.connect(socket);
96
+
97
+ socket.on('disconnect', evt => {
98
+ console.info('socked closed');
99
+ channel.disconnect();
100
+ const timeout = BackendApplicationConfigProvider.get().frontendConnectionTimeout;
101
+ const isMarkedForClose = this.channelsMarkedForClose.delete(frontEndId);
102
+ if (timeout === 0 || isMarkedForClose) {
103
+ this.closeConnection(frontEndId, evt);
104
+ } else if (timeout > 0) {
105
+ console.info(`setting close timeout for id ${frontEndId} to ${timeout}`);
106
+ const handle = setTimeout(() => {
107
+ this.closeConnection(frontEndId, evt);
108
+ }, timeout);
109
+ this.closeTimeouts.set(frontEndId, handle);
110
+ } else {
111
+ // timeout < 0: never close the back end
112
+ }
113
+ });
114
+
115
+ this.connectionsByFrontend.set(frontEndId, channel);
116
+ return channel;
117
+ }
118
+
119
+ markForClose(channelId: string): void {
120
+ this.channelsMarkedForClose.add(channelId);
121
+ }
122
+ }
123
+
124
+ class ReconnectableSocketChannel extends AbstractChannel {
125
+ private socket: Socket | undefined;
126
+ private socketBuffer = new SocketWriteBuffer();
127
+ private disposables = new DisposableCollection();
128
+
129
+ connect(socket: Socket): void {
130
+ this.disposables = new DisposableCollection();
131
+ this.socket = socket;
132
+ const errorHandler = (err: Error) => {
133
+ this.onErrorEmitter.fire(err);
134
+ };
135
+ this.disposables.push(Disposable.create(() => {
136
+ socket.off('error', errorHandler);
137
+ }));
138
+ socket.on('error', errorHandler);
139
+
140
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
141
+ const dataListener = (data: any) => {
142
+ // In the browser context socketIO receives binary messages as ArrayBuffers.
143
+ // So we have to convert them to a Uint8Array before delegating the message to the read buffer.
144
+ const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
145
+ this.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(buffer));
146
+ };
147
+ this.disposables.push(Disposable.create(() => {
148
+ socket.off('message', dataListener);
149
+ }));
150
+ socket.on('message', dataListener);
151
+ this.socketBuffer.flush(socket);
152
+ }
153
+
154
+ disconnect(): void {
155
+ this.disposables.dispose();
156
+ this.socket = undefined;
157
+ }
158
+
159
+ override getWriteBuffer(): WriteBuffer {
160
+ const writeBuffer = new Uint8ArrayWriteBuffer();
161
+ writeBuffer.onCommit(data => {
162
+ if (this.socket?.connected) {
163
+ this.socket.send(data);
164
+ } else {
165
+ this.socketBuffer.buffer(data);
166
+ }
167
+ });
168
+ return writeBuffer;
169
+ }
170
+ }
171
+