@theia/core 1.48.3 → 1.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +5 -2
  3. package/i18n/nls.de.json +5 -2
  4. package/i18n/nls.es.json +5 -2
  5. package/i18n/nls.fr.json +5 -2
  6. package/i18n/nls.hu.json +5 -2
  7. package/i18n/nls.it.json +5 -2
  8. package/i18n/nls.ja.json +5 -2
  9. package/i18n/nls.json +5 -2
  10. package/i18n/nls.pl.json +5 -2
  11. package/i18n/nls.pt-br.json +5 -2
  12. package/i18n/nls.pt-pt.json +5 -2
  13. package/i18n/nls.ru.json +5 -2
  14. package/i18n/nls.zh-cn.json +5 -2
  15. package/lib/browser/command-open-handler.js +1 -1
  16. package/lib/browser/command-open-handler.js.map +1 -1
  17. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  18. package/lib/browser/frontend-application-module.js +2 -0
  19. package/lib/browser/frontend-application-module.js.map +1 -1
  20. package/lib/browser/index.d.ts +1 -0
  21. package/lib/browser/index.d.ts.map +1 -1
  22. package/lib/browser/index.js +1 -0
  23. package/lib/browser/index.js.map +1 -1
  24. package/lib/browser/open-with-service.d.ts +44 -0
  25. package/lib/browser/open-with-service.d.ts.map +1 -0
  26. package/lib/browser/open-with-service.js +66 -0
  27. package/lib/browser/open-with-service.js.map +1 -0
  28. package/lib/browser/shell/view-contribution.d.ts.map +1 -1
  29. package/lib/browser/shell/view-contribution.js +2 -1
  30. package/lib/browser/shell/view-contribution.js.map +1 -1
  31. package/lib/common/command.d.ts +4 -0
  32. package/lib/common/command.d.ts.map +1 -1
  33. package/lib/common/command.js.map +1 -1
  34. package/lib/common/event.d.ts +5 -0
  35. package/lib/common/event.d.ts.map +1 -1
  36. package/lib/common/event.js +14 -1
  37. package/lib/common/event.js.map +1 -1
  38. package/lib/electron-browser/preload.d.ts.map +1 -1
  39. package/lib/electron-browser/preload.js +3 -0
  40. package/lib/electron-browser/preload.js.map +1 -1
  41. package/lib/electron-common/electron-api.d.ts +2 -0
  42. package/lib/electron-common/electron-api.d.ts.map +1 -1
  43. package/lib/electron-common/electron-api.js +2 -1
  44. package/lib/electron-common/electron-api.js.map +1 -1
  45. package/lib/electron-main/electron-api-main.d.ts.map +1 -1
  46. package/lib/electron-main/electron-api-main.js +3 -0
  47. package/lib/electron-main/electron-api-main.js.map +1 -1
  48. package/lib/electron-main/electron-main-application.d.ts +17 -1
  49. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  50. package/lib/electron-main/electron-main-application.js +83 -8
  51. package/lib/electron-main/electron-main-application.js.map +1 -1
  52. package/lib/electron-main/theia-electron-window.d.ts +6 -0
  53. package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
  54. package/lib/electron-main/theia-electron-window.js +3 -1
  55. package/lib/electron-main/theia-electron-window.js.map +1 -1
  56. package/lib/node/application-server.js +3 -3
  57. package/lib/node/application-server.js.map +1 -1
  58. package/lib/node/backend-application-module.d.ts.map +1 -1
  59. package/lib/node/backend-application-module.js +1 -4
  60. package/lib/node/backend-application-module.js.map +1 -1
  61. package/lib/node/backend-application.d.ts +6 -3
  62. package/lib/node/backend-application.d.ts.map +1 -1
  63. package/lib/node/backend-application.js +10 -18
  64. package/lib/node/backend-application.js.map +1 -1
  65. package/lib/node/env-variables/env-variables-server.d.ts.map +1 -1
  66. package/lib/node/env-variables/env-variables-server.js +2 -4
  67. package/lib/node/env-variables/env-variables-server.js.map +1 -1
  68. package/package.json +6 -6
  69. package/src/browser/command-open-handler.ts +1 -1
  70. package/src/browser/frontend-application-module.ts +3 -0
  71. package/src/browser/index.ts +1 -0
  72. package/src/browser/open-with-service.ts +93 -0
  73. package/src/browser/shell/view-contribution.ts +3 -2
  74. package/src/common/command.ts +4 -0
  75. package/src/common/event.ts +18 -0
  76. package/src/electron-browser/preload.ts +4 -1
  77. package/src/electron-common/electron-api.ts +2 -0
  78. package/src/electron-main/electron-api-main.ts +6 -1
  79. package/src/electron-main/electron-main-application.ts +101 -11
  80. package/src/electron-main/theia-electron-window.ts +9 -1
  81. package/src/node/application-server.ts +3 -3
  82. package/src/node/backend-application-module.ts +2 -5
  83. package/src/node/backend-application.ts +10 -18
  84. package/src/node/env-variables/env-variables-server.ts +2 -4
@@ -18,7 +18,7 @@ import { injectable, inject, interfaces, optional } from 'inversify';
18
18
  import { Widget } from '@phosphor/widgets';
19
19
  import {
20
20
  MenuModelRegistry, Command, CommandContribution,
21
- MenuContribution, CommandRegistry
21
+ MenuContribution, CommandRegistry, nls
22
22
  } from '../../common';
23
23
  import { KeybindingContribution, KeybindingRegistry } from '../keybinding';
24
24
  import { WidgetManager } from '../widget-manager';
@@ -69,7 +69,8 @@ export abstract class AbstractViewContribution<T extends Widget> implements Comm
69
69
  if (options.toggleCommandId) {
70
70
  this.toggleCommand = {
71
71
  id: options.toggleCommandId,
72
- label: 'Toggle ' + this.viewLabel + ' View'
72
+ category: nls.localizeByDefault('View'),
73
+ label: nls.localizeByDefault('Toggle {0}', this.viewLabel)
73
74
  };
74
75
  }
75
76
  }
@@ -41,6 +41,10 @@ export interface Command {
41
41
  * An icon class of this command.
42
42
  */
43
43
  iconClass?: string;
44
+ /**
45
+ * A short title used for display in menus.
46
+ */
47
+ shortTitle?: string;
44
48
  /**
45
49
  * A category of this command.
46
50
  */
@@ -467,3 +467,21 @@ export class AsyncEmitter<T extends WaitUntilEvent> extends Emitter<T> {
467
467
  }
468
468
 
469
469
  }
470
+
471
+ export class QueueableEmitter<T> extends Emitter<T[]> {
472
+
473
+ currentQueue?: T[];
474
+
475
+ queue(...arg: T[]): void {
476
+ if (!this.currentQueue) {
477
+ this.currentQueue = [];
478
+ }
479
+ this.currentQueue.push(...arg);
480
+ }
481
+
482
+ override fire(): void {
483
+ super.fire(this.currentQueue || []);
484
+ this.currentQueue = undefined;
485
+ }
486
+
487
+ }
@@ -26,7 +26,7 @@ import {
26
26
  CHANNEL_IS_FULL_SCREEN, CHANNEL_SET_MENU_BAR_VISIBLE, CHANNEL_REQUEST_CLOSE, CHANNEL_SET_TITLE_STYLE, CHANNEL_RESTART,
27
27
  CHANNEL_REQUEST_RELOAD, CHANNEL_APP_STATE_CHANGED, CHANNEL_SHOW_ITEM_IN_FOLDER, CHANNEL_READ_CLIPBOARD, CHANNEL_WRITE_CLIPBOARD,
28
28
  CHANNEL_KEYBOARD_LAYOUT_CHANGED, CHANNEL_IPC_CONNECTION, InternalMenuDto, CHANNEL_REQUEST_SECONDARY_CLOSE, CHANNEL_SET_BACKGROUND_COLOR,
29
- CHANNEL_WC_METADATA, CHANNEL_ABOUT_TO_CLOSE
29
+ CHANNEL_WC_METADATA, CHANNEL_ABOUT_TO_CLOSE, CHANNEL_OPEN_WITH_SYSTEM_APP
30
30
  } from '../electron-common/electron-api';
31
31
 
32
32
  // eslint-disable-next-line import/no-extraneous-dependencies
@@ -79,6 +79,9 @@ const api: TheiaCoreAPI = {
79
79
  showItemInFolder: fsPath => {
80
80
  ipcRenderer.send(CHANNEL_SHOW_ITEM_IN_FOLDER, fsPath);
81
81
  },
82
+ openWithSystemApp: fsPath => {
83
+ ipcRenderer.send(CHANNEL_OPEN_WITH_SYSTEM_APP, fsPath);
84
+ },
82
85
  attachSecurityToken: (endpoint: string) => ipcRenderer.invoke(CHANNEL_ATTACH_SECURITY_TOKEN, endpoint),
83
86
 
84
87
  popup: async function (menu: MenuDto[], x: number, y: number, onClosed: () => void, windowName?: string): Promise<number> {
@@ -56,6 +56,7 @@ export interface TheiaCoreAPI {
56
56
  focusWindow(name?: string): void;
57
57
 
58
58
  showItemInFolder(fsPath: string): void;
59
+ openWithSystemApp(fsPath: string): void;
59
60
 
60
61
  getTitleBarStyleAtStartup(): Promise<string>;
61
62
  setTitleBarStyle(style: string): void;
@@ -112,6 +113,7 @@ export const CHANNEL_FOCUS_WINDOW = 'FocusWindow';
112
113
  export const CHANNEL_SHOW_OPEN = 'ShowOpenDialog';
113
114
  export const CHANNEL_SHOW_SAVE = 'ShowSaveDialog';
114
115
  export const CHANNEL_SHOW_ITEM_IN_FOLDER = 'ShowItemInFolder';
116
+ export const CHANNEL_OPEN_WITH_SYSTEM_APP = 'OpenWithSystemApp';
115
117
  export const CHANNEL_ATTACH_SECURITY_TOKEN = 'AttachSecurityToken';
116
118
 
117
119
  export const CHANNEL_GET_TITLE_STYLE_AT_STARTUP = 'GetTitleStyleAtStartup';
@@ -53,7 +53,8 @@ import {
53
53
  CHANNEL_REQUEST_SECONDARY_CLOSE,
54
54
  CHANNEL_SET_BACKGROUND_COLOR,
55
55
  CHANNEL_WC_METADATA,
56
- CHANNEL_ABOUT_TO_CLOSE
56
+ CHANNEL_ABOUT_TO_CLOSE,
57
+ CHANNEL_OPEN_WITH_SYSTEM_APP
57
58
  } from '../electron-common/electron-api';
58
59
  import { ElectronMainApplication, ElectronMainApplicationContribution } from './electron-main-application';
59
60
  import { Disposable, DisposableCollection, isOSX, MaybePromise } from '../common';
@@ -164,6 +165,10 @@ export class TheiaMainApi implements ElectronMainApplicationContribution {
164
165
  shell.showItemInFolder(fsPath);
165
166
  });
166
167
 
168
+ ipcMain.on(CHANNEL_OPEN_WITH_SYSTEM_APP, (event, fsPath) => {
169
+ shell.openPath(fsPath);
170
+ });
171
+
167
172
  ipcMain.handle(CHANNEL_GET_TITLE_STYLE_AT_STARTUP, event => application.getTitleBarStyleAtStartup(event.sender));
168
173
 
169
174
  ipcMain.on(CHANNEL_SET_TITLE_STYLE, (event, style) => application.setTitleBarStyle(event.sender, style));
@@ -22,16 +22,16 @@ import { AddressInfo } from 'net';
22
22
  import { promises as fs } from 'fs';
23
23
  import { existsSync, mkdirSync } from 'fs-extra';
24
24
  import { fork, ForkOptions } from 'child_process';
25
- import { DefaultTheme, FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
25
+ import { DefaultTheme, ElectronFrontendApplicationConfig, FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
26
26
  import URI from '../common/uri';
27
27
  import { FileUri } from '../common/file-uri';
28
- import { Deferred } from '../common/promise-util';
28
+ import { Deferred, timeout } from '../common/promise-util';
29
29
  import { MaybePromise } from '../common/types';
30
30
  import { ContributionProvider } from '../common/contribution-provider';
31
31
  import { ElectronSecurityTokenService } from './electron-security-token-service';
32
32
  import { ElectronSecurityToken } from '../electron-common/electron-token';
33
33
  import Storage = require('electron-store');
34
- import { Disposable, DisposableCollection, isOSX, isWindows } from '../common';
34
+ import { CancellationTokenSource, Disposable, DisposableCollection, isOSX, isWindows } from '../common';
35
35
  import { DEFAULT_WINDOW_HASH, WindowSearchParams } from '../common/window';
36
36
  import { TheiaBrowserWindowOptions, TheiaElectronWindow, TheiaElectronWindowFactory } from './theia-electron-window';
37
37
  import { ElectronMainApplicationGlobals } from './electron-main-constants';
@@ -182,6 +182,7 @@ export class ElectronMainApplication {
182
182
  protected windows = new Map<number, TheiaElectronWindow>();
183
183
  protected restarting = false;
184
184
 
185
+ /** Used to temporarily store the reference to an early created main window */
185
186
  protected initialWindow?: BrowserWindow;
186
187
 
187
188
  get config(): FrontendApplicationConfig {
@@ -287,18 +288,110 @@ export class ElectronMainApplication {
287
288
  return this.didUseNativeWindowFrameOnStart.get(webContents.id) ? 'native' : 'custom';
288
289
  }
289
290
 
291
+ protected async determineSplashScreenBounds(initialWindowBounds: { x: number, y: number, width: number, height: number }):
292
+ Promise<{ x: number, y: number, width: number, height: number }> {
293
+ const splashScreenOptions = this.getSplashScreenOptions();
294
+ const width = splashScreenOptions?.width ?? 640;
295
+ const height = splashScreenOptions?.height ?? 480;
296
+
297
+ // determine the screen on which to show the splash screen via the center of the window to show
298
+ const windowCenterPoint = { x: initialWindowBounds.x + (initialWindowBounds.width / 2), y: initialWindowBounds.y + (initialWindowBounds.height / 2) };
299
+ const { bounds } = screen.getDisplayNearestPoint(windowCenterPoint);
300
+
301
+ // place splash screen center of screen
302
+ const screenCenterPoint = { x: bounds.x + (bounds.width / 2), y: bounds.y + (bounds.height / 2) };
303
+ const x = screenCenterPoint.x - (width / 2);
304
+ const y = screenCenterPoint.y - (height / 2);
305
+
306
+ return {
307
+ x, y, width, height
308
+ };
309
+ }
310
+
311
+ protected isShowWindowEarly(): boolean {
312
+ return !!this.config.electron.showWindowEarly &&
313
+ !('THEIA_ELECTRON_NO_EARLY_WINDOW' in process.env && process.env.THEIA_ELECTRON_NO_EARLY_WINDOW === '1');
314
+ }
315
+
290
316
  protected showInitialWindow(): void {
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');
317
+ if (this.isShowWindowEarly() || this.isShowSplashScreen()) {
294
318
  app.whenReady().then(async () => {
295
319
  const options = await this.getLastWindowOptions();
320
+ // If we want to show a splash screen, don't auto open the main window
321
+ if (this.isShowSplashScreen()) {
322
+ options.preventAutomaticShow = true;
323
+ }
296
324
  this.initialWindow = await this.createWindow({ ...options });
297
- this.initialWindow.show();
325
+
326
+ if (this.isShowSplashScreen()) {
327
+ console.log('Showing splash screen');
328
+ this.configureAndShowSplashScreen(this.initialWindow);
329
+ }
330
+
331
+ // Show main window early if windows shall be shown early and splash screen is not configured
332
+ if (this.isShowWindowEarly() && !this.isShowSplashScreen()) {
333
+ console.log('Showing main window early');
334
+ this.initialWindow.show();
335
+ }
298
336
  });
299
337
  }
300
338
  }
301
339
 
340
+ protected async configureAndShowSplashScreen(mainWindow: BrowserWindow): Promise<BrowserWindow> {
341
+ const splashScreenOptions = this.getSplashScreenOptions()!;
342
+ console.debug('SplashScreen options', splashScreenOptions);
343
+
344
+ const splashScreenBounds = await this.determineSplashScreenBounds(mainWindow.getBounds());
345
+ const splashScreenWindow = new BrowserWindow({
346
+ ...splashScreenBounds,
347
+ frame: false,
348
+ alwaysOnTop: true,
349
+ show: false
350
+ });
351
+
352
+ if (this.isShowWindowEarly()) {
353
+ console.log('Showing splash screen early');
354
+ splashScreenWindow.show();
355
+ } else {
356
+ splashScreenWindow.on('ready-to-show', () => {
357
+ splashScreenWindow.show();
358
+ });
359
+ }
360
+
361
+ splashScreenWindow.loadFile(path.resolve(this.globals.THEIA_APP_PROJECT_PATH, splashScreenOptions.content!).toString());
362
+
363
+ // close splash screen and show main window once frontend is ready or a timeout is hit
364
+ const cancelTokenSource = new CancellationTokenSource();
365
+ const minTime = timeout(splashScreenOptions.minDuration ?? 0, cancelTokenSource.token);
366
+ const maxTime = timeout(splashScreenOptions.maxDuration ?? 30000, cancelTokenSource.token);
367
+
368
+ const showWindowAndCloseSplashScreen = () => {
369
+ cancelTokenSource.cancel();
370
+ if (!mainWindow.isVisible()) {
371
+ mainWindow.show();
372
+ }
373
+ splashScreenWindow.close();
374
+ };
375
+ TheiaRendererAPI.onApplicationStateChanged(mainWindow.webContents, state => {
376
+ if (state === 'ready') {
377
+ minTime.then(() => showWindowAndCloseSplashScreen());
378
+ }
379
+ });
380
+ maxTime.then(() => showWindowAndCloseSplashScreen());
381
+ return splashScreenWindow;
382
+ }
383
+
384
+ protected isShowSplashScreen(): boolean {
385
+ return typeof this.config.electron.splashScreenOptions === 'object' && !!this.config.electron.splashScreenOptions.content;
386
+ }
387
+
388
+ protected getSplashScreenOptions(): ElectronFrontendApplicationConfig.SplashScreenOptions | undefined {
389
+ if (this.isShowSplashScreen()) {
390
+ return this.config.electron.splashScreenOptions;
391
+ }
392
+ return undefined;
393
+ }
394
+
302
395
  /**
303
396
  * Use this rather than creating `BrowserWindow` instances from scratch, since some security parameters need to be set, this method will do it.
304
397
  *
@@ -316,6 +409,7 @@ export class ElectronMainApplication {
316
409
  electronWindow.window.on('focus', () => TheiaRendererAPI.sendWindowEvent(electronWindow.window.webContents, 'focus'));
317
410
  this.attachSaveWindowState(electronWindow.window);
318
411
  this.configureNativeSecondaryWindowCreation(electronWindow.window);
412
+
319
413
  return electronWindow.window;
320
414
  }
321
415
 
@@ -548,10 +642,6 @@ export class ElectronMainApplication {
548
642
  protected async startBackend(): Promise<number> {
549
643
  // Check if we should run everything as one process.
550
644
  const noBackendFork = process.argv.indexOf('--no-cluster') !== -1;
551
- // We cannot use the `process.cwd()` as the application project path (the location of the `package.json` in other words)
552
- // in a bundled electron application because it depends on the way we start it. For instance, on OS X, these are a differences:
553
- // https://github.com/eclipse-theia/theia/issues/3297#issuecomment-439172274
554
- process.env.THEIA_APP_PROJECT_PATH = this.globals.THEIA_APP_PROJECT_PATH;
555
645
  // Set the electron version for both the dev and the production mode. (https://github.com/eclipse-theia/theia/issues/3254)
556
646
  // Otherwise, the forked backend processes will not know that they're serving the electron frontend.
557
647
  process.env.THEIA_ELECTRON_VERSION = process.versions.electron;
@@ -37,6 +37,12 @@ export interface TheiaBrowserWindowOptions extends BrowserWindowConstructorOptio
37
37
  * in which case we want to invalidate the stored options and use the default options instead.
38
38
  */
39
39
  screenLayout?: string;
40
+ /**
41
+ * By default, the window will be shown as soon as the content is ready to render.
42
+ * This can be prevented by handing over preventAutomaticShow: `true`.
43
+ * Use this for fine-grained control over when to show the window, e.g. to coordinate with a splash screen.
44
+ */
45
+ preventAutomaticShow?: boolean;
40
46
  }
41
47
 
42
48
  export const TheiaBrowserWindowOptions = Symbol('TheiaBrowserWindowOptions');
@@ -76,7 +82,9 @@ export class TheiaElectronWindow {
76
82
  protected init(): void {
77
83
  this._window = new BrowserWindow(this.options);
78
84
  this._window.setMenuBarVisibility(false);
79
- this.attachReadyToShow();
85
+ if (!this.options.preventAutomaticShow) {
86
+ this.attachReadyToShow();
87
+ }
80
88
  this.restoreMaximizedState();
81
89
  this.attachCloseListeners();
82
90
  this.trackApplicationState();
@@ -26,9 +26,9 @@ export class ApplicationServerImpl implements ApplicationServer {
26
26
  protected readonly applicationPackage: ApplicationPackage;
27
27
 
28
28
  getExtensionsInfos(): Promise<ExtensionInfo[]> {
29
- const extensions = this.applicationPackage.extensionPackages;
30
- const infos: ExtensionInfo[] = extensions.map(extension => ({ name: extension.name, version: extension.version }));
31
- return Promise.resolve(infos);
29
+ // @ts-expect-error
30
+ const appInfo: ExtensionInfo[] = globalThis.extensionInfo;
31
+ return Promise.resolve(appInfo);
32
32
  }
33
33
 
34
34
  getApplicationInfo(): Promise<ApplicationInfo | undefined> {
@@ -21,7 +21,7 @@ import {
21
21
  bindContributionProvider, MessageService, MessageClient, ConnectionHandler, RpcConnectionHandler,
22
22
  CommandService, commandServicePath, messageServicePath, OSBackendProvider, OSBackendProviderPath
23
23
  } from '../common';
24
- import { BackendApplication, BackendApplicationContribution, BackendApplicationCliContribution, BackendApplicationServer } from './backend-application';
24
+ import { BackendApplication, BackendApplicationContribution, BackendApplicationCliContribution, BackendApplicationServer, BackendApplicationPath } from './backend-application';
25
25
  import { CliManager, CliContribution } from './cli';
26
26
  import { IPCConnectionProvider } from './messaging';
27
27
  import { ApplicationServerImpl } from './application-server';
@@ -101,10 +101,7 @@ export const backendApplicationModule = new ContainerModule(bind => {
101
101
  })
102
102
  ).inSingletonScope();
103
103
 
104
- bind(ApplicationPackage).toDynamicValue(({ container }) => {
105
- const { projectPath } = container.get(BackendApplicationCliContribution);
106
- return new ApplicationPackage({ projectPath });
107
- }).inSingletonScope();
104
+ bind(ApplicationPackage).toConstantValue(new ApplicationPackage({ projectPath: BackendApplicationPath }));
108
105
 
109
106
  bind(WsRequestValidator).toSelf().inSingletonScope();
110
107
  bindContributionProvider(bind, WsRequestValidatorContribution);
@@ -27,9 +27,14 @@ import { CliContribution } from './cli';
27
27
  import { Deferred } from '../common/promise-util';
28
28
  import { environment } from '../common/index';
29
29
  import { AddressInfo } from 'net';
30
- import { ApplicationPackage } from '@theia/application-package';
31
30
  import { ProcessUtils } from './process-utils';
32
31
 
32
+ /**
33
+ * The path to the application project directory. This is the directory where the application code is located.
34
+ * Mostly contains the `package.json` file and the `lib` directory.
35
+ */
36
+ export const BackendApplicationPath = process.env.THEIA_APP_PROJECT_PATH || process.cwd();
37
+
33
38
  export type DnsResultOrder = 'ipv4first' | 'verbatim' | 'nodeDefault';
34
39
 
35
40
  const APP_PROJECT_PATH = 'app-project-path';
@@ -115,7 +120,8 @@ export class BackendApplicationCliContribution implements CliContribution {
115
120
  ssl: boolean | undefined;
116
121
  cert: string | undefined;
117
122
  certkey: string | undefined;
118
- projectPath: string;
123
+ /** @deprecated Use the `BackendApplicationPath` constant or `process.env.THEIA_APP_PROJECT_PATH` environment variable instead */
124
+ projectPath = BackendApplicationPath;
119
125
 
120
126
  configure(conf: yargs.Argv): void {
121
127
  conf.option('port', { alias: 'p', description: 'The port the backend server listens on.', type: 'number', default: DEFAULT_PORT });
@@ -123,7 +129,7 @@ export class BackendApplicationCliContribution implements CliContribution {
123
129
  conf.option('ssl', { description: 'Use SSL (HTTPS), cert and certkey must also be set', type: 'boolean', default: DEFAULT_SSL });
124
130
  conf.option('cert', { description: 'Path to SSL certificate.', type: 'string' });
125
131
  conf.option('certkey', { description: 'Path to SSL certificate key.', type: 'string' });
126
- conf.option(APP_PROJECT_PATH, { description: 'Sets the application project directory', default: this.appProjectPath() });
132
+ conf.option(APP_PROJECT_PATH, { description: 'Sets the application project directory', deprecated: true });
127
133
  conf.option('dnsDefaultResultOrder', {
128
134
  type: 'string',
129
135
  description: 'Configure Node\'s DNS resolver default behavior, see https://nodejs.org/docs/latest-v18.x/api/dns.html#dnssetdefaultresultorderorder',
@@ -138,19 +144,8 @@ export class BackendApplicationCliContribution implements CliContribution {
138
144
  this.ssl = args.ssl as boolean;
139
145
  this.cert = args.cert as string;
140
146
  this.certkey = args.certkey as string;
141
- this.projectPath = args[APP_PROJECT_PATH] as string;
142
147
  this.dnsDefaultResultOrder = args.dnsDefaultResultOrder as DnsResultOrder;
143
148
  }
144
-
145
- protected appProjectPath(): string {
146
- if (environment.electron.is()) {
147
- if (process.env.THEIA_APP_PROJECT_PATH) {
148
- return process.env.THEIA_APP_PROJECT_PATH;
149
- }
150
- throw new Error('The \'THEIA_APP_PROJECT_PATH\' environment variable must be set when running in electron.');
151
- }
152
- return process.cwd();
153
- }
154
149
  }
155
150
 
156
151
  /**
@@ -161,9 +156,6 @@ export class BackendApplication {
161
156
 
162
157
  protected readonly app: express.Application = express();
163
158
 
164
- @inject(ApplicationPackage)
165
- protected readonly applicationPackage: ApplicationPackage;
166
-
167
159
  @inject(ProcessUtils)
168
160
  protected readonly processUtils: ProcessUtils;
169
161
 
@@ -352,7 +344,7 @@ export class BackendApplication {
352
344
  const acceptedEncodings = req.acceptsEncodings();
353
345
 
354
346
  const gzUrl = `${req.url}.gz`;
355
- const gzPath = path.join(this.applicationPackage.projectPath, 'lib', 'frontend', gzUrl);
347
+ const gzPath = path.join(BackendApplicationPath, 'lib', 'frontend', gzUrl);
356
348
  if (acceptedEncodings.indexOf('gzip') === -1 || !(await fs.pathExists(gzPath))) {
357
349
  next();
358
350
  return;
@@ -22,6 +22,7 @@ import { pathExists, mkdir } from 'fs-extra';
22
22
  import { EnvVariable, EnvVariablesServer } from '../../common/env-variables';
23
23
  import { isWindows } from '../../common/os';
24
24
  import { FileUri } from '../../common/file-uri';
25
+ import { BackendApplicationPath } from '../backend-application';
25
26
 
26
27
  @injectable()
27
28
  export class EnvVariablesServerImpl implements EnvVariablesServer {
@@ -45,10 +46,7 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
45
46
  }
46
47
 
47
48
  protected async createConfigDirUri(): Promise<string> {
48
- let dataFolderPath: string = '';
49
- if (process.env.THEIA_APP_PROJECT_PATH) {
50
- dataFolderPath = join(process.env.THEIA_APP_PROJECT_PATH, 'data');
51
- }
49
+ const dataFolderPath = join(BackendApplicationPath, 'data');
52
50
  const userDataPath = join(dataFolderPath, 'user-data');
53
51
  const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath);
54
52
  if (dataFolderExists) {