diff --git a/dev-packages/application-manager/src/generator/backend-generator.ts b/dev-packages/application-manager/src/generator/backend-generator.ts index a5df1bdb80b46..fd47708a0d3af 100644 --- a/dev-packages/application-manager/src/generator/backend-generator.ts +++ b/dev-packages/application-manager/src/generator/backend-generator.ts @@ -52,10 +52,12 @@ if (process.env.LC_ALL) { } process.env.LC_NUMERIC = 'C'; +const { resolve } = require('path'); +const theiaAppProjectPath = resolve(__dirname, '..', '..'); +process.env.THEIA_APP_PROJECT_PATH = theiaAppProjectPath; const { default: electronMainApplicationModule } = require('@theia/core/lib/electron-main/electron-main-application-module'); const { ElectronMainApplication, ElectronMainApplicationGlobals } = require('@theia/core/lib/electron-main/electron-main-application'); const { Container } = require('inversify'); -const { resolve } = require('path'); const { app } = require('electron'); const config = ${this.prettyStringify(this.pck.props.frontend.config)}; @@ -71,7 +73,7 @@ const isSingleInstance = ${this.pck.props.backend.config.singleInstance === true const container = new Container(); container.load(electronMainApplicationModule); container.bind(ElectronMainApplicationGlobals).toConstantValue({ - THEIA_APP_PROJECT_PATH: resolve(__dirname, '..', '..'), + THEIA_APP_PROJECT_PATH: theiaAppProjectPath, THEIA_BACKEND_MAIN_PATH: resolve(__dirname, 'main.js'), THEIA_FRONTEND_HTML_PATH: resolve(__dirname, '..', '..', 'lib', 'frontend', 'index.html'), }); @@ -119,6 +121,7 @@ if ('ELECTRON_RUN_AS_NODE' in process.env) { } const path = require('path'); +process.env.THEIA_APP_PROJECT_PATH = path.resolve(__dirname, '..', '..') const express = require('express'); const { Container } = require('inversify'); const { BackendApplication, BackendApplicationServer, CliManager } = require('@theia/core/lib/node'); diff --git a/packages/core/src/electron-main/electron-main-application.ts b/packages/core/src/electron-main/electron-main-application.ts index 2efa9fce419e2..9c0f410fba9ba 100644 --- a/packages/core/src/electron-main/electron-main-application.ts +++ b/packages/core/src/electron-main/electron-main-application.ts @@ -548,10 +548,6 @@ export class ElectronMainApplication { protected async startBackend(): Promise { // Check if we should run everything as one process. const noBackendFork = process.argv.indexOf('--no-cluster') !== -1; - // We cannot use the `process.cwd()` as the application project path (the location of the `package.json` in other words) - // in a bundled electron application because it depends on the way we start it. For instance, on OS X, these are a differences: - // https://github.com/eclipse-theia/theia/issues/3297#issuecomment-439172274 - process.env.THEIA_APP_PROJECT_PATH = this.globals.THEIA_APP_PROJECT_PATH; // Set the electron version for both the dev and the production mode. (https://github.com/eclipse-theia/theia/issues/3254) // Otherwise, the forked backend processes will not know that they're serving the electron frontend. process.env.THEIA_ELECTRON_VERSION = process.versions.electron; diff --git a/packages/core/src/node/backend-application-module.ts b/packages/core/src/node/backend-application-module.ts index e3461c473b956..a89a7a8a52ea6 100644 --- a/packages/core/src/node/backend-application-module.ts +++ b/packages/core/src/node/backend-application-module.ts @@ -21,7 +21,7 @@ import { bindContributionProvider, MessageService, MessageClient, ConnectionHandler, RpcConnectionHandler, CommandService, commandServicePath, messageServicePath, OSBackendProvider, OSBackendProviderPath } from '../common'; -import { BackendApplication, BackendApplicationContribution, BackendApplicationCliContribution, BackendApplicationServer } from './backend-application'; +import { BackendApplication, BackendApplicationContribution, BackendApplicationCliContribution, BackendApplicationServer, BackendApplicationPath } from './backend-application'; import { CliManager, CliContribution } from './cli'; import { IPCConnectionProvider } from './messaging'; import { ApplicationServerImpl } from './application-server'; @@ -101,10 +101,7 @@ export const backendApplicationModule = new ContainerModule(bind => { }) ).inSingletonScope(); - bind(ApplicationPackage).toDynamicValue(({ container }) => { - const { projectPath } = container.get(BackendApplicationCliContribution); - return new ApplicationPackage({ projectPath }); - }).inSingletonScope(); + bind(ApplicationPackage).toConstantValue(new ApplicationPackage({ projectPath: BackendApplicationPath })); bind(WsRequestValidator).toSelf().inSingletonScope(); bindContributionProvider(bind, WsRequestValidatorContribution); diff --git a/packages/core/src/node/backend-application.ts b/packages/core/src/node/backend-application.ts index a93376955750b..31549abbc5f79 100644 --- a/packages/core/src/node/backend-application.ts +++ b/packages/core/src/node/backend-application.ts @@ -27,9 +27,14 @@ import { CliContribution } from './cli'; import { Deferred } from '../common/promise-util'; import { environment } from '../common/index'; import { AddressInfo } from 'net'; -import { ApplicationPackage } from '@theia/application-package'; import { ProcessUtils } from './process-utils'; +/** + * The path to the application project directory. This is the directory where the application code is located. + * Mostly contains the `package.json` file and the `lib` directory. + */ +export const BackendApplicationPath = process.env.THEIA_APP_PROJECT_PATH || process.cwd(); + export type DnsResultOrder = 'ipv4first' | 'verbatim' | 'nodeDefault'; const APP_PROJECT_PATH = 'app-project-path'; @@ -115,7 +120,8 @@ export class BackendApplicationCliContribution implements CliContribution { ssl: boolean | undefined; cert: string | undefined; certkey: string | undefined; - projectPath: string; + /** @deprecated Use the `BackendApplicationPath` constant or `process.env.THEIA_APP_PROJECT_PATH` environment variable instead */ + projectPath = BackendApplicationPath; configure(conf: yargs.Argv): void { 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 { conf.option('ssl', { description: 'Use SSL (HTTPS), cert and certkey must also be set', type: 'boolean', default: DEFAULT_SSL }); conf.option('cert', { description: 'Path to SSL certificate.', type: 'string' }); conf.option('certkey', { description: 'Path to SSL certificate key.', type: 'string' }); - conf.option(APP_PROJECT_PATH, { description: 'Sets the application project directory', default: this.appProjectPath() }); + conf.option(APP_PROJECT_PATH, { description: 'Sets the application project directory', deprecated: true }); conf.option('dnsDefaultResultOrder', { type: 'string', 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 { this.ssl = args.ssl as boolean; this.cert = args.cert as string; this.certkey = args.certkey as string; - this.projectPath = args[APP_PROJECT_PATH] as string; this.dnsDefaultResultOrder = args.dnsDefaultResultOrder as DnsResultOrder; } - - protected appProjectPath(): string { - if (environment.electron.is()) { - if (process.env.THEIA_APP_PROJECT_PATH) { - return process.env.THEIA_APP_PROJECT_PATH; - } - throw new Error('The \'THEIA_APP_PROJECT_PATH\' environment variable must be set when running in electron.'); - } - return process.cwd(); - } } /** @@ -161,9 +156,6 @@ export class BackendApplication { protected readonly app: express.Application = express(); - @inject(ApplicationPackage) - protected readonly applicationPackage: ApplicationPackage; - @inject(ProcessUtils) protected readonly processUtils: ProcessUtils; @@ -352,7 +344,7 @@ export class BackendApplication { const acceptedEncodings = req.acceptsEncodings(); const gzUrl = `${req.url}.gz`; - const gzPath = path.join(this.applicationPackage.projectPath, 'lib', 'frontend', gzUrl); + const gzPath = path.join(BackendApplicationPath, 'lib', 'frontend', gzUrl); if (acceptedEncodings.indexOf('gzip') === -1 || !(await fs.pathExists(gzPath))) { next(); return; diff --git a/packages/core/src/node/env-variables/env-variables-server.ts b/packages/core/src/node/env-variables/env-variables-server.ts index 7c337992ac90b..57cdf059756fd 100644 --- a/packages/core/src/node/env-variables/env-variables-server.ts +++ b/packages/core/src/node/env-variables/env-variables-server.ts @@ -22,6 +22,7 @@ import { pathExists, mkdir } from 'fs-extra'; import { EnvVariable, EnvVariablesServer } from '../../common/env-variables'; import { isWindows } from '../../common/os'; import { FileUri } from '../../common/file-uri'; +import { BackendApplicationPath } from '../backend-application'; @injectable() export class EnvVariablesServerImpl implements EnvVariablesServer { @@ -45,10 +46,7 @@ export class EnvVariablesServerImpl implements EnvVariablesServer { } protected async createConfigDirUri(): Promise { - let dataFolderPath: string = ''; - if (process.env.THEIA_APP_PROJECT_PATH) { - dataFolderPath = join(process.env.THEIA_APP_PROJECT_PATH, 'data'); - } + const dataFolderPath = join(BackendApplicationPath, 'data'); const userDataPath = join(dataFolderPath, 'user-data'); const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath); if (dataFolderExists) { diff --git a/packages/remote/src/electron-node/setup/remote-copy-contribution.ts b/packages/remote/src/electron-node/setup/remote-copy-contribution.ts index b6db142310ea8..4aecf9e8f0746 100644 --- a/packages/remote/src/electron-node/setup/remote-copy-contribution.ts +++ b/packages/remote/src/electron-node/setup/remote-copy-contribution.ts @@ -61,8 +61,7 @@ export class RemoteCopyRegistry { const globResult = await promiseGlob(pattern, { cwd: projectPath }); - const relativeFiles = globResult.map(file => path.relative(projectPath, file)); - for (const file of relativeFiles) { + for (const file of globResult) { const targetFile = this.withTarget(file, target); this.files.push({ path: file,