@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
@@ -41,6 +41,9 @@ export type InternalMenuDto = Omit<MenuDto, 'execute' | 'submenu'> & {
41
41
  export type WindowEvent = 'maximize' | 'unmaximize' | 'focus';
42
42
 
43
43
  export interface TheiaCoreAPI {
44
+ WindowMetadata: {
45
+ webcontentId: string;
46
+ }
44
47
  getSecurityToken: () => string;
45
48
  attachSecurityToken: (endpoint: string) => Promise<void>;
46
49
 
@@ -63,6 +66,7 @@ export interface TheiaCoreAPI {
63
66
  unMaximize(): void;
64
67
  close(): void;
65
68
  onWindowEvent(event: WindowEvent, handler: () => void): Disposable;
69
+ onAboutToClose(handler: () => void): Disposable;
66
70
  setCloseRequestHandler(handler: (reason: StopReason) => Promise<boolean>): void;
67
71
 
68
72
  setSecondaryWindowCloseRequestHandler(windowName: string, handler: () => Promise<boolean>): void;
@@ -87,6 +91,7 @@ export interface TheiaCoreAPI {
87
91
 
88
92
  sendData(data: Uint8Array): void;
89
93
  onData(handler: (data: Uint8Array) => void): Disposable;
94
+ useNativeElements: boolean;
90
95
  }
91
96
 
92
97
  declare global {
@@ -95,6 +100,7 @@ declare global {
95
100
  }
96
101
  }
97
102
 
103
+ export const CHANNEL_WC_METADATA = 'WebContentMetadata';
98
104
  export const CHANNEL_SET_MENU = 'SetMenu';
99
105
  export const CHANNEL_SET_MENU_BAR_VISIBLE = 'SetMenuBarVisible';
100
106
  export const CHANNEL_INVOKE_MENU = 'InvokeMenu';
@@ -116,6 +122,8 @@ export const CHANNEL_MINIMIZE = 'Minimize';
116
122
  export const CHANNEL_MAXIMIZE = 'Maximize';
117
123
  export const CHANNEL_IS_MAXIMIZED = 'IsMaximized';
118
124
 
125
+ export const CHANNEL_ABOUT_TO_CLOSE = 'AboutToClose';
126
+
119
127
  export const CHANNEL_UNMAXIMIZE = 'UnMaximize';
120
128
  export const CHANNEL_ON_WINDOW_EVENT = 'OnWindowEvent';
121
129
  export const CHANNEL_TOGGLE_DEVTOOLS = 'ToggleDevtools';
@@ -51,7 +51,9 @@ import {
51
51
  CHANNEL_TOGGLE_FULL_SCREEN,
52
52
  CHANNEL_IS_MAXIMIZED,
53
53
  CHANNEL_REQUEST_SECONDARY_CLOSE,
54
- CHANNEL_SET_BACKGROUND_COLOR
54
+ CHANNEL_SET_BACKGROUND_COLOR,
55
+ CHANNEL_WC_METADATA,
56
+ CHANNEL_ABOUT_TO_CLOSE
55
57
  } from '../electron-common/electron-api';
56
58
  import { ElectronMainApplication, ElectronMainApplicationContribution } from './electron-main-application';
57
59
  import { Disposable, DisposableCollection, isOSX, MaybePromise } from '../common';
@@ -65,6 +67,10 @@ export class TheiaMainApi implements ElectronMainApplicationContribution {
65
67
  protected readonly openPopups = new Map<number, Menu>();
66
68
 
67
69
  onStart(application: ElectronMainApplication): MaybePromise<void> {
70
+ ipcMain.on(CHANNEL_WC_METADATA, event => {
71
+ event.returnValue = event.sender.id.toString();
72
+ });
73
+
68
74
  // electron security token
69
75
  ipcMain.on(CHANNEL_GET_SECURITY_TOKEN, event => {
70
76
  event.returnValue = this.electronSecurityToken.value;
@@ -254,6 +260,19 @@ export namespace TheiaRendererAPI {
254
260
  wc.send(CHANNEL_ON_WINDOW_EVENT, event);
255
261
  }
256
262
 
263
+ export function sendAboutToClose(wc: WebContents): Promise<void> {
264
+ return new Promise<void>(resolve => {
265
+ const channelNr = nextReplyChannel++;
266
+ const replyChannel = `aboutToClose${channelNr}`;
267
+ const l = createDisposableListener(ipcMain, replyChannel, e => {
268
+ l.dispose();
269
+ resolve();
270
+ });
271
+
272
+ wc.send(CHANNEL_ABOUT_TO_CLOSE, replyChannel);
273
+ });
274
+ }
275
+
257
276
  export function requestClose(wc: WebContents, stopReason: StopReason): Promise<boolean> {
258
277
  const channelNr = nextReplyChannel++;
259
278
  const confirmChannel = `confirm-${channelNr}`;
@@ -22,12 +22,12 @@ import { ElectronSecurityToken } from '../electron-common/electron-token';
22
22
  import { ElectronMainWindowService, electronMainWindowServicePath } from '../electron-common/electron-main-window-service';
23
23
  import { ElectronMainApplication, ElectronMainApplicationContribution, ElectronMainProcessArgv } from './electron-main-application';
24
24
  import { ElectronMainWindowServiceImpl } from './electron-main-window-service-impl';
25
- import { ElectronMessagingContribution } from './messaging/electron-messaging-contribution';
26
- import { ElectronMessagingService } from './messaging/electron-messaging-service';
27
- import { ElectronConnectionHandler } from '../electron-common/messaging/electron-connection-handler';
28
- import { ElectronSecurityTokenService } from './electron-security-token-service';
29
25
  import { TheiaBrowserWindowOptions, TheiaElectronWindow, TheiaElectronWindowFactory, WindowApplicationConfig } from './theia-electron-window';
30
26
  import { TheiaMainApi } from './electron-api-main';
27
+ import { ElectronMessagingContribution } from './messaging/electron-messaging-contribution';
28
+ import { ElectronSecurityTokenService } from './electron-security-token-service';
29
+ import { ElectronMessagingService } from './messaging/electron-messaging-service';
30
+ import { ElectronConnectionHandler } from './messaging/electron-connection-handler';
31
31
 
32
32
  const electronSecurityToken: ElectronSecurityToken = { value: v4() };
33
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -36,6 +36,7 @@ const electronSecurityToken: ElectronSecurityToken = { value: v4() };
36
36
  export default new ContainerModule(bind => {
37
37
  bind(ElectronMainApplication).toSelf().inSingletonScope();
38
38
  bind(ElectronMessagingContribution).toSelf().inSingletonScope();
39
+ bind(ElectronMainApplicationContribution).toService(ElectronMessagingContribution);
39
40
  bind(ElectronSecurityToken).toConstantValue(electronSecurityToken);
40
41
  bind(ElectronSecurityTokenService).toSelf().inSingletonScope();
41
42
 
@@ -43,7 +44,6 @@ export default new ContainerModule(bind => {
43
44
  bindContributionProvider(bind, ElectronMessagingService.Contribution);
44
45
  bindContributionProvider(bind, ElectronMainApplicationContribution);
45
46
 
46
- bind(ElectronMainApplicationContribution).toService(ElectronMessagingContribution);
47
47
  bind(TheiaMainApi).toSelf().inSingletonScope();
48
48
  bind(ElectronMainApplicationContribution).toService(TheiaMainApi);
49
49
 
@@ -20,6 +20,7 @@ import * as path from 'path';
20
20
  import { Argv } from 'yargs';
21
21
  import { AddressInfo } from 'net';
22
22
  import { promises as fs } from 'fs';
23
+ import { existsSync, mkdirSync } from 'fs-extra';
23
24
  import { fork, ForkOptions } from 'child_process';
24
25
  import { DefaultTheme, FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
25
26
  import URI from '../common/uri';
@@ -53,19 +54,13 @@ export interface ElectronMainCommandOptions {
53
54
  */
54
55
  readonly file?: string;
55
56
 
56
- }
57
+ readonly cwd: string;
57
58
 
58
- /**
59
- * Fields related to a launch event.
60
- *
61
- * This kind of event is triggered in two different contexts:
62
- * 1. The app is launched for the first time, `secondInstance` is false.
63
- * 2. The app is already running but user relaunches it, `secondInstance` is true.
64
- */
65
- export interface ElectronMainExecutionParams {
59
+ /**
60
+ * If the app is launched for the first time, `secondInstance` is false.
61
+ * If the app is already running but user relaunches it, `secondInstance` is true.
62
+ */
66
63
  readonly secondInstance: boolean;
67
- readonly argv: string[];
68
- readonly cwd: string;
69
64
  }
70
65
 
71
66
  /**
@@ -171,6 +166,8 @@ export class ElectronMainApplication {
171
166
  @inject(TheiaElectronWindowFactory)
172
167
  protected readonly windowFactory: TheiaElectronWindowFactory;
173
168
 
169
+ protected isPortable = this.makePortable();
170
+
174
171
  protected readonly electronStore = new Storage<{
175
172
  windowstate?: TheiaBrowserWindowOptions
176
173
  }>();
@@ -194,24 +191,59 @@ export class ElectronMainApplication {
194
191
  return this._config;
195
192
  }
196
193
 
194
+ protected makePortable(): boolean {
195
+ const dataFolderPath = path.join(app.getAppPath(), 'data');
196
+ const appDataPath = path.join(dataFolderPath, 'app-data');
197
+ if (existsSync(dataFolderPath)) {
198
+ if (!existsSync(appDataPath)) {
199
+ mkdirSync(appDataPath);
200
+ }
201
+ app.setPath('userData', appDataPath);
202
+ return true;
203
+ } else {
204
+ return false;
205
+ }
206
+ }
207
+
197
208
  async start(config: FrontendApplicationConfig): Promise<void> {
198
- this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native';
199
- this._config = config;
200
- this.hookApplicationEvents();
201
- this.showInitialWindow();
202
- const port = await this.startBackend();
203
- this._backendPort.resolve(port);
204
- await app.whenReady();
205
- await this.attachElectronSecurityToken(port);
206
- await this.startContributions();
207
- await this.launch({
208
- secondInstance: false,
209
- argv: this.processArgv.getProcessArgvWithoutBin(process.argv),
210
- cwd: process.cwd()
211
- });
209
+ const argv = this.processArgv.getProcessArgvWithoutBin(process.argv);
210
+ createYargs(argv, process.cwd())
211
+ .command('$0 [file]', false,
212
+ cmd => cmd
213
+ .option('electronUserData', {
214
+ type: 'string',
215
+ describe: 'The area where the electron main process puts its data'
216
+ })
217
+ .positional('file', { type: 'string' }),
218
+ async args => {
219
+ if (args.electronUserData) {
220
+ console.info(`using electron user data area : '${args.electronUserData}'`);
221
+ await fs.mkdir(args.electronUserData, { recursive: true });
222
+ app.setPath('userData', args.electronUserData);
223
+ }
224
+ this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native';
225
+ this._config = config;
226
+ this.hookApplicationEvents();
227
+ this.showInitialWindow();
228
+ const port = await this.startBackend();
229
+ this._backendPort.resolve(port);
230
+ await app.whenReady();
231
+ await this.attachElectronSecurityToken(port);
232
+ await this.startContributions();
233
+
234
+ this.handleMainCommand({
235
+ file: args.file,
236
+ cwd: process.cwd(),
237
+ secondInstance: false
238
+ });
239
+ },
240
+ ).parse();
212
241
  }
213
242
 
214
243
  protected getTitleBarStyle(config: FrontendApplicationConfig): 'native' | 'custom' {
244
+ if ('THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS' in process.env && process.env.THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS === '1') {
245
+ return 'custom';
246
+ }
215
247
  if (isOSX) {
216
248
  return 'native';
217
249
  }
@@ -256,7 +288,9 @@ export class ElectronMainApplication {
256
288
  }
257
289
 
258
290
  protected showInitialWindow(): void {
259
- if (this.config.electron.showWindowEarly) {
291
+ if (this.config.electron.showWindowEarly &&
292
+ !('THEIA_ELECTRON_NO_EARLY_WINDOW' in process.env && process.env.THEIA_ELECTRON_NO_EARLY_WINDOW === '1')) {
293
+ console.log('Showing main window early');
260
294
  app.whenReady().then(async () => {
261
295
  const options = await this.getLastWindowOptions();
262
296
  this.initialWindow = await this.createWindow({ ...options });
@@ -265,15 +299,6 @@ export class ElectronMainApplication {
265
299
  }
266
300
  }
267
301
 
268
- protected async launch(params: ElectronMainExecutionParams): Promise<void> {
269
- createYargs(params.argv, params.cwd)
270
- .command('$0 [file]', false,
271
- cmd => cmd
272
- .positional('file', { type: 'string' }),
273
- args => this.handleMainCommand(params, { file: args.file }),
274
- ).parse();
275
- }
276
-
277
302
  /**
278
303
  * Use this rather than creating `BrowserWindow` instances from scratch, since some security parameters need to be set, this method will do it.
279
304
  *
@@ -372,7 +397,7 @@ export class ElectronMainApplication {
372
397
  electronWindow.webContents.setWindowOpenHandler(() => {
373
398
  const { minWidth, minHeight } = this.getDefaultOptions();
374
399
  const options: BrowserWindowConstructorOptions = {
375
- ...this.getDefaultTheiaWindowBounds(),
400
+ ...this.getDefaultTheiaSecondaryWindowBounds(),
376
401
  // We always need the native window frame for now because the secondary window does not have Theia's title bar by default.
377
402
  // In 'custom' title bar mode this would leave the window without any window controls (close, min, max)
378
403
  // TODO set to this.useNativeWindowFrame when secondary windows support a custom title bar.
@@ -399,15 +424,15 @@ export class ElectronMainApplication {
399
424
  app.quit();
400
425
  }
401
426
 
402
- protected async handleMainCommand(params: ElectronMainExecutionParams, options: ElectronMainCommandOptions): Promise<void> {
403
- if (params.secondInstance === false) {
427
+ protected async handleMainCommand(options: ElectronMainCommandOptions): Promise<void> {
428
+ if (options.secondInstance === false) {
404
429
  await this.openWindowWithWorkspace(''); // restore previous workspace.
405
430
  } else if (options.file === undefined) {
406
431
  await this.openDefaultWindow();
407
432
  } else {
408
433
  let workspacePath: string | undefined;
409
434
  try {
410
- workspacePath = await fs.realpath(path.resolve(params.cwd, options.file));
435
+ workspacePath = await fs.realpath(path.resolve(options.cwd, options.file));
411
436
  } catch {
412
437
  console.error(`Could not resolve the workspace path. "${options.file}" is not a valid 'file' option. Falling back to the default workspace location.`);
413
438
  }
@@ -438,6 +463,10 @@ export class ElectronMainApplication {
438
463
  };
439
464
  }
440
465
 
466
+ protected getDefaultTheiaSecondaryWindowBounds(): TheiaBrowserWindowOptions {
467
+ return {};
468
+ }
469
+
441
470
  protected getDefaultTheiaWindowBounds(): TheiaBrowserWindowOptions {
442
471
  // The `screen` API must be required when the application is ready.
443
472
  // See: https://electronjs.org/docs/api/screen#screen
@@ -461,7 +490,7 @@ export class ElectronMainApplication {
461
490
  */
462
491
  protected attachSaveWindowState(electronWindow: BrowserWindow): void {
463
492
  const windowStateListeners = new DisposableCollection();
464
- let delayedSaveTimeout: NodeJS.Timer | undefined;
493
+ let delayedSaveTimeout: NodeJS.Timeout | undefined;
465
494
  const saveWindowStateDelayed = () => {
466
495
  if (delayedSaveTimeout) {
467
496
  clearTimeout(delayedSaveTimeout);
@@ -547,8 +576,8 @@ export class ElectronMainApplication {
547
576
  backendProcess.on('error', error => {
548
577
  reject(error);
549
578
  });
550
- backendProcess.on('exit', () => {
551
- reject(new Error('backend process exited'));
579
+ backendProcess.on('exit', code => {
580
+ reject(code);
552
581
  });
553
582
  app.on('quit', () => {
554
583
  // Only issue a kill signal if the backend process is running.
@@ -622,9 +651,8 @@ export class ElectronMainApplication {
622
651
  if (wrapper) {
623
652
  const listener = wrapper.onDidClose(async () => {
624
653
  listener.dispose();
625
- await this.launch({
654
+ await this.handleMainCommand({
626
655
  secondInstance: false,
627
- argv: this.processArgv.getProcessArgvWithoutBin(process.argv),
628
656
  cwd: process.cwd()
629
657
  });
630
658
  this.restarting = false;
@@ -16,15 +16,15 @@
16
16
 
17
17
  import { WebContents } from '@theia/electron/shared/electron';
18
18
  import { inject, injectable, named, postConstruct } from 'inversify';
19
- import { ContributionProvider } from '../../common/contribution-provider';
20
- import { MessagingContribution } from '../../node/messaging/messaging-contribution';
21
- import { ElectronConnectionHandler } from '../../electron-common/messaging/electron-connection-handler';
22
- import { ElectronMainApplicationContribution } from '../electron-main-application';
23
- import { ElectronMessagingService } from './electron-messaging-service';
19
+ import { ConnectionHandlers } from '../../node/messaging/default-messaging-service';
24
20
  import { AbstractChannel, Channel, ChannelMultiplexer, MessageProvider } from '../../common/message-rpc/channel';
25
- import { ConnectionHandler, Emitter, WriteBuffer } from '../../common';
21
+ import { ConnectionHandler, ContributionProvider, Emitter, WriteBuffer } from '../../common';
26
22
  import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '../../common/message-rpc/uint8-array-message-buffer';
27
23
  import { TheiaRendererAPI } from '../electron-api-main';
24
+ import { MessagingService } from '../../node';
25
+ import { ElectronMessagingService } from './electron-messaging-service';
26
+ import { ElectronConnectionHandler } from './electron-connection-handler';
27
+ import { ElectronMainApplicationContribution } from '../electron-main-application';
28
28
 
29
29
  /**
30
30
  * This component replicates the role filled by `MessagingContribution` but for Electron.
@@ -36,37 +36,54 @@ import { TheiaRendererAPI } from '../electron-api-main';
36
36
 
37
37
  @injectable()
38
38
  export class ElectronMessagingContribution implements ElectronMainApplicationContribution, ElectronMessagingService {
39
-
40
39
  @inject(ContributionProvider) @named(ElectronMessagingService.Contribution)
41
40
  protected readonly messagingContributions: ContributionProvider<ElectronMessagingService.Contribution>;
42
41
 
43
42
  @inject(ContributionProvider) @named(ElectronConnectionHandler)
44
43
  protected readonly connectionHandlers: ContributionProvider<ConnectionHandler>;
45
44
 
46
- protected readonly channelHandlers = new MessagingContribution.ConnectionHandlers<Channel>();
45
+ protected readonly channelHandlers = new ConnectionHandlers<Channel>();
46
+
47
47
  /**
48
48
  * Each electron window has a main channel and its own multiplexer to route multiple client messages the same IPC connection.
49
49
  */
50
- protected readonly windowChannelMultiplexer = new Map<number, { channel: ElectronWebContentChannel, multiplexer: ChannelMultiplexer }>();
50
+ protected readonly openChannels = new Map<number, ElectronWebContentChannel>();
51
51
 
52
52
  @postConstruct()
53
53
  protected init(): void {
54
54
  TheiaRendererAPI.onIpcData((sender, data) => this.handleIpcEvent(sender, data));
55
55
  }
56
56
 
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ ipcChannel(spec: string, callback: (params: any, channel: Channel) => void): void {
59
+ this.channelHandlers.push(spec, callback);
60
+ }
61
+
62
+ onStart(): void {
63
+ for (const contribution of this.messagingContributions.getContributions()) {
64
+ contribution.configure(this);
65
+ }
66
+ for (const connectionHandler of this.connectionHandlers.getContributions()) {
67
+ this.channelHandlers.push(connectionHandler.path, (params, channel) => {
68
+ connectionHandler.onConnection(channel);
69
+ });
70
+ }
71
+ }
72
+
57
73
  protected handleIpcEvent(sender: WebContents, data: Uint8Array): void {
58
74
  // Get the multiplexer for a given window id
59
75
  try {
60
- const windowChannelData = this.windowChannelMultiplexer.get(sender.id) ?? this.createWindowChannelData(sender);
61
- windowChannelData!.channel.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(data));
76
+ const windowChannel = this.openChannels.get(sender.id) ?? this.createWindowChannel(sender);
77
+ windowChannel.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(data));
62
78
  } catch (error) {
63
79
  console.error('IPC: Failed to handle message', { error, data });
64
80
  }
65
81
  }
66
82
 
67
- // Creates a new multiplexer for a given sender/window
68
- protected createWindowChannelData(sender: Electron.WebContents): { channel: ElectronWebContentChannel, multiplexer: ChannelMultiplexer } {
69
- const mainChannel = this.createWindowMainChannel(sender);
83
+ // Creates a new channel for a given sender/window
84
+ protected createWindowChannel(sender: Electron.WebContents): ElectronWebContentChannel {
85
+ const mainChannel = new ElectronWebContentChannel(sender);
86
+
70
87
  const multiplexer = new ChannelMultiplexer(mainChannel);
71
88
  multiplexer.onDidOpenChannel(openEvent => {
72
89
  const { channel, id } = openEvent;
@@ -75,41 +92,26 @@ export class ElectronMessagingContribution implements ElectronMainApplicationCon
75
92
  channel.onClose(() => console.debug(`Closing channel on service path '${id}'.`));
76
93
  }
77
94
  });
78
-
79
- sender.once('did-navigate', () => this.disposeMultiplexer(sender.id, multiplexer, 'Window was refreshed')); // When refreshing the browser window.
80
- sender.once('destroyed', () => this.disposeMultiplexer(sender.id, multiplexer, 'Window was closed')); // When closing the browser window.
81
- const data = { channel: mainChannel, multiplexer };
82
- this.windowChannelMultiplexer.set(sender.id, data);
83
- return data;
84
- }
85
-
86
- /**
87
- * Creates the main channel to a window.
88
- * @param sender The window that the channel should be established to.
89
- */
90
- protected createWindowMainChannel(sender: WebContents): ElectronWebContentChannel {
91
- return new ElectronWebContentChannel(sender);
95
+ sender.once('did-navigate', () => this.deleteChannel(sender.id, 'Window was refreshed'));
96
+ sender.once('destroyed', () => this.deleteChannel(sender.id, 'Window was closed'));
97
+ this.openChannels.set(sender.id, mainChannel);
98
+ return mainChannel;
92
99
  }
93
100
 
94
- protected disposeMultiplexer(windowId: number, multiplexer: ChannelMultiplexer, reason: string): void {
95
- multiplexer.onUnderlyingChannelClose({ reason });
96
- this.windowChannelMultiplexer.delete(windowId);
97
- }
98
-
99
- onStart(): void {
100
- for (const contribution of this.messagingContributions.getContributions()) {
101
- contribution.configure(this);
102
- }
103
- for (const connectionHandler of this.connectionHandlers.getContributions()) {
104
- this.channelHandlers.push(connectionHandler.path, (params, channel) => {
105
- connectionHandler.onConnection(channel);
101
+ protected deleteChannel(senderId: number, reason: string): void {
102
+ const channel = this.openChannels.get(senderId);
103
+ if (channel) {
104
+ this.openChannels.delete(senderId);
105
+ channel.onCloseEmitter.fire({
106
+ reason: reason
106
107
  });
107
108
  }
108
109
  }
109
110
 
110
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
- ipcChannel(spec: string, callback: (params: any, channel: Channel) => void): void {
112
- this.channelHandlers.push(spec, callback);
111
+ protected readonly wsHandlers = new ConnectionHandlers();
112
+
113
+ registerConnectionHandler(spec: string, callback: (params: MessagingService.PathParams, channel: Channel) => void): void {
114
+ this.wsHandlers.push(spec, callback);
113
115
  }
114
116
  }
115
117
 
@@ -23,6 +23,7 @@ export interface ElectronMessagingService {
23
23
  */
24
24
  ipcChannel(path: string, callback: (params: ElectronMessagingService.PathParams, socket: Channel) => void): void;
25
25
  }
26
+
26
27
  export namespace ElectronMessagingService {
27
28
  export interface PathParams {
28
29
  [name: string]: string
@@ -129,8 +129,9 @@ export class TheiaElectronWindow {
129
129
  }, this.toDispose);
130
130
  }
131
131
 
132
- protected doCloseWindow(): void {
132
+ protected async doCloseWindow(): Promise<void> {
133
133
  this.closeIsConfirmed = true;
134
+ await TheiaRendererAPI.sendAboutToClose(this._window.webContents);
134
135
  this._window.close();
135
136
  }
136
137
 
@@ -139,13 +140,13 @@ export class TheiaElectronWindow {
139
140
  }
140
141
 
141
142
  protected reload(): void {
142
- this.handleStopRequest(() => {
143
+ this.handleStopRequest(async () => {
143
144
  this.applicationState = 'init';
144
145
  this._window.reload();
145
146
  }, StopReason.Reload);
146
147
  }
147
148
 
148
- protected async handleStopRequest(onSafeCallback: () => unknown, reason: StopReason): Promise<boolean> {
149
+ protected async handleStopRequest(onSafeCallback: () => Promise<unknown>, reason: StopReason): Promise<boolean> {
149
150
  // Only confirm close to windows that have loaded our frontend.
150
151
  // Both the windows's URL and the FS path of the `index.html` should be converted to the "same" format to be able to compare them. (#11226)
151
152
  // Notes:
@@ -170,6 +170,8 @@ export class BackendApplication {
170
170
  @inject(Stopwatch)
171
171
  protected readonly stopwatch: Stopwatch;
172
172
 
173
+ private _configured: Promise<void>;
174
+
173
175
  constructor(
174
176
  @inject(ContributionProvider) @named(BackendApplicationContribution)
175
177
  protected readonly contributionsProvider: ContributionProvider<BackendApplicationContribution>,
@@ -198,7 +200,7 @@ export class BackendApplication {
198
200
  }
199
201
 
200
202
  protected async initialize(): Promise<void> {
201
- for (const contribution of this.contributionsProvider.getContributions()) {
203
+ await Promise.all(this.contributionsProvider.getContributions().map(async contribution => {
202
204
  if (contribution.initialize) {
203
205
  try {
204
206
  await this.measure(contribution.constructor.name + '.initialize',
@@ -208,18 +210,20 @@ export class BackendApplication {
208
210
  console.error('Could not initialize contribution', error);
209
211
  }
210
212
  }
211
- }
213
+ }));
214
+ }
215
+
216
+ get configured(): Promise<void> {
217
+ return this._configured;
212
218
  }
213
219
 
214
220
  @postConstruct()
215
221
  protected init(): void {
216
- this.configure();
222
+ this._configured = this.configure();
217
223
  }
218
224
 
219
225
  protected async configure(): Promise<void> {
220
- // Do not await the initialization because contributions are expected to handle
221
- // concurrent initialize/configure in undefined order if they provide both
222
- this.initialize();
226
+ await this.initialize();
223
227
 
224
228
  this.app.get('*.js', this.serveGzipped.bind(this, 'text/javascript'));
225
229
  this.app.get('*.js.map', this.serveGzipped.bind(this, 'application/json'));
@@ -233,17 +237,16 @@ export class BackendApplication {
233
237
  this.app.get('*.woff', this.serveGzipped.bind(this, 'font/woff'));
234
238
  this.app.get('*.woff2', this.serveGzipped.bind(this, 'font/woff2'));
235
239
 
236
- for (const contribution of this.contributionsProvider.getContributions()) {
240
+ await Promise.all(this.contributionsProvider.getContributions().map(async contribution => {
237
241
  if (contribution.configure) {
238
242
  try {
239
- await this.measure(contribution.constructor.name + '.configure',
240
- () => contribution.configure!(this.app)
241
- );
243
+ await contribution.configure!(this.app);
242
244
  } catch (error) {
243
245
  console.error('Could not configure contribution', error);
244
246
  }
245
247
  }
246
- }
248
+ }));
249
+ console.info('configured all backend app contributions');
247
250
  }
248
251
 
249
252
  use(...handlers: express.Handler[]): void {
@@ -44,7 +44,7 @@ describe('CliManager', () => {
44
44
  value.resolve(args['foo'] as string);
45
45
  }
46
46
  });
47
- await manager.initializeCli(['-f', 'bla']);
47
+ await manager.initializeCli(['-f', 'bla'], () => Promise.resolve(), () => Promise.resolve());
48
48
  chai.assert.equal(await value.promise, 'bla');
49
49
  });
50
50
 
@@ -59,14 +59,14 @@ describe('CliManager', () => {
59
59
  value.resolve(args['bar'] as string);
60
60
  }
61
61
  });
62
- await manager.initializeCli(['--foo']);
62
+ await manager.initializeCli(['--foo'], () => Promise.resolve(), () => Promise.resolve());
63
63
  chai.assert.equal(await value.promise, 'my-default');
64
64
  });
65
65
 
66
66
  it('prints help and exits', async () =>
67
67
  assertExits(async () => {
68
68
  const manager = new TestCliManager();
69
- await manager.initializeCli(['--help']);
69
+ await manager.initializeCli(['--help'], () => Promise.resolve(), () => Promise.resolve());
70
70
  })
71
71
  );
72
72
  });
package/src/node/cli.ts CHANGED
@@ -35,7 +35,7 @@ export class CliManager {
35
35
  constructor(@inject(ContributionProvider) @named(CliContribution)
36
36
  protected readonly contributionsProvider: ContributionProvider<CliContribution>) { }
37
37
 
38
- async initializeCli(argv: string[]): Promise<void> {
38
+ async initializeCli<T>(argv: string[], postSetArguments: () => Promise<void>, defaultCommand: () => Promise<void>): Promise<void> {
39
39
  const pack = require('../../package.json');
40
40
  const version = pack.version;
41
41
  const command = yargs.version(version);
@@ -43,14 +43,18 @@ export class CliManager {
43
43
  for (const contrib of this.contributionsProvider.getContributions()) {
44
44
  contrib.configure(command);
45
45
  }
46
- const args = command
46
+ await command
47
47
  .detectLocale(false)
48
48
  .showHelpOnFail(false, 'Specify --help for available options')
49
49
  .help('help')
50
+ .middleware(async args => {
51
+ for (const contrib of this.contributionsProvider.getContributions()) {
52
+ await contrib.setArguments(args);
53
+ }
54
+ await postSetArguments();
55
+ })
56
+ .command('$0', false, () => { }, defaultCommand)
50
57
  .parse(argv);
51
- for (const contrib of this.contributionsProvider.getContributions()) {
52
- await contrib.setArguments(args);
53
- }
54
58
  }
55
59
 
56
60
  protected isExit(): boolean {